ruby-changes:1697
From: ko1@a...
Date: 22 Aug 2007 10:50:37 +0900
Subject: [ruby-changes:1697] shyouhei - Ruby:r13188 (ruby_1_8_6): * bignum.c (rb_big_lshift, rb_big_rshift): separated functions
shyouhei 2007-08-22 10:50:21 +0900 (Wed, 22 Aug 2007)
New Revision: 13188
Modified files:
branches/ruby_1_8_6/ChangeLog
branches/ruby_1_8_6/bignum.c
branches/ruby_1_8_6/intern.h
branches/ruby_1_8_6/numeric.c
branches/ruby_1_8_6/version.h
Log:
* bignum.c (rb_big_lshift, rb_big_rshift): separated functions
to get rid of infinite recursion. fixed calculation in edge
cases. [ruby-dev:31244]
* numeric.c (rb_fix_lshift, rb_fix_rshift): ditto.
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8_6/intern.h?r1=13188&r2=13187
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8_6/ChangeLog?r1=13188&r2=13187
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8_6/version.h?r1=13188&r2=13187
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8_6/numeric.c?r1=13188&r2=13187
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8_6/bignum.c?r1=13188&r2=13187
Index: ruby_1_8_6/intern.h
===================================================================
--- ruby_1_8_6/intern.h (revision 13187)
+++ ruby_1_8_6/intern.h (revision 13188)
@@ -114,6 +114,7 @@
VALUE rb_class_instance_methods _((int, VALUE*, VALUE));
VALUE rb_class_public_instance_methods _((int, VALUE*, VALUE));
VALUE rb_class_protected_instance_methods _((int, VALUE*, VALUE));
+VALUE rb_big_rshift(VALUE, VALUE);
VALUE rb_class_private_instance_methods _((int, VALUE*, VALUE));
VALUE rb_obj_singleton_methods _((int, VALUE*, VALUE));
void rb_define_method_id _((VALUE, ID, VALUE (*)(ANYARGS), int));
Index: ruby_1_8_6/numeric.c
===================================================================
--- ruby_1_8_6/numeric.c (revision 13187)
+++ ruby_1_8_6/numeric.c (revision 13188)
@@ -2457,7 +2457,8 @@
return LONG2NUM(val);
}
-static VALUE fix_rshift _((VALUE, VALUE));
+static VALUE fix_lshift _((long, unsigned long));
+static VALUE fix_rshift _((long, unsigned long));
/*
* call-seq:
@@ -2467,18 +2468,28 @@
*/
static VALUE
-fix_lshift(x, y)
+rb_fix_lshift(x, y)
VALUE x, 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(val, width)
+ 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), ULONG2NUM(width));
}
val = val << width;
return LONG2NUM(val);
@@ -2492,16 +2503,24 @@
*/
static VALUE
-fix_rshift(x, y)
+rb_fix_rshift(x, y)
VALUE x, y;
{
long i, val;
- i = NUM2LONG(y);
+ 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(x, LONG2FIX(-i));
- if (i == 0) return x;
- val = FIX2LONG(x);
+ 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);
return INT2FIX(0);
@@ -2902,8 +2921,8 @@
rb_define_method(rb_cFixnum, "^", fix_xor, 1);
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);
rb_define_method(rb_cFixnum, "size", fix_size, 0);
Index: ruby_1_8_6/ChangeLog
===================================================================
--- ruby_1_8_6/ChangeLog (revision 13187)
+++ ruby_1_8_6/ChangeLog (revision 13188)
@@ -1,3 +1,11 @@
+Wed Aug 22 10:36:15 2007 Nobuyoshi Nakada <nobu@r...>
+
+ * bignum.c (rb_big_lshift, rb_big_rshift): separated functions
+ to get rid of infinite recursion. fixed calculation in edge
+ cases. [ruby-dev:31244]
+
+ * numeric.c (rb_fix_lshift, rb_fix_rshift): ditto.
+
Wed Aug 22 10:29:45 2007 Nobuyoshi Nakada <nobu@r...>
* bignum.c (rb_big_pow): refine overflow check. [ruby-dev:31242]
Index: ruby_1_8_6/version.h
===================================================================
--- ruby_1_8_6/version.h (revision 13187)
+++ ruby_1_8_6/version.h (revision 13188)
@@ -2,7 +2,7 @@
#define RUBY_RELEASE_DATE "2007-08-22"
#define RUBY_VERSION_CODE 186
#define RUBY_RELEASE_CODE 20070822
-#define RUBY_PATCHLEVEL 70
+#define RUBY_PATCHLEVEL 71
#define RUBY_VERSION_MAJOR 1
#define RUBY_VERSION_MINOR 8
Index: ruby_1_8_6/bignum.c
===================================================================
--- ruby_1_8_6/bignum.c (revision 13187)
+++ ruby_1_8_6/bignum.c (revision 13188)
@@ -1544,6 +1544,20 @@
return bignorm(z);
}
+static VALUE big_lshift _((VALUE, unsigned int));
+static VALUE big_rshift _((VALUE, unsigned int));
+
+static VALUE big_shift(x, n)
+ 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;
+}
+
/*
* call-seq:
* big.divmod(numeric) => array
@@ -1849,7 +1863,15 @@
return bignorm(z);
}
-static VALUE rb_big_rshift _((VALUE,VALUE));
+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:
@@ -1862,15 +1884,45 @@
rb_big_lshift(x, y)
VALUE x, 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(x, shift)
+ VALUE x;
+ unsigned int shift;
+{
BDIGIT *xds, *zds;
- int shift = NUM2INT(y);
int s1 = shift/BITSPERDIG;
int s2 = shift%BITSPERDIG;
VALUE z;
BDIGIT_DBL num = 0;
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);
zds = BDIGITS(z);
@@ -1894,12 +1946,46 @@
* Shifts big right _numeric_ positions (left if _numeric_ is negative).
*/
-static VALUE
+VALUE
rb_big_rshift(x, y)
VALUE x, 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(x, shift)
+ VALUE x;
+ unsigned int shift;
+{
BDIGIT *xds, *zds;
- int shift = NUM2INT(y);
long s1 = shift/BITSPERDIG;
long s2 = shift%BITSPERDIG;
VALUE z;
@@ -1907,8 +1993,6 @@
long i, j;
volatile VALUE save_x;
- if (shift < 0) return rb_big_lshift(x, INT2FIX(-shift));
-
if (s1 > RBIGNUM(x)->len) {
if (RBIGNUM(x)->sign)
return INT2FIX(0);
--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml