ruby-changes:12909
From: nobu <ko1@a...>
Date: Tue, 25 Aug 2009 17:38:52 +0900 (JST)
Subject: [ruby-changes:12909] Ruby:r24645 (trunk): * bignum.c (rb_big_clone, bigmul1_normal, bigdivrem): trivial
nobu 2009-08-25 17:38:28 +0900 (Tue, 25 Aug 2009) New Revision: 24645 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=24645 Log: * bignum.c (rb_big_clone, bigmul1_normal, bigdivrem): trivial optimization. * bignum.c (big2dbl): truncates zero digits to get rid of possible underflow. Modified files: trunk/ChangeLog trunk/bignum.c Index: ChangeLog =================================================================== --- ChangeLog (revision 24644) +++ ChangeLog (revision 24645) @@ -1,3 +1,11 @@ +Tue Aug 25 17:38:22 2009 Nobuyoshi Nakada <nobu@r...> + + * bignum.c (rb_big_clone, bigmul1_normal, bigdivrem): trivial + optimization. + + * bignum.c (big2dbl): truncates zero digits to get rid of possible + underflow. + Tue Aug 25 12:22:25 2009 Nobuyoshi Nakada <nobu@r...> * Makefile.in (enc/unicode/name2ctype.h): explicitly ignores the Index: bignum.c =================================================================== --- bignum.c (revision 24644) +++ bignum.c (revision 24645) @@ -159,9 +159,10 @@ VALUE rb_big_clone(VALUE x) { - VALUE z = bignew_1(CLASS_OF(x), RBIGNUM_LEN(x), RBIGNUM_SIGN(x)); + long len = RBIGNUM_LEN(x); + VALUE z = bignew_1(CLASS_OF(x), len, RBIGNUM_SIGN(x)); - MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, RBIGNUM_LEN(x)); + MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, len); return z; } @@ -716,7 +717,7 @@ const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz"; static VALUE bigsqr(VALUE x); -static void bigdivmod(VALUE x, VALUE y, VALUE *divp, VALUE *modp); +static void bigdivmod(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp); #define POW2_P(x) (((x)&((x)-1))==0) @@ -1195,7 +1196,7 @@ big2dbl(VALUE x) { double d = 0.0; - long i = RBIGNUM_LEN(x), lo = 0, bits; + long i = (bigtrunc(x), RBIGNUM_LEN(x)), lo = 0, bits; BDIGIT *ds = BDIGITS(x), dl; if (i) { @@ -1747,22 +1748,21 @@ static VALUE bigmul1_normal(VALUE x, VALUE y) { - long i, j; + long xl = RBIGNUM_LEN(x), yl = RBIGNUM_LEN(y), i, j = xl + yl + 1; BDIGIT_DBL n = 0; - VALUE z = bignew(RBIGNUM_LEN(x) + RBIGNUM_LEN(y) + 1, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y)); + VALUE z = bignew(j, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y)); BDIGIT *xds, *yds, *zds; - j = RBIGNUM_LEN(x) + RBIGNUM_LEN(y) + 1; xds = BDIGITS(x); yds = BDIGITS(y); zds = BDIGITS(z); while (j--) zds[j] = 0; - for (i = 0; i < RBIGNUM_LEN(x); i++) { + for (i = 0; i < xl; i++) { BDIGIT_DBL dd; dd = xds[i]; if (dd == 0) continue; n = 0; - for (j = 0; j < RBIGNUM_LEN(y); j++) { + for (j = 0; j < yl; j++) { BDIGIT_DBL ee = n + (BDIGIT_DBL)dd * yds[j]; n = zds[i + j] + ee; if (ee) zds[i + j] = BIGLO(n); @@ -1817,14 +1817,16 @@ /* split a bignum into high and low bignums */ static void -big_split(VALUE v, long n, VALUE *ph, VALUE *pl) +big_split(VALUE v, long n, volatile VALUE *ph, volatile VALUE *pl) { - long hn, ln; + long hn = 0, ln = RBIGNUM_LEN(v); VALUE h, l; BDIGIT *vds = BDIGITS(v); - ln = RBIGNUM_LEN(v) > n ? n : RBIGNUM_LEN(v); - hn = RBIGNUM_LEN(v) - ln; + if (ln > n) { + hn = ln - n; + ln = n; + } while (--hn && !vds[hn + ln]); h = bignew(hn += 2, 1); @@ -2121,24 +2123,24 @@ } static VALUE -bigdivrem(VALUE x, VALUE y, VALUE *divp, VALUE *modp) +bigdivrem(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp) { struct big_div_struct bds; long nx = RBIGNUM_LEN(x), ny = RBIGNUM_LEN(y); long i, j; - volatile VALUE yy, z; + VALUE z, yy, zz; BDIGIT *xds, *yds, *zds, *tds; BDIGIT_DBL t2; BDIGIT dd, q; if (BIGZEROP(y)) rb_num_zerodiv(); + xds = BDIGITS(x); yds = BDIGITS(y); - if (nx < ny || (nx == ny && BDIGITS(x)[nx - 1] < BDIGITS(y)[ny - 1])) { + if (nx < ny || (nx == ny && xds[nx - 1] < yds[ny - 1])) { if (divp) *divp = rb_int2big(0); if (modp) *modp = x; return Qnil; } - xds = BDIGITS(x); if (ny == 1) { dd = yds[0]; z = rb_big_clone(x); @@ -2179,6 +2181,7 @@ t2 = BIGDN(t2); } yds = tds; + RB_GC_GUARD(y) = yy; j = 0; t2 = 0; while (j<nx) { @@ -2199,7 +2202,7 @@ bds.zds = zds; bds.yds = yds; bds.stop = Qfalse; - if (RBIGNUM_LEN(x) > 10000 || RBIGNUM_LEN(y) > 10000) { + if (nx > 10000 || ny > 10000) { rb_thread_blocking_region(bigdivrem1, &bds, rb_big_stop, &bds.stop); } else { @@ -2207,16 +2210,16 @@ } if (divp) { /* move quotient down in z */ - *divp = rb_big_clone(z); - zds = BDIGITS(*divp); + *divp = zz = rb_big_clone(z); + zds = BDIGITS(zz); j = (nx==ny ? nx+2 : nx+1) - ny; for (i = 0;i < j;i++) zds[i] = zds[i+ny]; if (!zds[i-1]) i--; - RBIGNUM_SET_LEN(*divp, i); + RBIGNUM_SET_LEN(zz, i); } if (modp) { /* normalize remainder */ - *modp = rb_big_clone(z); - zds = BDIGITS(*modp); + *modp = zz = rb_big_clone(z); + zds = BDIGITS(zz); while (--ny && !zds[ny]); ++ny; if (dd) { t2 = 0; i = ny; @@ -2228,14 +2231,14 @@ } } if (!zds[ny-1]) ny--; - RBIGNUM_SET_LEN(*modp, ny); - RBIGNUM_SET_SIGN(*modp, RBIGNUM_SIGN(x)); + RBIGNUM_SET_LEN(zz, ny); + RBIGNUM_SET_SIGN(zz, RBIGNUM_SIGN(x)); } return z; } static void -bigdivmod(VALUE x, VALUE y, VALUE *divp, VALUE *modp) +bigdivmod(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp) { VALUE mod; -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/