diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-06-03 14:49:33 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-06-03 14:49:33 +0000 |
commit | 935d39a5b82aebdb1af7763311590655ff2adf4c (patch) | |
tree | b725123c817dda0b0fdd5e7480f88f11d643936d | |
parent | bf386e580ff48d5bcdd7bc5a49c4515c6865afdb (diff) | |
download | ruby-935d39a5b82aebdb1af7763311590655ff2adf4c.tar.gz |
* bignum.c (bitlength_bdigit): New function.
(rb_big_pow): Use bitlength_bdigit instead of ffs.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41050 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | bignum.c | 20 |
2 files changed, 24 insertions, 1 deletions
@@ -1,3 +1,8 @@ +Mon Jun 3 23:47:55 2013 Tanaka Akira <akr@fsij.org> + + * bignum.c (bitlength_bdigit): New function. + (rb_big_pow): Use bitlength_bdigit instead of ffs. + Mon Jun 3 23:11:19 2013 Ayumu AIZAWA <ayumu.aizawa@gmail.com> * lib/fileutils.rb: fix behavior when mkdir/mkdir_p accepted "/". @@ -3178,6 +3178,24 @@ bigsqr(VALUE x) return bigtrunc(bigmul0(x, x)); } +static int +bitlength_bdigit(BDIGIT v) +{ + if (v == 0) + return 0; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; +#if 2 < SIZEOF_BDIGITS + v |= v >> 16; +#endif + v++; + if (v == 0) + return SIZEOF_BDIGITS*CHAR_BIT; + return ffs(v); /* assumption: sizeof(BDIGIT) <= sizeof(int) */ +} + /* * call-seq: * big ** exponent -> numeric @@ -3219,7 +3237,7 @@ rb_big_pow(VALUE x, VALUE y) VALUE z = 0; SIGNED_VALUE mask; const long xlen = RBIGNUM_LEN(x) - 1; - const long xbits = ffs(RBIGNUM_DIGITS(x)[xlen]) + SIZEOF_BDIGITS*BITSPERDIG*xlen; + const long xbits = bitlength_bdigit(RBIGNUM_DIGITS(x)[xlen]) + SIZEOF_BDIGITS*BITSPERDIG*xlen; const long BIGLEN_LIMIT = BITSPERDIG*1024*1024; if ((xbits > BIGLEN_LIMIT) || (xbits * yy > BIGLEN_LIMIT)) { |