1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@14329 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2007-12-19 10:13:03 +00:00
parent e7e4d03a6e
commit 8acb0fbd4d
2 changed files with 89 additions and 20 deletions

View file

@ -1,3 +1,10 @@
Wed Dec 19 19:11:08 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
* 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@atdot.net>
* compile.c (iseq_compile_each): remove "retry" in block.

102
bignum.c
View file

@ -1442,34 +1442,32 @@ rb_big_minus(VALUE x, VALUE y)
}
}
static VALUE
rb_big_mul0(VALUE x, VALUE y)
static void
rb_big_stop(void *ptr)
{
VALUE *stop = (VALUE*)ptr;
*stop = Qtrue;
}
struct big_mul_struct {
VALUE x, y, stop;
};
static VALUE
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 @@ rb_big_mul0(VALUE x, VALUE y)
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 @@ rb_big_mul(VALUE x, VALUE y)
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 @@ bigdivrem(VALUE x, VALUE y, VALUE *divp, VALUE *modp)
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 @@ bigdivrem(VALUE x, VALUE y, VALUE *divp, VALUE *modp)
}
}
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)
{