summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-06-26 15:27:20 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-06-26 15:27:20 +0000
commitc72186f4c290685c145e5f1c6d1c6d8d7463eab2 (patch)
tree9057ed4c7fb11b9302de4897bb9f0125c4f6ea63
parent186b494a81741c4138d4aa8f20b52ec0f52260f3 (diff)
* 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
-rw-r--r--ChangeLog6
-rw-r--r--bignum.c13
2 files changed, 15 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index e23813aa8f..bf6ae60c33 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Thu Jun 27 00:23:57 2013 Tanaka Akira <akr@fsij.org>
+
+ * bignum.c (rb_big_pow): Retry if y is a Bignum and it is
+ representable as a Fixnum.
+ Use rb_absint_numwords.
+
Wed Jun 26 23:53:00 2013 Charlie Somerville <charliesome@ruby-lang.org>
* ext/bigdecimal/bigdecimal.c (BigDecimal_save_rounding_mode): fix typo.
diff --git a/bignum.c b/bignum.c
index fb95412164..015eae924c 100644
--- a/bignum.c
+++ b/bignum.c
@@ -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;