diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-07-13 15:36:18 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-07-13 15:36:18 +0000 |
commit | 75a86e4733faf3f5a26aa08745e407c061d178c3 (patch) | |
tree | c5fc468018ff661cebaa3442945c91008dc9fa69 | |
parent | b9eeeac5c87591ca43fdb6aaafb521a84d7d3800 (diff) | |
download | ruby-75a86e4733faf3f5a26aa08745e407c061d178c3.tar.gz |
* bignum.c (rb_big_aref): Less scan when the number is negative.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41960 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | bignum.c | 26 |
2 files changed, 16 insertions, 14 deletions
@@ -1,3 +1,7 @@ +Sun Jul 14 00:32:51 2013 Tanaka Akira <akr@fsij.org> + + * bignum.c (rb_big_aref): Less scan when the number is negative. + Sun Jul 14 00:17:42 2013 Tanaka Akira <akr@fsij.org> * bignum.c (big_shift): Avoid signed integer overflow. @@ -5889,9 +5889,9 @@ static VALUE rb_big_aref(VALUE x, VALUE y) { BDIGIT *xds; - BDIGIT_DBL num; unsigned long shift; long i, s1, s2; + BDIGIT bit; if (RB_TYPE_P(y, T_BIGNUM)) { if (!RBIGNUM_SIGN(y)) @@ -5910,21 +5910,19 @@ rb_big_aref(VALUE x, VALUE y) } s1 = shift/BITSPERDIG; s2 = shift%BITSPERDIG; + bit = (BDIGIT)1 << s2; if (s1 >= RBIGNUM_LEN(x)) goto out_of_range; - if (!RBIGNUM_SIGN(x)) { - xds = BDIGITS(x); - i = 0; num = 1; - while (num += BIGLO(~xds[i]), ++i <= s1) { - num = BIGDN(num); - } - } - else { - num = BDIGITS(x)[s1]; - } - if (num & ((BDIGIT_DBL)1<<s2)) - return INT2FIX(1); - return INT2FIX(0); + + xds = BDIGITS(x); + if (RBIGNUM_POSITIVE_P(x)) + return (xds[s1] & bit) ? INT2FIX(1) : INT2FIX(0); + if (xds[s1] & (bit-1)) + return (xds[s1] & bit) ? INT2FIX(0) : INT2FIX(1); + for (i = 0; i < s1; i++) + if (xds[i]) + return (xds[s1] & bit) ? INT2FIX(0) : INT2FIX(1); + return (xds[s1] & bit) ? INT2FIX(1) : INT2FIX(0); } /* |