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