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

ruby-changes:29587

From: akr <ko1@a...>
Date: Wed, 26 Jun 2013 12:16:23 +0900 (JST)
Subject: [ruby-changes:29587] akr:r41639 (trunk): * bignum.c (bigand_int): Consider negative values.

akr	2013-06-26 12:16:12 +0900 (Wed, 26 Jun 2013)

  New Revision: 41639

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

  Log:
    * bignum.c (bigand_int): Consider negative values.
      (bigor_int): The allocated bignum should have enough size
      to store long.
      This fixes (bignum fits in a BDIGIT) | (fixnum bigger than BDIGIT)
      on platforms which SIZEOF_BDIGITS < SIZEOF_LONG,
      such as LP64 with 32bit BDIGIT (no int128).

  Modified files:
    trunk/ChangeLog
    trunk/bignum.c
    trunk/test/ruby/test_bignum.rb
    trunk/test/ruby/test_integer_comb.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 41638)
+++ ChangeLog	(revision 41639)
@@ -1,3 +1,12 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Wed Jun 26 12:13:12 2013  Tanaka Akira  <akr@f...>
+
+	* bignum.c (bigand_int): Consider negative values.
+	  (bigor_int): The allocated bignum should have enough size
+	  to store long.
+	  This fixes (bignum fits in a BDIGIT) | (fixnum bigger than BDIGIT)
+	  on platforms which SIZEOF_BDIGITS < SIZEOF_LONG,
+	  such as LP64 with 32bit BDIGIT (no int128).
+
 Wed Jun 26 12:08:51 2013  Tanaka Akira  <akr@f...>
 
 	* test/socket/test_udp.rb: Close sockets explicitly.
Index: bignum.c
===================================================================
--- bignum.c	(revision 41638)
+++ bignum.c	(revision 41639)
@@ -4643,6 +4643,10 @@ bigand_int(VALUE x, long y) https://github.com/ruby/ruby/blob/trunk/bignum.c#L4643
 	return LONG2NUM(y);
     }
 #endif
+#if SIZEOF_BDIGITS < SIZEOF_LONG
+    if (RBIGNUM_NEGATIVE_P(x) && zn < bdigit_roomof(SIZEOF_LONG))
+        zn = bdigit_roomof(SIZEOF_LONG);
+#endif
 
     z = bignew(zn, RBIGNUM_SIGN(x) || sign);
     zds = BDIGITS(z);
@@ -4656,10 +4660,18 @@ bigand_int(VALUE x, long y) https://github.com/ruby/ruby/blob/trunk/bignum.c#L4660
         zds[i] = xds[i] & BIGLO(y);
         y = BIGDN(y);
     }
+    for (; i < zn; i++) {
+        if (y == 0 || y == -1) break;
+        zds[i] = RBIGNUM_NEGATIVE_P(x) ? BIGLO(y) : 0;
+        y = BIGDN(y);
+    }
+
 #endif
-    while (i < xn) {
+    for (;i < xn; i++) {
 	zds[i] = sign?0:xds[i];
-	i++;
+    }
+    for (;i < zn; i++) {
+	zds[i] = (!sign && RBIGNUM_NEGATIVE_P(x)) ? BDIGMAX : 0;
     }
     if (!RBIGNUM_SIGN(z)) get2comp(z);
     return bignorm(z);
@@ -4737,26 +4749,54 @@ bigor_int(VALUE x, long y) https://github.com/ruby/ruby/blob/trunk/bignum.c#L4749
     sign = (y >= 0);
     xds = BDIGITS(x);
     zn = xn = RBIGNUM_LEN(x);
+#if SIZEOF_BDIGITS < SIZEOF_LONG
+    if (zn < bdigit_roomof(SIZEOF_LONG))
+        zn = bdigit_roomof(SIZEOF_LONG);
+#endif
     z = bignew(zn, RBIGNUM_SIGN(x) && sign);
     zds = BDIGITS(z);
 
 #if SIZEOF_BDIGITS >= SIZEOF_LONG
     i = 1;
     zds[0] = xds[0] | y;
+    if (i < zn)
+        goto y_is_fixed_point;
+    goto finish;
 #else
-    {
-	long num = y;
-
-	for (i=0; i<bdigit_roomof(SIZEOF_LONG); i++) {
-	    zds[i] = xds[i] | BIGLO(num);
-	    num = BIGDN(num);
-	}
+    for (i=0; i < xn; i++) {
+        if (y == 0 || y == -1) goto y_is_fixed_point;
+        zds[i] = xds[i] | BIGLO(y);
+        y = BIGDN(y);
+    }
+    if (RBIGNUM_NEGATIVE_P(x))
+        goto fill_hibits;
+    for (; i < zn; i++) {
+        if (y == 0 || y == -1) goto y_is_fixed_point;
+        zds[i] = BIGLO(y);
+        y = BIGDN(y);
     }
+  goto finish;
 #endif
-    while (i < xn) {
-	zds[i] = sign?xds[i]:BDIGMAX;
-	i++;
+
+  y_is_fixed_point:
+    if (!sign)
+        goto fill_hibits;
+    for (; i < xn; i++) {
+        zds[i] = xds[i];
     }
+    if (RBIGNUM_NEGATIVE_P(x))
+        goto fill_hibits;
+    for (; i < zn; i++) {
+        zds[i] = 0;
+    }
+  goto finish;
+
+  fill_hibits:
+    for (; i < zn; i++) {
+        zds[i] = BDIGMAX;
+    }
+
+  finish:
     if (!RBIGNUM_SIGN(z)) get2comp(z);
     return bignorm(z);
 }
Index: test/ruby/test_bignum.rb
===================================================================
--- test/ruby/test_bignum.rb	(revision 41638)
+++ test/ruby/test_bignum.rb	(revision 41639)
@@ -123,6 +123,12 @@ class TestBignum < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_bignum.rb#L123
   T1024  = b.coerce(2**1024).first
   T1024P = b.coerce(T1024 - 1).first
 
+  f = b
+  while Bignum === f-1
+    f = f >> 1
+  end
+  FIXNUM_MAX = f-1
+
   def test_prepare
     assert_instance_of(Bignum, T_ZERO)
     assert_instance_of(Bignum, T_ONE)
@@ -454,6 +460,7 @@ class TestBignum < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_bignum.rb#L460
     assert_equal(T32 + T31, T32 | T31)
     assert_equal(-T31, (-T32) | (-T31))
     assert_equal(T64 + T32, T32 | T64)
+    assert_equal(FIXNUM_MAX, T_ZERO | FIXNUM_MAX)
   end
 
   def test_xor
Index: test/ruby/test_integer_comb.rb
===================================================================
--- test/ruby/test_integer_comb.rb	(revision 41638)
+++ test/ruby/test_integer_comb.rb	(revision 41639)
@@ -106,6 +106,8 @@ class TestIntegerComb < Test::Unit::Test https://github.com/ruby/ruby/blob/trunk/test/ruby/test_integer_comb.rb#L106
   ]
 
   #VS.map! {|v| 0x4000000000000000.coerce(v)[0] }
+  #VS.concat VS.find_all {|v| Fixnum === v }.map {|v| 0x4000000000000000.coerce(v)[0] }
+  #VS.sort! {|a, b| a.abs <=> b.abs }
 
   min = -1
   min *= 2 while min.class == Fixnum

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

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