From 5ef43814a8d1cf3b3905c70555b09255f37cf1e3 Mon Sep 17 00:00:00 2001 From: matz Date: Wed, 8 Jun 2005 02:16:35 +0000 Subject: * bignum.c (get2comp): revert all prior changes, and calculate proper 2's complement for negative numbers. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8591 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 10 +++++++++- bignum.c | 41 +++++++++++++++++++++++++++-------------- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index a969e4998e..ccd39a24d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Wed Jun 8 11:11:34 2005 Yukihiro Matsumoto + + * bignum.c (get2comp): revert all prior changes, and calculate + proper 2's complement for negative numbers. + Wed Jun 8 08:33:10 2005 Nobuyoshi Nakada * enum.c (enum_min_by, enum_max_by): return nil if no iteration. @@ -11,7 +16,10 @@ Wed Jun 8 01:27:06 2005 Yukihiro Matsumoto * bignum.c (bignorm): fixed a bug in normalizing negative numbers reported from Honda Hiroki . normalizing - should not trim preceding zeros from negative numbers. + should not trim leading zeros from negative numbers. + + * bignum.c (rb_cstr_to_inum): must remove leading zeros for this + case. Wed Jun 8 00:15:08 2005 Yukihiro Matsumoto diff --git a/bignum.c b/bignum.c index e534150073..dc5e117445 100644 --- a/bignum.c +++ b/bignum.c @@ -85,7 +85,7 @@ get2comp(x, carry) /* get 2's complement */ if ((ds[RBIGNUM(x)->len-1] & (1<<(BITSPERDIG-1))) == 0) { REALLOC_N(RBIGNUM(x)->digits, BDIGIT, ++RBIGNUM(x)->len); ds = BDIGITS(x); - ds[RBIGNUM(x)->len-1] = ~0; + ds[RBIGNUM(x)->len-1] = RBIGNUM(x)->sign ? ~0 : 1; } } @@ -105,15 +105,9 @@ bignorm(x) BDIGIT *ds = BDIGITS(x); while (len-- && !ds[len]) ; - len++; - if (RBIGNUM(x)->sign) { - RBIGNUM(x)->len = len; - } - else if (len == 0) { - return x; - } + RBIGNUM(x)->len = ++len; - if (RBIGNUM(x)->len*SIZEOF_BDIGITS <= sizeof(VALUE)) { + if (len*SIZEOF_BDIGITS <= sizeof(VALUE)) { long num = 0; while (len--) { num = BIGUP(num) + ds[len]; @@ -1063,11 +1057,30 @@ rb_big_neg(x) VALUE z = rb_big_clone(x); long i = RBIGNUM(x)->len; BDIGIT *ds = BDIGITS(z); + int nz = 0; if (!RBIGNUM(x)->sign) get2comp(z, Qtrue); - while (i--) ds[i] = ~ds[i]; - if (RBIGNUM(x)->sign) get2comp(z, Qfalse); + while (i--) { + ds[i] = ~ds[i]; + } RBIGNUM(z)->sign = !RBIGNUM(z)->sign; + if (RBIGNUM(x)->sign) get2comp(z, Qtrue); +#if 0 + i = RBIGNUM(x)->len; + if (RBIGNUM(x)->sign) { + while (i--) { + if (ds[i]) nz = Qtrue; + } + if (!nz) { + z = bignew(RBIGNUM(x)->len+1, 1); + for (i=0; ilen; i++) { + BDIGITS(z)[i] = BDIGITS(x)[i]; + } + BDIGITS(z)[i] = 1; + BDIGITS(z)[0] = 0; + } + } +#endif return bignorm(z); } @@ -1688,7 +1701,7 @@ rb_big_and(xx, yy) for (; isign) get2comp(z, Qfalse); + if (!RBIGNUM(z)->sign) get2comp(z, Qtrue); return bignorm(z); } @@ -1745,7 +1758,7 @@ rb_big_or(xx, yy) for (; isign) get2comp(z, Qfalse); + if (!RBIGNUM(z)->sign) get2comp(z, Qtrue); return bignorm(z); } @@ -1806,7 +1819,7 @@ rb_big_xor(xx, yy) for (; isign) get2comp(z, Qfalse); + if (!RBIGNUM(z)->sign) get2comp(z, Qtrue); return bignorm(z); } -- cgit v1.2.3