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

ruby-changes:2838

From: ko1@a...
Date: 19 Dec 2007 19:13:41 +0900
Subject: [ruby-changes:2838] matz - Ruby:r14329 (trunk): * bignum.c (rb_big_mul0): blocking check for bigger numbers.

matz	2007-12-19 19:13:03 +0900 (Wed, 19 Dec 2007)

  New Revision: 14329

  Modified files:
    trunk/ChangeLog
    trunk/bignum.c

  Log:
    * bignum.c (rb_big_mul0): blocking check for bigger numbers.
      a patch from Yusuke ENDOH <mame AT tsg.ne.jp> in [ruby-dev:32632].
    
    * bignum.c (bigdivrem): ditto.

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=14329&r2=14328
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/bignum.c?r1=14329&r2=14328

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 14328)
+++ ChangeLog	(revision 14329)
@@ -1,3 +1,10 @@
+Wed Dec 19 19:11:08 2007  Yukihiro Matsumoto  <matz@r...>
+
+	* bignum.c (rb_big_mul0): blocking check for bigger numbers.
+	  a patch from Yusuke ENDOH <mame AT tsg.ne.jp> in [ruby-dev:32632].
+
+	* bignum.c (bigdivrem): ditto.
+
 Wed Dec 19 17:34:50 2007  Koichi Sasada  <ko1@a...>
 
 	* compile.c (iseq_compile_each): remove "retry" in block.
Index: bignum.c
===================================================================
--- bignum.c	(revision 14328)
+++ bignum.c	(revision 14329)
@@ -1442,34 +1442,32 @@
     }
 }
 
+static void
+rb_big_stop(void *ptr)
+{
+    VALUE *stop = (VALUE*)ptr;
+    *stop = Qtrue;
+}
+
+struct big_mul_struct {
+    VALUE x, y, stop;
+};
+
 static VALUE
-rb_big_mul0(VALUE x, VALUE y)
+bigmul1(void *ptr)
 {
+    struct big_mul_struct *bms = (struct big_mul_struct*)ptr;
     long i, j;
     BDIGIT_DBL n = 0;
-    VALUE z;
+    VALUE x = bms->x, y = bms->y, z;
     BDIGIT *zds;
 
-    switch (TYPE(y)) {
-      case T_FIXNUM:
-	y = rb_int2big(FIX2LONG(y));
-	break;
-
-      case T_BIGNUM:
-	break;
-
-      case T_FLOAT:
-	return DOUBLE2NUM(rb_big2dbl(x) * RFLOAT_VALUE(y));
-
-      default:
-	return rb_num_coerce_bin(x, y);
-    }
-
     j = RBIGNUM_LEN(x) + RBIGNUM_LEN(y) + 1;
     z = bignew(j, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
     zds = BDIGITS(z);
     while (j--) zds[j] = 0;
     for (i = 0; i < RBIGNUM_LEN(x); i++) {
+	if (bms->stop) return Qnil;
 	BDIGIT_DBL dd = BDIGITS(x)[i];
 	if (dd == 0) continue;
 	n = 0;
@@ -1486,6 +1484,42 @@
     return z;
 }
 
+static VALUE
+rb_big_mul0(VALUE x, VALUE y)
+{
+    struct big_mul_struct bms;
+    VALUE z;
+
+    switch (TYPE(y)) {
+      case T_FIXNUM:
+	y = rb_int2big(FIX2LONG(y));
+	break;
+
+      case T_BIGNUM:
+	break;
+
+      case T_FLOAT:
+	return DOUBLE2NUM(rb_big2dbl(x) * RFLOAT_VALUE(y));
+
+      default:
+	return rb_num_coerce_bin(x, y);
+    }
+
+    bms.x = x;
+    bms.y = y;
+    bms.stop = Qfalse;
+
+    if (RBIGNUM_LEN(x) + RBIGNUM_LEN(y) > 10000) {
+	VALUE stop = Qfalse;
+	z = rb_thread_blocking_region(bigmul1, &bms, rb_big_stop, &bms.stop);
+    }
+    else {
+	z = bigmul1(&bms);
+    }
+
+    return z;
+}
+
 /*
  *  call-seq:
  *     big * other  => Numeric
@@ -1499,9 +1533,15 @@
     return bignorm(rb_big_mul0(x, y));
 }
 
-static void
-bigdivrem(VALUE x, VALUE y, VALUE *divp, VALUE *modp)
+struct big_div_struct {
+    VALUE x, y, *divp, *modp, stop;
+};
+
+static VALUE
+bigdivrem1(void *ptr)
 {
+    struct big_div_struct *bds = (struct big_div_struct*)ptr;
+    VALUE x = bds->x, y = bds->y, *divp = bds->divp, *modp = bds->modp;
     long nx = RBIGNUM_LEN(x), ny = RBIGNUM_LEN(y);
     long i, j;
     VALUE yy, z;
@@ -1575,6 +1615,7 @@
 
     j = nx==ny?nx+1:nx;
     do {
+	if (bds->stop) return Qnil;
 	if (zds[j] ==  yds[ny-1]) q = BIGRAD-1;
 	else q = (BDIGIT)((BIGUP(zds[j]) + zds[j-1])/yds[ny-1]);
 	if (q) {
@@ -1627,6 +1668,27 @@
     }
 }
 
+static VALUE
+bigdivrem(VALUE x, VALUE y, VALUE *divp, VALUE *modp)
+{
+    struct big_div_struct bds;
+    VALUE z;
+
+    bds.x = x;
+    bds.y = y;
+    bds.divp = divp;
+    bds.modp = modp;
+    bds.stop = Qfalse;
+    if (RBIGNUM_LEN(x) > 10000 || RBIGNUM_LEN(y) > 10000) {
+	VALUE stop = Qfalse;
+	z = rb_thread_blocking_region(bigdivrem1, &bds, rb_big_stop, &bds.stop);
+    }
+    else {
+	z = bigdivrem1(&bds);
+    }
+    return z;
+}
+
 static void
 bigdivmod(VALUE x, VALUE y, VALUE *divp, VALUE *modp)
 {

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml

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