[前][次][番号順一覧][スレッド一覧]

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

[前][次][番号順一覧][スレッド一覧]