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