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/