summaryrefslogtreecommitdiff
path: root/bignum.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-04-26 15:02:57 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-04-26 15:02:57 +0000
commita379112975823550ab7b4493d4bd1244a6a1aeb5 (patch)
tree831305636a99b0f5fd5c0e2e8b6d0d90338dccee /bignum.c
parent93bdc98f33c0dfa2d7baf03787f0d8181062d9cf (diff)
* bignum.c (rb_big_pow): truncate all zero BDIGITs. [ruby-dev:30733]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12224 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'bignum.c')
-rw-r--r--bignum.c54
1 files changed, 34 insertions, 20 deletions
diff --git a/bignum.c b/bignum.c
index ba107e9edc..8346433a56 100644
--- a/bignum.c
+++ b/bignum.c
@@ -90,34 +90,48 @@ rb_big_2comp(VALUE x) /* get 2's complement */
}
static VALUE
-bignorm(VALUE x)
+bigtrunc(VALUE x)
{
- if (FIXNUM_P(x)) {
- return x;
- }
- else if (TYPE(x) == T_BIGNUM) {
- long len = RBIGNUM(x)->len;
- BDIGIT *ds = BDIGITS(x);
+ long len = RBIGNUM(x)->len;
+ BDIGIT *ds = BDIGITS(x);
- while (len-- && !ds[len]) ;
- RBIGNUM(x)->len = ++len;
+ while (len-- && !ds[len]);
+ RBIGNUM(x)->len = ++len;
+ return x;
+}
+
+static VALUE
+bigfixize(VALUE x)
+{
+ long len = RBIGNUM(x)->len;
+ BDIGIT *ds = BDIGITS(x);
- if (len*SIZEOF_BDIGITS <= sizeof(VALUE)) {
- SIGNED_VALUE num = 0;
- while (len--) {
- num = BIGUP(num) + ds[len];
+ if (len*SIZEOF_BDIGITS <= sizeof(VALUE)) {
+ SIGNED_VALUE num = 0;
+ while (len--) {
+ num = BIGUP(num) + ds[len];
+ }
+ if (num >= 0) {
+ if (RBIGNUM(x)->sign) {
+ if (POSFIXABLE(num)) return LONG2FIX(num);
}
- if (num >= 0) {
- if (RBIGNUM(x)->sign) {
- if (POSFIXABLE(num)) return LONG2FIX(num);
- }
- else if (NEGFIXABLE(-(long)num)) return LONG2FIX(-(long)num);
+ else {
+ if (NEGFIXABLE(-(long)num)) return LONG2FIX(-(long)num);
}
}
}
return x;
}
+static VALUE
+bignorm(VALUE x)
+{
+ if (!FIXNUM_P(x) && TYPE(x) == T_BIGNUM) {
+ x = bigfixize(bigtrunc(x));
+ }
+ return x;
+}
+
VALUE
rb_big_norm(VALUE x)
{
@@ -1563,10 +1577,10 @@ rb_big_pow(VALUE x, VALUE y)
do {
yy /= 2;
x = rb_big_mul0(x, x);
- if (!BDIGITS(x)[RBIGNUM(x)->len-1]) RBIGNUM(x)->len--;
+ bigtrunc(x);
} while (yy % 2 == 0);
z = z ? rb_big_mul0(z, x) : x;
- if (!BDIGITS(z)[RBIGNUM(z)->len-1]) RBIGNUM(z)->len--;
+ bigtrunc(z);
}
return bignorm(z);
}