From: Nobuyoshi Nakada Date: 2007-07-23T03:14:55+09:00 Subject: [ruby-dev:31273] Re: (1 << 0x40000000)[0x40000000] なかだです。 At Mon, 23 Jul 2007 00:35:30 +0900, Tanaka Akira wrote in [ruby-dev:31271]: > 次のように、(1 << 0x40000000)[0x40000000] が 0 になります。 (以下略) Index: trunk/bignum.c =================================================================== --- trunk/bignum.c (revision 12828) +++ trunk/bignum.c (working copy) @@ -2062,27 +2062,37 @@ rb_big_aref(VALUE x, VALUE y) { BDIGIT *xds; - int shift; - long s1, s2; + BDIGIT_DBL num; + VALUE shift; + long i, s1, s2; if (TYPE(y) == T_BIGNUM) { - if (!RBIGNUM(y)->sign || RBIGNUM(x)->sign) + if (!RBIGNUM(y)->sign) return INT2FIX(0); - return INT2FIX(1); + if (RBIGNUM(bigtrunc(y))->len > SIZEOF_VALUE/SIZEOF_BDIGITS) { + out_of_range: + return RBIGNUM(x)->sign ? INT2FIX(0) : INT2FIX(1); + } + shift = big2ulong(y, "long", Qfalse); + } + else { + i = NUM2LONG(y); + if (i < 0) return INT2FIX(0); + shift = (VALUE)i; } - shift = NUM2INT(y); - if (shift < 0) return INT2FIX(0); s1 = shift/BITSPERDIG; s2 = shift%BITSPERDIG; + if (s1 >= RBIGNUM(x)->len) goto out_of_range; if (!RBIGNUM(x)->sign) { - if (s1 >= RBIGNUM(x)->len) return INT2FIX(1); - x = rb_big_clone(x); - get2comp(x); + xds = BDIGITS(x); + i = 0; num = 1; + while (num += ~xds[i], ++i <= s1) { + num = BIGDN(num); + } } else { - if (s1 >= RBIGNUM(x)->len) return INT2FIX(0); + num = BDIGITS(x)[s1]; } - xds = BDIGITS(x); - if (xds[s1] & (1<sign || RBIGNUM(x)->sign) + if (!RBIGNUM(y)->sign) return INT2FIX(0); - return INT2FIX(1); + if (RBIGNUM(bigtrunc(y))->len > SIZEOF_LONG/SIZEOF_BDIGITS) { + out_of_range: + return RBIGNUM(x)->sign ? INT2FIX(0) : INT2FIX(1); + } + shift = big2ulong(y, "long", Qfalse); + } + else { + i = NUM2LONG(y); + if (i < 0) return INT2FIX(0); + shift = (VALUE)i; } - shift = NUM2INT(y); - if (shift < 0) return INT2FIX(0); s1 = shift/BITSPERDIG; s2 = shift%BITSPERDIG; + if (s1 >= RBIGNUM(x)->len) goto out_of_range; if (!RBIGNUM(x)->sign) { - if (s1 >= RBIGNUM(x)->len) return INT2FIX(1); - x = rb_big_clone(x); - get2comp(x); + xds = BDIGITS(x); + i = 0; num = 1; + while (num += ~xds[i], ++i <= s1) { + num = BIGDN(num); + } } else { - if (s1 >= RBIGNUM(x)->len) return INT2FIX(0); + num = BDIGITS(x)[s1]; } - xds = BDIGITS(x); - if (xds[s1] & (1<