diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-06-26 15:27:20 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-06-26 15:27:20 +0000 |
commit | c72186f4c290685c145e5f1c6d1c6d8d7463eab2 (patch) | |
tree | 9057ed4c7fb11b9302de4897bb9f0125c4f6ea63 /bignum.c | |
parent | 186b494a81741c4138d4aa8f20b52ec0f52260f3 (diff) | |
download | ruby-c72186f4c290685c145e5f1c6d1c6d8d7463eab2.tar.gz |
* bignum.c (rb_big_pow): Retry if y is a Bignum and it is
representable as a Fixnum.
Use rb_absint_numwords.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41667 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'bignum.c')
-rw-r--r-- | bignum.c | 13 |
1 files changed, 9 insertions, 4 deletions
@@ -4578,6 +4578,7 @@ rb_big_pow(VALUE x, VALUE y) double d; SIGNED_VALUE yy; + again: if (y == INT2FIX(0)) return INT2FIX(1); switch (TYPE(y)) { case T_FLOAT: @@ -4587,6 +4588,9 @@ rb_big_pow(VALUE x, VALUE y) break; case T_BIGNUM: + y = bignorm(y); + if (FIXNUM_P(y)) + goto again; rb_warn("in a**b, b may be too big"); d = rb_big2dbl(y); break; @@ -4599,11 +4603,12 @@ rb_big_pow(VALUE x, VALUE y) else { VALUE z = 0; SIGNED_VALUE mask; - const long xlen = RBIGNUM_LEN(x); - const long xbits = BITSPERDIG*xlen - nlz(RBIGNUM_DIGITS(x)[xlen-1]); - const long BIGLEN_LIMIT = 32*1024*1024; + const size_t xbits = rb_absint_numwords(x, 1, NULL); + const size_t BIGLEN_LIMIT = 32*1024*1024; - if ((xbits > BIGLEN_LIMIT) || (xbits * yy > BIGLEN_LIMIT)) { + if (xbits == (size_t)-1 || + (xbits > BIGLEN_LIMIT) || + (xbits * yy > BIGLEN_LIMIT)) { rb_warn("in a**b, b may be too big"); d = (double)yy; break; |