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

ruby-changes:29976

From: akr <ko1@a...>
Date: Wed, 17 Jul 2013 22:53:35 +0900 (JST)
Subject: [ruby-changes:29976] akr:r42028 (trunk): * bignum.c: An static assertion for relation of SIZEOF_LONG and

akr	2013-07-17 22:53:24 +0900 (Wed, 17 Jul 2013)

  New Revision: 42028

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=42028

  Log:
    * bignum.c: An static assertion for relation of SIZEOF_LONG and
      SIZEOF_BDIGITS is added.
      (bary_mul_precheck): Reduce comparisons.
      (bary_mul): Invoke bary_sq_fast or bary_mul1 if the bignum size is
      small.
      (bigfixize): Resize the argument bignum here.
      (bignorm): Don't call bigtrunc after bigfixize.

  Modified files:
    trunk/ChangeLog
    trunk/bignum.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 42027)
+++ ChangeLog	(revision 42028)
@@ -1,3 +1,13 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Wed Jul 17 22:34:47 2013  Tanaka Akira  <akr@f...>
+
+	* bignum.c: An static assertion for relation of SIZEOF_LONG and
+	  SIZEOF_BDIGITS is added.
+	  (bary_mul_precheck): Reduce comparisons.
+	  (bary_mul): Invoke bary_sq_fast or bary_mul1 if the bignum size is
+	  small.
+	  (bigfixize): Resize the argument bignum here.
+	  (bignorm): Don't call bigtrunc after bigfixize.
+
 Wed Jul 17 22:13:26 2013  Masaki Matsushita  <glass.saga@g...>
 
 	* hash.c (rb_hash_replace): performance improvement by using
Index: bignum.c
===================================================================
--- bignum.c	(revision 42027)
+++ bignum.c	(revision 42028)
@@ -47,6 +47,12 @@ STATIC_ASSERT(bdigit_dbl_signedness, 0 < https://github.com/ruby/ruby/blob/trunk/bignum.c#L47
 STATIC_ASSERT(bdigit_dbl_signed_signedness, 0 > (BDIGIT_DBL_SIGNED)-1);
 STATIC_ASSERT(rbignum_embed_len_max, RBIGNUM_EMBED_LEN_MAX <= (RBIGNUM_EMBED_LEN_MASK >> RBIGNUM_EMBED_LEN_SHIFT));
 
+#if SIZEOF_BDIGITS < SIZEOF_LONG
+STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_LONG % SIZEOF_BDIGITS == 0);
+#else
+STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_BDIGITS % SIZEOF_LONG == 0);
+#endif
+
 #ifdef WORDS_BIGENDIAN
 #   define HOST_BIGENDIAN_P 1
 #else
@@ -1911,22 +1917,40 @@ bary_mul_precheck(BDIGIT **zdsp, size_t https://github.com/ruby/ruby/blob/trunk/bignum.c#L1917
 
     assert(xl + yl <= zl);
 
-    while (0 < xl && xds[xl-1] == 0)
-        xl--;
-    while (0 < yl && yds[yl-1] == 0)
-        yl--;
-
     nlsz = 0;
-    while (0 < xl && xds[0] == 0) {
-        xds++;
-        xl--;
-        nlsz++;
+
+    while (0 < xl) {
+        if (xds[xl-1] == 0) {
+            xl--;
+        }
+        else {
+            do {
+                if (xds[0] != 0)
+                    break;
+                xds++;
+                xl--;
+                nlsz++;
+            } while (0 < xl);
+            break;
+        }
     }
-    while (0 < yl && yds[0] == 0) {
-        yds++;
-        yl--;
-        nlsz++;
+
+    while (0 < yl) {
+        if (yds[yl-1] == 0) {
+            yl--;
+        }
+        else {
+            do {
+                if (xds[0] != 0)
+                    break;
+                yds++;
+                yl--;
+                nlsz++;
+            } while (0 < yl);
+            break;
+        }
     }
+
     if (nlsz) {
         MEMZERO(zds, BDIGIT, nlsz);
         zds += nlsz;
@@ -1942,12 +1966,12 @@ bary_mul_precheck(BDIGIT **zdsp, size_t https://github.com/ruby/ruby/blob/trunk/bignum.c#L1966
     }
     assert(xl <= yl);
 
-    if (xl == 0) {
-        MEMZERO(zds, BDIGIT, zl);
-        return 1;
-    }
+    if (xl <= 1) {
+        if (xl == 0) {
+            MEMZERO(zds, BDIGIT, zl);
+            return 1;
+        }
 
-    if (xl == 1) {
         if (xds[0] == 1) {
             MEMCPY(zds, yds, BDIGIT, yl);
             MEMZERO(zds+yl, BDIGIT, zl-yl);
@@ -2059,6 +2083,14 @@ bary_mul_toom3_start(BDIGIT *zds, size_t https://github.com/ruby/ruby/blob/trunk/bignum.c#L2083
 static void
 bary_mul(BDIGIT *zds, size_t zl, BDIGIT *xds, size_t xl, BDIGIT *yds, size_t yl)
 {
+    if (xl < KARATSUBA_MUL_DIGITS) {
+        if (xds == yds && xl == yl)
+            bary_sq_fast(zds, zl, xds, xl);
+        else
+            bary_mul1(zds, zl, xds, xl, yds, yl);
+        return;
+    }
+
     bary_mul_toom3_start(zds, zl, xds, xl, yds, yl, NULL, 0);
 }
 
@@ -2275,28 +2307,45 @@ bigtrunc(VALUE x) https://github.com/ruby/ruby/blob/trunk/bignum.c#L2307
 static inline VALUE
 bigfixize(VALUE x)
 {
-    long len = RBIGNUM_LEN(x);
+    size_t len = RBIGNUM_LEN(x);
     BDIGIT *ds = BDIGITS(x);
+#if SIZEOF_BDIGITS < SIZEOF_LONG
+    unsigned long u;
+#else
+    BDIGIT u;
+#endif
+
+    while (0 < len && ds[len-1] == 0)
+        len--;
 
     if (len == 0) return INT2FIX(0);
-    if (BIGSIZE(x) <= sizeof(long)) {
-	long num = 0;
-#if SIZEOF_BDIGITS >= SIZEOF_LONG
-	num = (long)ds[0];
-#else
-	while (len--) {
-	    num = (long)(BIGUP(num) + ds[len]);
-	}
+
+#if SIZEOF_BDIGITS < SIZEOF_LONG
+    if (sizeof(long)/SIZEOF_BDIGITS < len)
+        goto return_big;
+    else {
+        int i = (int)len;
+        u = 0;
+        while (i--) {
+            u = (long)(BIGUP(u) + ds[i]);
+        }
+    }
+#else /* SIZEOF_BDIGITS >= SIZEOF_LONG */
+    if (1 < len || LONG_MAX < ds[0])
+        goto return_big;
+    else
+        u = ds[0];
 #endif
-	if (num >= 0) {
-	    if (RBIGNUM_SIGN(x)) {
-		if (POSFIXABLE(num)) return LONG2FIX(num);
-	    }
-	    else {
-		if (NEGFIXABLE(-num)) return LONG2FIX(-num);
-	    }
-	}
+
+    if (RBIGNUM_POSITIVE_P(x)) {
+        if (POSFIXABLE(u)) return LONG2FIX((long)u);
     }
+    else {
+        if (u <= -FIXNUM_MIN) return LONG2FIX(-(long)u);
+    }
+
+  return_big:
+    rb_big_resize(x, len);
     return x;
 }
 
@@ -2305,8 +2354,6 @@ bignorm(VALUE x) https://github.com/ruby/ruby/blob/trunk/bignum.c#L2354
 {
     if (RB_TYPE_P(x, T_BIGNUM)) {
 	x = bigfixize(x);
-        if (!FIXNUM_P(x))
-            bigtrunc(x);
     }
     return x;
 }

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

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