From 67212c5ba4e7955f9def6213e00bddd91675ef19 Mon Sep 17 00:00:00 2001 From: mame Date: Tue, 29 Jan 2008 12:58:24 +0000 Subject: * bignum.c: move object allocation out of blocking_region. [ruby-dev:33139] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@15322 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 +++ bignum.c | 122 ++++++++++++++++++++++++++++++++------------------------------ 2 files changed, 69 insertions(+), 58 deletions(-) diff --git a/ChangeLog b/ChangeLog index fddaa4d165..04d09e2173 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Tue Jan 29 21:55:35 2008 Yusuke Endoh + + * bignum.c: move object allocation out of blocking_region. + [ruby-dev:33139] + Tue Jan 29 20:37:36 2008 NARUSE, Yui * enc/trans/make_transdb.rb: add for make transdb.h. diff --git a/bignum.c b/bignum.c index 4a4bdbd9d4..ec5b8e8cce 100644 --- a/bignum.c +++ b/bignum.c @@ -1449,7 +1449,7 @@ rb_big_stop(void *ptr) } struct big_mul_struct { - VALUE x, y, stop; + VALUE x, y, z, stop; }; static VALUE @@ -1458,11 +1458,10 @@ bigmul1(void *ptr) struct big_mul_struct *bms = (struct big_mul_struct*)ptr; long i, j; BDIGIT_DBL n = 0; - VALUE x = bms->x, y = bms->y, z; + VALUE x = bms->x, y = bms->y, z = bms->z; BDIGIT *zds; 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++) { @@ -1488,7 +1487,7 @@ static VALUE rb_big_mul0(VALUE x, VALUE y) { struct big_mul_struct bms; - VALUE z; + volatile VALUE z; switch (TYPE(y)) { case T_FIXNUM: @@ -1507,6 +1506,7 @@ rb_big_mul0(VALUE x, VALUE y) bms.x = x; bms.y = y; + bms.z = bignew(RBIGNUM_LEN(x) + RBIGNUM_LEN(y) + 1, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y)); bms.stop = Qfalse; if (RBIGNUM_LEN(x) + RBIGNUM_LEN(y) > 10000) { @@ -1533,20 +1533,64 @@ rb_big_mul(VALUE x, VALUE y) } struct big_div_struct { - VALUE x, y, *divp, *modp, stop; + long nx, ny; + BDIGIT *yds, *zds; + VALUE 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 = bds->nx, ny = bds->ny; + long i, j; + BDIGIT *yds = bds->yds, *zds = bds->zds; + BDIGIT_DBL t2; + BDIGIT_DBL_SIGNED num; + BDIGIT q; + + 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) { + i = 0; num = 0; t2 = 0; + do { /* multiply and subtract */ + BDIGIT_DBL ee; + t2 += (BDIGIT_DBL)yds[i] * q; + ee = num - BIGLO(t2); + num = (BDIGIT_DBL)zds[j - ny + i] + ee; + if (ee) zds[j - ny + i] = BIGLO(num); + num = BIGDN(num); + t2 = BIGDN(t2); + } while (++i < ny); + num += zds[j - ny + i] - t2;/* borrow from high digit; don't update */ + while (num) { /* "add back" required */ + i = 0; num = 0; q--; + do { + BDIGIT_DBL ee = num + yds[i]; + num = (BDIGIT_DBL)zds[j - ny + i] + ee; + if (ee) zds[j - ny + i] = BIGLO(num); + num = BIGDN(num); + } while (++i < ny); + num--; + } + } + zds[j] = q; + } while (--j >= ny); + return Qnil; +} + +static VALUE +bigdivrem(VALUE x, VALUE y, VALUE *divp, VALUE *modp) +{ + struct big_div_struct bds; long nx = RBIGNUM_LEN(x), ny = RBIGNUM_LEN(y); long i, j; - VALUE yy, z; + volatile VALUE yy, z; BDIGIT *xds, *yds, *zds, *tds; BDIGIT_DBL t2; - BDIGIT_DBL_SIGNED num; BDIGIT dd, q; if (BIGZEROP(y)) rb_num_zerodiv(); @@ -1612,36 +1656,18 @@ bigdivrem1(void *ptr) while (j--) zds[j] = xds[j]; } - 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) { - i = 0; num = 0; t2 = 0; - do { /* multiply and subtract */ - BDIGIT_DBL ee; - t2 += (BDIGIT_DBL)yds[i] * q; - ee = num - BIGLO(t2); - num = (BDIGIT_DBL)zds[j - ny + i] + ee; - if (ee) zds[j - ny + i] = BIGLO(num); - num = BIGDN(num); - t2 = BIGDN(t2); - } while (++i < ny); - num += zds[j - ny + i] - t2;/* borrow from high digit; don't update */ - while (num) { /* "add back" required */ - i = 0; num = 0; q--; - do { - BDIGIT_DBL ee = num + yds[i]; - num = (BDIGIT_DBL)zds[j - ny + i] + ee; - if (ee) zds[j - ny + i] = BIGLO(num); - num = BIGDN(num); - } while (++i < ny); - num--; - } - } - zds[j] = q; - } while (--j >= ny); + bds.nx = nx; + bds.ny = ny; + bds.zds = zds; + bds.yds = yds; + bds.stop = Qfalse; + if (RBIGNUM_LEN(x) > 10000 || RBIGNUM_LEN(y) > 10000) { + rb_thread_blocking_region(bigdivrem1, &bds, rb_big_stop, &bds.stop); + } + else { + bigdivrem1(&bds); + } + if (divp) { /* move quotient down in z */ *divp = rb_big_clone(z); zds = BDIGITS(*divp); @@ -1665,26 +1691,6 @@ bigdivrem1(void *ptr) RBIGNUM_SET_LEN(*modp, ny); RBIGNUM_SET_SIGN(*modp, RBIGNUM_SIGN(x)); } - return Qnil; -} - -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) { - z = rb_thread_blocking_region(bigdivrem1, &bds, rb_big_stop, &bds.stop); - } - else { - z = bigdivrem1(&bds); - } return z; } -- cgit v1.2.3