[前][次][番号順一覧][スレッド一覧]

ruby-changes:41667

From: naruse <ko1@a...>
Date: Fri, 5 Feb 2016 13:31:27 +0900 (JST)
Subject: [ruby-changes:41667] naruse:r53741 (trunk): * insns.def (opt_mult): Use int128_t for overflow detection.

naruse	2016-02-05 13:31:27 +0900 (Fri, 05 Feb 2016)

  New Revision: 53741

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=53741

  Log:
    * insns.def (opt_mult): Use int128_t for overflow detection.
    
    * bignum.c (rb_uint128t2big): added for opt_mult.
    
    * bignum.c (rb_uint128t2big): added for rb_uint128t2big..
    
    * configure.in: define int128_t, uint128_t and related MACROs.
      Initially introduced by r41379 but reverted by r50749.

  Modified files:
    trunk/ChangeLog
    trunk/bignum.c
    trunk/configure.in
    trunk/insns.def
Index: bignum.c
===================================================================
--- bignum.c	(revision 53740)
+++ bignum.c	(revision 53741)
@@ -4367,6 +4367,46 @@ rb_ll2inum(LONG_LONG n) https://github.com/ruby/ruby/blob/trunk/bignum.c#L4367
 
 #endif  /* HAVE_LONG_LONG */
 
+#ifdef HAVE_INT128_T
+static VALUE
+rb_uint128t2big(uint128_t n)
+{
+    long i;
+    VALUE big = bignew(bdigit_roomof(SIZEOF_INT128_T), 1);
+    BDIGIT *digits = BDIGITS(big);
+
+    for (i = 0; i < bdigit_roomof(SIZEOF_INT128_T); i++) {
+	digits[i] = BIGLO(RSHIFT(n ,BITSPERDIG*i));
+    }
+
+    i = bdigit_roomof(SIZEOF_INT128_T);
+    while (i-- && !digits[i]) ;
+    BIGNUM_SET_LEN(big, i+1);
+    return big;
+}
+
+VALUE
+rb_int128t2big(int128_t n)
+{
+    int neg = 0;
+    uint128_t u;
+    VALUE big;
+
+    if (n < 0) {
+        u = 1 + (uint128_t)(-(n + 1)); /* u = -n avoiding overflow */
+	neg = 1;
+    }
+    else {
+        u = n;
+    }
+    big = rb_uint128t2big(u);
+    if (neg) {
+	BIGNUM_SET_SIGN(big, 0);
+    }
+    return big;
+}
+#endif
+
 VALUE
 rb_cstr2inum(const char *str, int base)
 {
Index: configure.in
===================================================================
--- configure.in	(revision 53740)
+++ configure.in	(revision 53741)
@@ -1472,6 +1472,7 @@ RUBY_CHECK_SIZEOF(short) https://github.com/ruby/ruby/blob/trunk/configure.in#L1472
 RUBY_CHECK_SIZEOF(long, [int], [ILP LP])
 RUBY_CHECK_SIZEOF(long long)
 RUBY_CHECK_SIZEOF(__int64)
+RUBY_CHECK_SIZEOF(__int128)
 RUBY_CHECK_SIZEOF(off_t)
 RUBY_CHECK_SIZEOF(void*, [int long "long long"], [ILP LP LLP])
 RUBY_CHECK_SIZEOF(float)
@@ -2007,6 +2008,7 @@ typedef $1 t; int s = sizeof(t) == 42;]) https://github.com/ruby/ruby/blob/trunk/configure.in#L2008
     ["$ac_cv_sizeof_long"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])long"],
     ["$ac_cv_sizeof_long_long"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])long long"],
     ["$ac_cv_sizeof___int64"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])__int64"],
+    ["$ac_cv_sizeof___int128"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])__int128"],
     [ rb_cv_type_$1=no])])])
 if test "${rb_cv_type_$1}" != no; then
     AC_DEFINE([HAVE_]AS_TR_CPP($1), 1)
@@ -2028,6 +2030,8 @@ RUBY_DEFINT(int32_t, 4) https://github.com/ruby/ruby/blob/trunk/configure.in#L2030
 RUBY_DEFINT(uint32_t, 4, unsigned)
 RUBY_DEFINT(int64_t, 8)
 RUBY_DEFINT(uint64_t, 8, unsigned)
+RUBY_DEFINT(int128_t, 16)
+RUBY_DEFINT(uint128_t, 16, unsigned)
 RUBY_DEFINT(intptr_t, void*)
 RUBY_DEFINT(uintptr_t, void*, unsigned)
 RUBY_DEFINT(ssize_t, size_t, [], [@%:@include <sys/types.h>])	dnl may differ from int, so not use AC_TYPE_SSIZE_T.
Index: insns.def
===================================================================
--- insns.def	(revision 53740)
+++ insns.def	(revision 53741)
@@ -1430,20 +1430,29 @@ opt_mult https://github.com/ruby/ruby/blob/trunk/insns.def#L1430
 {
     if (FIXNUM_2_P(recv, obj) &&
 	BASIC_OP_UNREDEFINED_P(BOP_MULT, FIXNUM_REDEFINED_OP_FLAG)) {
-	long a, b;
-
-	a = FIX2LONG(recv);
+	long a = FIX2LONG(recv);
 	if (a == 0) {
 	    val = recv;
 	}
 	else {
-	    b = FIX2LONG(obj);
-            if (MUL_OVERFLOW_FIXNUM_P(a, b)) {
+#ifdef HAVE_INT128_T
+	    VALUE rb_int128t2big(int128_t n);
+	    int128_t r = (int128_t)a * FIX2LONG(obj);
+	    if (RB_FIXABLE(r)) {
+		val = LONG2FIX((long)r);
+	    }
+	    else {
+		val = rb_int128t2big(r);
+	    }
+#else
+	    long b = FIX2LONG(obj);
+	    if (MUL_OVERFLOW_FIXNUM_P(a, b)) {
 		val = rb_big_mul(rb_int2big(a), rb_int2big(b));
-            }
-            else {
+	    }
+	    else {
 		val = LONG2FIX(a * b);
-            }
+	    }
+#endif
 	}
     }
     else if (FLONUM_2_P(recv, obj) &&
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 53740)
+++ ChangeLog	(revision 53741)
@@ -1,3 +1,14 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Fri Feb  5 12:22:20 2016  NARUSE, Yui  <naruse@r...>
+
+	* insns.def (opt_mult): Use int128_t for overflow detection.
+
+	* bignum.c (rb_uint128t2big): added for opt_mult.
+
+	* bignum.c (rb_uint128t2big): added for rb_uint128t2big..
+
+	* configure.in: define int128_t, uint128_t and related MACROs.
+	  Initially introduced by r41379 but reverted by r50749.
+
 Thu Feb  4 21:05:17 2016  Martin Duerst  <duerst@i...>
 
 	* enc/unicode.c: Activated :ascii flag for ASCII-only case conversion

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]