# Shift

**URL:** <https://www.ruby-forum.com/t/shift/109706>\
**Category:** Development\
**Created:** [July 18, 2007, 5:43am UTC](https://www.ruby-forum.com/t/shift/109706 "2007-07-18T05:43:34Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tanaka\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c67d28/32.png) [@Tanaka\_A](https://www.ruby-forum.com/u/Tanaka_A)\
**Post date:** [July 18, 2007, 5:43am UTC](https://www.ruby-forum.com/t/shift/109706/1 "2007-07-18T05:43:34Z")

</div>

-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 into`long’ (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 into`long’  
\>\>(RangeError)  
from -e:1:in `’

---

<div class="post-metadata">

**Author:** ![Tanaka\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c67d28/32.png) [@Tanaka\_A](https://www.ruby-forum.com/u/Tanaka_A)\
**Post date:** [July 18, 2007, 9:54am UTC](https://www.ruby-forum.com/t/shift/109706/2 "2007-07-18T09:54:56Z")

</div>

In article  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid),  
Nobuyoshi N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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

---

<div class="post-metadata">

**Author:** ![Tanaka\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c67d28/32.png) [@Tanaka\_A](https://www.ruby-forum.com/u/Tanaka_A)\
**Post date:** [July 18, 2007, 9:43am UTC](https://www.ruby-forum.com/t/shift/109706/3 "2007-07-18T09:43:55Z")

</div>

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);

- 

```
 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;

- 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 (;😉 {
- 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 (;😉 {
- 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);

- 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

---

<div class="post-metadata">

**Author:** ![Tanaka\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c67d28/32.png) [@Tanaka\_A](https://www.ruby-forum.com/u/Tanaka_A)\
**Post date:** [September 25, 2007, 11:04pm UTC](https://www.ruby-forum.com/t/shift/109706/4 "2007-09-25T23:04:05Z")

</div>

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.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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

---

<div class="post-metadata">

**Author:** ![Tanaka\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c67d28/32.png) [@Tanaka\_A](https://www.ruby-forum.com/u/Tanaka_A)\
**Post date:** [July 18, 2007, 10:53am UTC](https://www.ruby-forum.com/t/shift/109706/5 "2007-07-18T10:53:05Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Tanaka\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c67d28/32.png) [@Tanaka\_A](https://www.ruby-forum.com/u/Tanaka_A)\
**Post date:** [September 25, 2007, 11:05pm UTC](https://www.ruby-forum.com/t/shift/109706/6 "2007-09-25T23:05:48Z")

</div>

In article  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid),  
Nobuyoshi N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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

---

<div class="post-metadata">

**Author:** ![Tanaka\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c67d28/32.png) [@Tanaka\_A](https://www.ruby-forum.com/u/Tanaka_A)\
**Post date:** [September 25, 2007, 11:11pm UTC](https://www.ruby-forum.com/t/shift/109706/7 "2007-09-25T23:11:08Z")

</div>

In article  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid),  
Nobuyoshi N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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

---

<div class="post-metadata">

**Author:** ![Tanaka\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c67d28/32.png) [@Tanaka\_A](https://www.ruby-forum.com/u/Tanaka_A)\
**Post date:** [September 25, 2007, 11:04pm UTC](https://www.ruby-forum.com/t/shift/109706/8 "2007-09-25T23:04:59Z")

</div>

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);

- 

```
 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 (;😉 {
- 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 (;😉 {
- 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);

- 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
