Shift

-O0 e$B$G!"0J2<$N$h$&$K$9$k$He(B SEGV e$B$K$J$j$^$9!#e(B

% ./ruby -ve ‘1 << -0x40000000’
ruby 1.9.0 (2007-07-18 patchlevel 0) [i686-linux]
zsh: segmentation fault ./ruby -ve ‘1 << -0x40000000’

e$B$3$3$G!":8%%Z%i%s%I$r$R$H$D8:$i$9$H!":8%^%$%J%9$?$/$5$s%7%Ue(B
e$B%H$J$N$G!"7k2L$Oe(B 0 e$B$K$J$k$O$:$@$H$
$b$&$N$G$9$,!"I=<($9$k$Ke(B
e$B$OBg$-$9$.$kCM$K$J$j$^$9!#e(B

% ./ruby -e ‘p((1 << -0x40000001).size)’
134217728

e$B$:$C$H8:$i$7$F0J2<$J$i!"$d$O$je(B 0
e$B$K$J$k$O$:$@$H$*$b$$$^$9$,!"e(B
1 e$B$K$J$j$^$9!#e(B

% ./ruby -e ‘p 1 << -0x80000000’
1

e$B$5$i$K$b$&$R$H$D8:$i$9$H!"$d$O$je(B 0 e$B$K$J$C$F$[$7$$$N$G$9$,!"e(B
RangeError e$B$K$J$j$^$9!#e(B

% ./ruby -e ‘p 1 << -0x80000001’
-e:1:in <<': bignum too big to convert intolong’ (RangeError)
from -e:1:in `’

e$B$^$?!"0J2<$Oe(B SEGV e$B$K$J$j$^$9!#e(B

% ./ruby -e ‘1 >> -0x40000000’
zsh: segmentation fault ./ruby -e ‘1 >> -0x40000000’

e$B$3$3$G:8%*%Z%i%s%I$r$R$H$D8:$i$9$H!"1&%^%$%J%9$?$/$5$s%7%U%He(B
e$B$J$N$G$H$F$bBg$-$JCM$K$J$k$H;W$&$N$G$9$,!"e(B0 e$B$K$J$j$^$9!#e(B

% ./ruby -e ‘p 1 >> -0x40000001’
0

e$B$:$C$H8:$i$7$F0J2<$J$i!"$d$O$j$H$F$bBg$-$JCM$K$J$k$H;W$&$N$Ge(B
e$B$9$,!"e(B1 e$B$K$J$j$^$9!#e(B

% ./ruby -e ‘p 1 >> -0x80000000’
1

e$B$^$?!"$3$s$I$O1&%*%Z%i%s%I$r@5$K$7$F0J2<$r;n$9$H!"e(B0 e$B$K$J$C$Fe(B
e$B$[$7$$$N$G$9$,e(B RangeError e$B$K$J$j$^$9!#e(B

% ./ruby -e ‘p 1 >> 0x80000000’
-e:1:in >>': bignum too big to convert intolong’
>>(RangeError)
from -e:1:in `’

In article
[email protected],
Nobuyoshi N. [email protected] writes:

e$B$3$s$J$H$3$m$G$I$&$G$7$g$&$+!#e(B

e$B$H$j$"$($:e(B rb_big_odd_p e$B$,$J$$$h$&$G$9!#e(B

% make

gcc -Wall -Wformat=2 -O0 -g3 -DRUBY_DEBUG_ENV -L. -rdynamic
-Wl,-export-dynamic main.o libruby-static.a -lpthread -ldl -lcrypt
-lm -o miniruby
libruby-static.a(bignum.o): In function rb_big_pow': /home/akr/ruby/yarvo0/ruby/bignum.c:1682: undefined reference to rb_big_odd_p’
collect2: ld returned 1 exit status

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

At Wed, 18 Jul 2007 12:42:11 +0900,
Tanaka A. wrote in [ruby-dev:31244]:

-O0 e$B$G!"0J2<$N$h$&$K$9$k$He(B SEGV e$B$K$J$j$^$9!#e(B
(ry

e$B$3$s$J$H$3$m$G$I$&$G$7$g$&$+!#e(B

Index: bignum.c

— bignum.c (revision 12812)
+++ bignum.c (working copy)
@@ -1530,5 +1537,15 @@ bdigbitsize(BDIGIT x)
}

-static VALUE rb_big_rshift(VALUE,VALUE);
+static VALUE big_lshift(VALUE, unsigned int);
+static VALUE big_rshift(VALUE, unsigned int);
+
+static VALUE big_shift(VALUE x, int n)
+{

  • if (n < 0)
  • return big_lshift(x, (unsigned int)n);
  • else if (n > 0)
  • return big_rshift(x, (unsigned int)n);
  • return x;
    +}

/*
@@ -1559,5 +1576,5 @@ rb_big_quo(VALUE x, VALUE y)
ex += bdigbitsize(BDIGITS(x)[RBIGNUM(x)->len - 1]);
ex -= 2 * DBL_BIGDIG * BITSPERDIG;

  • if (ex) x = rb_big_rshift(x, INT2FIX(ex));
  • if (ex) x = big_shift(x, ex);

    switch (TYPE(y)) {
    @@ -1568,5 +1585,5 @@ rb_big_quo(VALUE x, VALUE y)
    ey += bdigbitsize(BDIGITS(y)[RBIGNUM(y)->len - 1]);
    ey -= DBL_BIGDIG * BITSPERDIG;

  •  if (ey) y = rb_big_rshift(y, INT2FIX(ey));
    
  •  if (ey) y = big_shift(y, ey);
    

    bignum:
    bigdivrem(x, y, &z, 0);
    @@ -1659,4 +1676,5 @@ rb_big_pow(VALUE x, VALUE y)
    double d;
    SIGNED_VALUE yy;

  • int odd = 0;

    if (y == INT2FIX(0)) return INT2FIX(1);
    @@ -1669,4 +1687,5 @@ rb_big_pow(VALUE x, VALUE y)
    rb_warn(“in a**b, b may be too big”);
    d = rb_big2dbl(y);

  • odd = rb_big_odd_p(y);
    break;

@@ -1679,4 +1698,5 @@ rb_big_pow(VALUE x, VALUE y)
if (RBIGNUM(x)->len * SIZEOF_BDIGITS * yy > 1024*1024) {
rb_warn(“in a**b, b may be too big”);

  • odd = yy & 1;
    d = (double)yy;
    break;
    @@ -1696,5 +1716,12 @@ rb_big_pow(VALUE x, VALUE y)
    return rb_num_coerce_bin(x, y);
    }
  • return rb_float_new(pow(rb_big2dbl(x), d));
  • d = pow(rb_big2dbl(x), d);
    +#ifdef linux
  • if (isnan(d)) {
  • d = (RBIGNUM(x)->sign || !odd) ? +1 : -1;
  • d /= 0.0;
  • }
    +#endif
  • return rb_float_new(d);
    }

@@ -1871,4 +1898,17 @@ rb_big_xor(VALUE xx, VALUE yy)
}

+static VALUE
+check_shift_width(VALUE y, VALUE x)
+{

  • long len = RBIGNUM(y)->len;
  • if (len) {
  • len = 1 << (len - 1) * BITSPERDIG;
  • if (len / BITSPERDIG > RBIGNUM(x)->len) {
  •  return RBIGNUM(x)->sign ? INT2FIX(0) : INT2FIX(-1);
    
  • }
  • }
  • return Qnil;
    +}

/*

  • call-seq:
    @@ -1881,6 +1921,30 @@ VALUE
    rb_big_lshift(VALUE x, VALUE y)
    {
  • int shift;
  • for (;:wink: {
  • if (FIXNUM_P(y)) {
  •  shift = FIX2INT(y);
    
  •  break;
    
  • }
  • else if (TYPE(y) == T_BIGNUM) {
  •  if (!RBIGNUM(y)->sign) {
    
  • VALUE t = check_shift_width(y, x);
  • if (!NIL_P(t)) return t;
  •  }
    
  •  shift = big2ulong(y, "long", Qtrue);
    
  •  break;
    
  • }
  • y = rb_to_int(y);
  • }
  • if (shift < 0) return big_rshift(x, -shift);
  • return big_lshift(x, shift);
    +}

+static VALUE
+big_lshift(VALUE x, unsigned int shift)
+{
BDIGIT *xds, *zds;

  • int shift = NUM2INT(y);
    int s1 = shift/BITSPERDIG;
    int s2 = shift%BITSPERDIG;
    @@ -1889,5 +1953,4 @@ rb_big_lshift(VALUE x, VALUE y)
    long len, i;

  • if (shift < 0) return rb_big_rshift(x, INT2FIX(-shift));
    len = RBIGNUM(x)->len;
    z = bignew(len+s1+1, RBIGNUM(x)->sign);
    @@ -1913,9 +1976,33 @@ rb_big_lshift(VALUE x, VALUE y)
    */

-static VALUE
+VALUE
rb_big_rshift(VALUE x, VALUE y)
{

  • int shift;
  • for (;:wink: {
  • if (FIXNUM_P(y)) {
  •  shift = FIX2INT(y);
    
  •  break;
    
  • }
  • else if (TYPE(y) == T_BIGNUM) {
  •  if (RBIGNUM(y)->sign) {
    
  • VALUE t = check_shift_width(y, x);
  • if (!NIL_P(t)) return t;
  •  }
    
  •  shift = big2ulong(y, "long", Qtrue);
    
  •  break;
    
  • }
  • y = rb_to_int(y);
  • }
  • if (shift < 0) return big_lshift(x, -shift);
  • return big_rshift(x, shift);
    +}

+static VALUE
+big_rshift(VALUE x, unsigned int shift)
+{
BDIGIT *xds, *zds;

  • int shift = NUM2INT(y);
    long s1 = shift/BITSPERDIG;
    long s2 = shift%BITSPERDIG;
    @@ -1925,6 +2012,4 @@ rb_big_rshift(VALUE x, VALUE y)
    volatile VALUE save_x;

  • if (shift < 0) return rb_big_lshift(x, INT2FIX(-shift));

  • if (s1 > RBIGNUM(x)->len) {
    if (RBIGNUM(x)->sign)
    Index: numeric.c
    ===================================================================
    — numeric.c (revision 12812)
    +++ numeric.c (working copy)
    @@ -2592,5 +2600,6 @@ fix_xor(VALUE x, VALUE y)
    }

-static VALUE fix_rshift(VALUE, VALUE);
+static VALUE fix_lshift(long, unsigned long);
+static VALUE fix_rshift(long, unsigned long);

/*
@@ -2602,15 +2611,23 @@ static VALUE fix_rshift(VALUE, VALUE);

static VALUE
-fix_lshift(VALUE x, VALUE y)
+rb_fix_lshift(VALUE x, VALUE y)
{
long val, width;

 val = NUM2LONG(x);
  • width = NUM2LONG(y);
  • if (!FIXNUM_P(y))
  • return rb_big_lshift(rb_int2big(val), y);
  • width = FIX2LONG(y);
    if (width < 0)
  • return fix_rshift(x, LONG2FIX(-width));
  • return fix_rshift(val, (unsigned long)-width);
  • return fix_lshift(val, width);
    +}

+static VALUE
+fix_lshift(long val, unsigned long width)
+{
if (width > (sizeof(VALUE)*CHAR_BIT-1)
|| ((unsigned long)val)>>(sizeof(VALUE)*CHAR_BIT-1-width) > 0) {

  • return rb_big_lshift(rb_int2big(val), y);
  • return rb_big_lshift(rb_int2big(val), LONG2NUM(width));
    }
    val = val << width;
    @@ -2626,13 +2643,21 @@ fix_lshift(VALUE x, VALUE y)

static VALUE
-fix_rshift(VALUE x, VALUE y)
+rb_fix_rshift(VALUE x, VALUE y)
{
long i, val;

  • i = NUM2LONG(y);
  • if (i < 0)
  • return fix_lshift(x, LONG2FIX(-i));
  • if (i == 0) return x;
    val = FIX2LONG(x);
  • if (!FIXNUM_P(y))
  • return rb_big_rshift(rb_int2big(val), y);
  • i = FIX2LONG(y);
  • if (i == 0) return x;
  • if (i < 0)
  • return fix_lshift(val, (unsigned long)-i);
  • return fix_rshift(val, i);
    +}

+static VALUE
+fix_rshift(long val, unsigned long i)
+{
if (i >= sizeof(long)*CHAR_BIT-1) {
if (val < 0) return INT2FIX(-1);
@@ -2886,6 +2911,4 @@ static VALUE
int_dotimes(VALUE num)
{

  • VALUE val;
  • RETURN_ENUMERATOR(num, 0, 0);

@@ -3106,6 +3129,6 @@ Init_Numeric(void)
rb_define_method(rb_cFixnum, “[]”, fix_aref, 1);

  • rb_define_method(rb_cFixnum, “<<”, fix_lshift, 1);
  • rb_define_method(rb_cFixnum, “>>”, fix_rshift, 1);
  • rb_define_method(rb_cFixnum, “<<”, rb_fix_lshift, 1);

  • rb_define_method(rb_cFixnum, “>>”, rb_fix_rshift, 1);

    rb_define_method(rb_cFixnum, “to_f”, fix_to_f, 0);
    Index: include/ruby/intern.h
    ===================================================================
    — include/ruby/intern.h (revision 12812)
    +++ include/ruby/intern.h (working copy)
    @@ -115,4 +116,5 @@ VALUE rb_big_or(VALUE, VALUE);
    VALUE rb_big_xor(VALUE, VALUE);
    VALUE rb_big_lshift(VALUE, VALUE);
    +VALUE rb_big_rshift(VALUE, VALUE);
    /* class.c */
    VALUE rb_class_boot(VALUE);
    Index: test/ruby/test_integer.rb
    ===================================================================
    — test/ruby/test_integer.rb (revision 12812)
    +++ test/ruby/test_integer.rb (working copy)
    @@ -234,4 +234,8 @@ class TestInteger < Test::Unit::TestCase
    }
    }

  • assert_equal(0, 1 << -0x40000000)

  • assert_equal(0, 1 << -0x40000000)

  • assert_equal(0, 1 << -0x80000000)

  • assert_equal(0, 1 << -0x80000001)
    end

@@ -249,4 +253,5 @@ class TestInteger < Test::Unit::TestCase
}
}

  • assert_equal((1 << 0x40000000), (1 >> -0x40000000))
    end

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:31256] Re: shift”
on Thu, 19 Jul 2007 00:42:03 +0900, Nobuyoshi N.
[email protected] writes:

|At Wed, 18 Jul 2007 17:24:12 +0900,
|Tanaka A. wrote in [ruby-dev:31249]:
|> e$B$G$b!"D>$C$F$J$$$+$s$8e(B?
|
|e$B$?$7$+$K!#%F%9%H$bDI2C$7$^$7$?!#e(B

e$B%3%_%C%H$7$F$/$@$5$$!#e(B

e$B$G$b!"e(Bunsigned longe$B$KBP$7$F$Oe(BLONG2NUM
e$B$h$j$Oe(BULONG2NUMe$B$r;H$C$?e(B
e$BJ}$,$h$$$+$b$7$l$^$;$s!#e(B

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

At Wed, 18 Jul 2007 16:53:59 +0900,
Tanaka A. wrote in [ruby-dev:31246]:

e$B$3$s$J$H$3$m$G$I$&$G$7$g$&$+!#e(B

e$B$H$j$"$($:e(B rb_big_odd_p e$B$,$J$$$h$&$G$9!#e(B

e$B$9$$$^$;$s!"e(Brb_big_powe$B$NItJ,$OM>J,$G$7$?!#$=$3$O85$N$^$^$G!#e(B

In article
[email protected],
Nobuyoshi N. [email protected] writes:

e$B$9$$$^$;$s!"e(Brb_big_powe$B$NItJ,$OM>J,$G$7$?!#$=$3$O85$N$^$^$G!#e(B

e$B$"!<$d$O$j!#e(B

e$B$G$b!"D>$C$F$J$$$+$s$8e(B?

% ./ruby -e ‘p((1 << -0x40000001).size)’
134217732

% ./ruby -e ‘p 1 >> -0x40000001’
0

% ./ruby -e ‘p (1 >> 0x80000000).size’
268435460

e$B$"$H$5$i$K!#e(B

% ./ruby -e ‘p 1 >> 0xffffffff’
2

% ./ruby -e ‘p 1 >> 0x100000000’
-e:1:in >>': bignum too big to convert into long’ (RangeError)
from -e:1:in `’

% ./ruby -e ‘p 1 << 0x80000000’
0

% ./ruby -e ‘p 1 << 0xffffffff’
0

In article
[email protected],
Nobuyoshi N. [email protected] writes:

e$B$?$7$+$K!#%F%9%H$bDI2C$7$^$7$?!#e(B

e$BD>$C$?$+$s$8$G$9!#e(B

e$B$?$@!“$H$F$bBg$-$JCM$r%F%9%H$9$k$N$O;DG0$G$9$,$”$^$j$h$m$7$/e(B
e$B$J$$$H;W$$$^$9!#e(B

e$B@$$NCf$$$D$b%a%b%j$r;H$$J|Bj$H$$$&$o$1$G$O$"$j$^$;$s$7!#e(B

  • assert_equal(bdsize(0x80000000), (1 << 0x80000000).size)
  • assert_equal(bdsize(0x40000001), (1 >> -0x40000001).size)
  • assert_equal((1 << 0x40000000), (1 >> -0x40000000))
  • assert_equal((1 << 0x40000001), (1 >> -0x40000001))

1 << 0x80000000 e$B$Ge(B 256Mbytes e$B$O$A$g$C$He(B…

e$B$3$N$“$?$j$N5sF0$r%F%9%H$7$J$$7gE@$h$j$b!”%a%b%j$,>.$5$$%^%7e(B
e$B%s$G$b%F%9%H$,$^$H$b$KF0$/$H$$$&MxE@$N$[$&$,Bg$-$$$H;W$$$^$9!#e(B

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

At Wed, 18 Jul 2007 17:24:12 +0900,
Tanaka A. wrote in [ruby-dev:31249]:

e$B$G$b!"D>$C$F$J$$$+$s$8e(B?

e$B$?$7$+$K!#%F%9%H$bDI2C$7$^$7$?!#e(B

Index: bignum.c

— bignum.c (revision 12813)
+++ bignum.c (working copy)
@@ -1530,5 +1530,15 @@ bdigbitsize(BDIGIT x)
}

-static VALUE rb_big_rshift(VALUE,VALUE);
+static VALUE big_lshift(VALUE, unsigned int);
+static VALUE big_rshift(VALUE, unsigned int);
+
+static VALUE big_shift(VALUE x, int n)
+{

  • if (n < 0)
  • return big_lshift(x, (unsigned int)n);
  • else if (n > 0)
  • return big_rshift(x, (unsigned int)n);
  • return x;
    +}

/*
@@ -1559,5 +1569,5 @@ rb_big_quo(VALUE x, VALUE y)
ex += bdigbitsize(BDIGITS(x)[RBIGNUM(x)->len - 1]);
ex -= 2 * DBL_BIGDIG * BITSPERDIG;

  • if (ex) x = rb_big_rshift(x, INT2FIX(ex));
  • if (ex) x = big_shift(x, ex);

    switch (TYPE(y)) {
    @@ -1568,5 +1578,5 @@ rb_big_quo(VALUE x, VALUE y)
    ey += bdigbitsize(BDIGITS(y)[RBIGNUM(y)->len - 1]);
    ey -= DBL_BIGDIG * BITSPERDIG;

  •  if (ey) y = rb_big_rshift(y, INT2FIX(ey));
    
  •  if (ey) y = big_shift(y, ey);
    
    bignum:
    bigdivrem(x, y, &z, 0);
    @@ -1873,4 +1883,14 @@ rb_big_xor(VALUE xx, VALUE yy)
    }

+static VALUE
+check_shiftdown(VALUE y, VALUE x)
+{

  • if (!RBIGNUM(x)->len) return INT2FIX(0);
  • if (RBIGNUM(y)->len > SIZEOF_LONG / SIZEOF_BDIGITS) {
  • return RBIGNUM(x)->sign ? INT2FIX(0) : INT2FIX(-1);
  • }
  • return Qnil;
    +}

/*

  • call-seq:
    @@ -1883,6 +1903,35 @@ VALUE
    rb_big_lshift(VALUE x, VALUE y)
    {
  • int shift, neg = 0;
  • for (;:wink: {
  • if (FIXNUM_P(y)) {
  •  shift = FIX2INT(y);
    
  •  if (shift < 0) {
    
  • neg = 1;
  • shift = -shift;
  •  }
    
  •  break;
    
  • }
  • else if (TYPE(y) == T_BIGNUM) {
  •  if (!RBIGNUM(y)->sign) {
    
  • VALUE t = check_shiftdown(y, x);
  • if (!NIL_P(t)) return t;
  • neg = 1;
  •  }
    
  •  shift = big2ulong(y, "long", Qtrue);
    
  •  break;
    
  • }
  • y = rb_to_int(y);
  • }
  • if (neg) return big_rshift(x, shift);
  • return big_lshift(x, shift);
    +}

+static VALUE
+big_lshift(VALUE x, unsigned int shift)
+{
BDIGIT *xds, *zds;

  • int shift = NUM2INT(y);
    int s1 = shift/BITSPERDIG;
    int s2 = shift%BITSPERDIG;
    @@ -1891,5 +1940,4 @@ rb_big_lshift(VALUE x, VALUE y)
    long len, i;

  • if (shift < 0) return rb_big_rshift(x, INT2FIX(-shift));
    len = RBIGNUM(x)->len;
    z = bignew(len+s1+1, RBIGNUM(x)->sign);
    @@ -1915,9 +1963,41 @@ rb_big_lshift(VALUE x, VALUE y)
    */

-static VALUE
+VALUE
rb_big_rshift(VALUE x, VALUE y)
{

  • int shift;
  • int neg = 0;
  • for (;:wink: {
  • if (FIXNUM_P(y)) {
  •  shift = FIX2INT(y);
    
  •  if (shift < 0) {
    
  • neg = 1;
  • shift = -shift;
  •  }
    
  •  break;
    
  • }
  • else if (TYPE(y) == T_BIGNUM) {
  •  if (RBIGNUM(y)->sign) {
    
  • VALUE t = check_shiftdown(y, x);
  • if (!NIL_P(t)) return t;
  •  }
    
  •  else {
    
  • neg = 1;
  •  }
    
  •  shift = big2ulong(y, "long", Qtrue);
    
  •  break;
    
  • }
  • y = rb_to_int(y);
  • }
  • if (neg) return big_lshift(x, shift);
  • return big_rshift(x, shift);
    +}

+static VALUE
+big_rshift(VALUE x, unsigned int shift)
+{
BDIGIT *xds, *zds;

  • int shift = NUM2INT(y);
    long s1 = shift/BITSPERDIG;
    long s2 = shift%BITSPERDIG;
    @@ -1927,6 +2007,4 @@ rb_big_rshift(VALUE x, VALUE y)
    volatile VALUE save_x;

  • if (shift < 0) return rb_big_lshift(x, INT2FIX(-shift));

  • if (s1 > RBIGNUM(x)->len) {
    if (RBIGNUM(x)->sign)
    Index: numeric.c
    ===================================================================
    — numeric.c (revision 12813)
    +++ numeric.c (working copy)
    @@ -2592,5 +2592,6 @@ fix_xor(VALUE x, VALUE y)
    }

-static VALUE fix_rshift(VALUE, VALUE);
+static VALUE fix_lshift(long, unsigned long);
+static VALUE fix_rshift(long, unsigned long);

/*
@@ -2602,15 +2603,23 @@ static VALUE fix_rshift(VALUE, VALUE);

static VALUE
-fix_lshift(VALUE x, VALUE y)
+rb_fix_lshift(VALUE x, VALUE y)
{
long val, width;

 val = NUM2LONG(x);
  • width = NUM2LONG(y);
  • if (!FIXNUM_P(y))
  • return rb_big_lshift(rb_int2big(val), y);
  • width = FIX2LONG(y);
    if (width < 0)
  • return fix_rshift(x, LONG2FIX(-width));
  • return fix_rshift(val, (unsigned long)-width);
  • return fix_lshift(val, width);
    +}

+static VALUE
+fix_lshift(long val, unsigned long width)
+{
if (width > (sizeof(VALUE)*CHAR_BIT-1)
|| ((unsigned long)val)>>(sizeof(VALUE)*CHAR_BIT-1-width) > 0) {

  • return rb_big_lshift(rb_int2big(val), y);
  • return rb_big_lshift(rb_int2big(val), LONG2NUM(width));
    }
    val = val << width;
    @@ -2626,13 +2635,21 @@ fix_lshift(VALUE x, VALUE y)

static VALUE
-fix_rshift(VALUE x, VALUE y)
+rb_fix_rshift(VALUE x, VALUE y)
{
long i, val;

  • i = NUM2LONG(y);
  • if (i < 0)
  • return fix_lshift(x, LONG2FIX(-i));
  • if (i == 0) return x;
    val = FIX2LONG(x);
  • if (!FIXNUM_P(y))
  • return rb_big_rshift(rb_int2big(val), y);
  • i = FIX2LONG(y);
  • if (i == 0) return x;
  • if (i < 0)
  • return fix_lshift(val, (unsigned long)-i);
  • return fix_rshift(val, i);
    +}

+static VALUE
+fix_rshift(long val, unsigned long i)
+{
if (i >= sizeof(long)*CHAR_BIT-1) {
if (val < 0) return INT2FIX(-1);
@@ -2886,6 +2903,4 @@ static VALUE
int_dotimes(VALUE num)
{

  • VALUE val;
  • RETURN_ENUMERATOR(num, 0, 0);

@@ -3106,6 +3121,6 @@ Init_Numeric(void)
rb_define_method(rb_cFixnum, “[]”, fix_aref, 1);

  • rb_define_method(rb_cFixnum, “<<”, fix_lshift, 1);
  • rb_define_method(rb_cFixnum, “>>”, fix_rshift, 1);
  • rb_define_method(rb_cFixnum, “<<”, rb_fix_lshift, 1);

  • rb_define_method(rb_cFixnum, “>>”, rb_fix_rshift, 1);

    rb_define_method(rb_cFixnum, “to_f”, fix_to_f, 0);
    Index: include/ruby/intern.h
    ===================================================================
    — include/ruby/intern.h (revision 12813)
    +++ include/ruby/intern.h (working copy)
    @@ -115,4 +115,5 @@ VALUE rb_big_or(VALUE, VALUE);
    VALUE rb_big_xor(VALUE, VALUE);
    VALUE rb_big_lshift(VALUE, VALUE);
    +VALUE rb_big_rshift(VALUE, VALUE);
    /* class.c */
    VALUE rb_class_boot(VALUE);
    Index: test/ruby/test_integer.rb
    ===================================================================
    — test/ruby/test_integer.rb (revision 12813)
    +++ test/ruby/test_integer.rb (working copy)
    @@ -94,4 +94,12 @@ class TestInteger < Test::Unit::TestCase
    #VS.map! {|v| 0x4000000000000000.coerce(v)[0] }

  • BDSIZE = 0x4000000000000000.coerce(0)[0].size

  • def self.bdsize(x)

  • ((x + 1) / 8 + BDSIZE) / BDSIZE * BDSIZE

  • end

  • def bdsize(x)

  • self.class.bdsize(x)

  • end

  • def test_aref
    VS.each {|a|
    @@ -234,4 +242,9 @@ class TestInteger < Test::Unit::TestCase
    }
    }

  • assert_equal(0, 1 << -0x40000000)

  • assert_equal(0, 1 << -0x40000001)

  • assert_equal(0, 1 << -0x80000000)

  • assert_equal(0, 1 << -0x80000001)

  • assert_equal(bdsize(0x80000000), (1 << 0x80000000).size)
    end

@@ -249,4 +262,10 @@ class TestInteger < Test::Unit::TestCase
}
}

  • assert_equal(bdsize(0x40000001), (1 >> -0x40000001).size)
  • assert((1 >> 0x80000000).zero?)
  • assert((1 >> 0xffffffff).zero?)
  • assert((1 >> 0x100000000).zero?)
  • assert_equal((1 << 0x40000000), (1 >> -0x40000000))
  • assert_equal((1 << 0x40000001), (1 >> -0x40000001))
    end