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 = 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)
+{
/*
- call-seq:
@@ -1881,6 +1921,30 @@ VALUE
rb_big_lshift(VALUE x, VALUE y)
{
+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)
{
+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);
- 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