diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2005-06-08 02:16:35 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2005-06-08 02:16:35 +0000 |
commit | 5ef43814a8d1cf3b3905c70555b09255f37cf1e3 (patch) | |
tree | 3770796837bcde32fd7ac419a127530addef2220 | |
parent | 17920c7a9e41f8f89f6a413e42fadfa332b5665e (diff) | |
download | ruby-5ef43814a8d1cf3b3905c70555b09255f37cf1e3.tar.gz |
* 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
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | bignum.c | 41 |
2 files changed, 36 insertions, 15 deletions
@@ -1,3 +1,8 @@ +Wed Jun 8 11:11:34 2005 Yukihiro Matsumoto <matz@ruby-lang.org> + + * 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 <nobu@ruby-lang.org> * 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 <matz@ruby-lang.org> * bignum.c (bignorm): fixed a bug in normalizing negative numbers reported from Honda Hiroki <hhonda@ipflex.com>. 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 <matz@ruby-lang.org> @@ -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; i<RBIGNUM(x)->len; 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 (; i<l2; i++) { zds[i] = sign?0:ds2[i]; } - if (!RBIGNUM(z)->sign) get2comp(z, Qfalse); + if (!RBIGNUM(z)->sign) get2comp(z, Qtrue); return bignorm(z); } @@ -1745,7 +1758,7 @@ rb_big_or(xx, yy) for (; i<l2; i++) { zds[i] = sign?ds2[i]:(BIGRAD-1); } - if (!RBIGNUM(z)->sign) get2comp(z, Qfalse); + if (!RBIGNUM(z)->sign) get2comp(z, Qtrue); return bignorm(z); } @@ -1806,7 +1819,7 @@ rb_big_xor(xx, yy) for (; i<l2; i++) { zds[i] = sign?ds2[i]:~ds2[i]; } - if (!RBIGNUM(z)->sign) get2comp(z, Qfalse); + if (!RBIGNUM(z)->sign) get2comp(z, Qtrue); return bignorm(z); } |