(1 << 0x40000000)[0x40000000]

e$B<!$N$h$&$K!"e(B(1 << 0x40000000)[0x40000000] e$B$,e(B 0
e$B$K$J$j$^$9!#e(B

% ./ruby -ve ‘p((1 << 0x40000000)[0x40000000])’
ruby 1.9.0 (2007-07-22 patchlevel 0) [i686-linux]
0

e$B$^$?!"e(B(-1 << 0x40000001)[0x40000000] e$B$,e(B 1 e$B$K$J$j$^$9!#e(B

% ./ruby -e ‘p((-1 << 0x40000001)[0x40000000])’
1

e$B$"$H!"e(B(-0x40000002)[big_zero] e$B$,e(B 1 e$B$K!"e(B
0x400000001[big_zero] e$B$,e(B 0 e$B$K$J$j$^$9!#e(B

% ./ruby -e ‘big_zero = 0x40000000.coerce(0)[0];
p((-0x40000002)[big_zero])’
1
% ./ruby -e ‘big_zero = 0x40000000.coerce(0)[0];
p(0x400000001[big_zero])’
0

e$B$J$+$@$G$9!#e(B

At Mon, 23 Jul 2007 00:35:30 +0900,
Tanaka A. wrote in [ruby-dev:31271]:

e$B<!$N$h$&$K!"e(B(1 << 0x40000000)[0x40000000] e$B$,e(B 0 e$B$K$J$j$^$9!#e(B
(e$B0J2<N,e(B)

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<<s2))
  • if (num & ((BDIGIT_DBL)1<<s2))
    return INT2FIX(1);
    return INT2FIX(0);
    Index: stable/bignum.c
    ===================================================================
    — stable/bignum.c (revision 12828)
    +++ stable/bignum.c (working copy)
    @@ -2152,27 +2152,37 @@ rb_big_aref(x, y)
    {
    BDIGIT *xds;
  • int shift;
  • long s1, s2;
  • BDIGIT_DBL num;

  • unsigned long 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_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<<s2))
  • if (num & ((BDIGIT_DBL)1<<s2))
    return INT2FIX(1);
    return INT2FIX(0);