summaryrefslogtreecommitdiff
path: root/bignum.c
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-06-13 12:26:33 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-06-13 12:26:33 +0000
commit63dd3e7ef9c1f2b839072003cb1696282520ffd1 (patch)
tree96ce3601194a172471319da724353594b7ce29ca /bignum.c
parent138bc4c0c4904b1370d4d178c74597ad4a3bdfae (diff)
* bignum.c (bigdivrem): Refactored to use ALLOCV_N for temporally
buffers. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41278 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'bignum.c')
-rw-r--r--bignum.c44
1 files changed, 23 insertions, 21 deletions
diff --git a/bignum.c b/bignum.c
index 5df4958aca..d2c1e865c7 100644
--- a/bignum.c
+++ b/bignum.c
@@ -3754,16 +3754,19 @@ static VALUE
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 nx = RBIGNUM_LEN(x), ny = RBIGNUM_LEN(y), nz;
long i, j;
- VALUE z, yy, zz;
- BDIGIT *xds, *yds, *zds, *tds;
+ VALUE z, zz;
+ VALUE tmpy = 0, tmpz = 0;
+ BDIGIT *xds, *yds, *zds, *tds, *qds;
BDIGIT_DBL t2;
BDIGIT dd, q;
if (BIGZEROP(y)) rb_num_zerodiv();
xds = BDIGITS(x);
yds = BDIGITS(y);
+ while (0 < nx && !xds[nx-1]) nx--;
+ while (!yds[ny-1]) ny--;
if (nx < ny || (nx == ny && xds[nx - 1] < yds[ny - 1])) {
if (divp) *divp = rb_int2big(0);
if (modp) *modp = x;
@@ -3788,17 +3791,15 @@ bigdivrem(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
return Qnil;
}
- z = bignew(nx==ny?nx+2:nx+1, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
- zds = BDIGITS(z);
+ nz = nx==ny ? nx+2 : nx+1;
+ zds = ALLOCV_N(BDIGIT, tmpz, nz);
if (nx==ny) zds[nx+1] = 0;
- while (!yds[ny-1]) ny--;
q = yds[ny-1];
dd = nlz(q);
q <<= dd;
if (dd) {
- yy = rb_big_clone(y);
- tds = BDIGITS(yy);
+ tds = ALLOCV_N(BDIGIT, tmpy, RBIGNUM_LEN(y));
j = 0;
t2 = 0;
while (j<ny) {
@@ -3807,7 +3808,6 @@ bigdivrem(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
t2 = BIGDN(t2);
}
yds = tds;
- RB_GC_GUARD(y) = yy;
j = 0;
t2 = 0;
while (j<nx) {
@@ -3828,7 +3828,7 @@ bigdivrem(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
bds.zds = zds;
bds.yds = yds;
bds.stop = Qfalse;
- bds.j = nx==ny?nx+1:nx;
+ bds.j = nz - 1;
for (bds.nyzero = 0; !yds[bds.nyzero]; bds.nyzero++);
if (nx > 10000 || ny > 10000) {
retry:
@@ -3845,16 +3845,14 @@ bigdivrem(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
}
if (divp) { /* move quotient down in z */
- *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(zz, i);
+ j = nz - ny;
+ *divp = zz = bignew(j, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
+ qds = BDIGITS(zz);
+ for (i = 0;i < j;i++) qds[i] = zds[i+ny];
+ if (!qds[i-1])
+ RBIGNUM_SET_LEN(zz, i-1);
}
if (modp) { /* normalize remainder */
- *modp = zz = rb_big_clone(z);
- zds = BDIGITS(zz);
while (ny > 1 && !zds[ny-1]) --ny;
if (dd) {
t2 = 0; i = ny;
@@ -3866,10 +3864,14 @@ bigdivrem(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
}
}
if (!zds[ny-1]) ny--;
- RBIGNUM_SET_LEN(zz, ny);
- RBIGNUM_SET_SIGN(zz, RBIGNUM_SIGN(x));
+ *modp = zz = bignew(ny, RBIGNUM_SIGN(x));
+ MEMCPY(BDIGITS(zz), zds, BDIGIT, ny);
}
- return z;
+ if (tmpy)
+ ALLOCV_END(tmpy);
+ if (tmpz)
+ ALLOCV_END(tmpz);
+ return Qnil;
}
static void