From 935d39a5b82aebdb1af7763311590655ff2adf4c Mon Sep 17 00:00:00 2001 From: akr Date: Mon, 3 Jun 2013 14:49:33 +0000 Subject: * 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 --- ChangeLog | 5 +++++ bignum.c | 20 +++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 05b44fbdc4..ded56360f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Mon Jun 3 23:47:55 2013 Tanaka Akira + + * bignum.c (bitlength_bdigit): New function. + (rb_big_pow): Use bitlength_bdigit instead of ffs. + Mon Jun 3 23:11:19 2013 Ayumu AIZAWA * lib/fileutils.rb: fix behavior when mkdir/mkdir_p accepted "/". diff --git a/bignum.c b/bignum.c index 96b570a52d..820eff0fb4 100644 --- a/bignum.c +++ b/bignum.c @@ -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)) { -- cgit v1.2.3