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:
parent
e7e4d03a6e
commit
8acb0fbd4d
2 changed files with 89 additions and 20 deletions
|
@ -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
102
bignum.c
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue