summaryrefslogtreecommitdiff
path: root/bignum.c
diff options
context:
space:
mode:
authormrkn <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-11-27 12:46:32 +0000
committermrkn <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-11-27 12:46:32 +0000
commit1dce5edf993a15c66c61965fcab4c2f5a07f6312 (patch)
tree34bcf7e5ea51b9c40738cea49635586b0ba7d191 /bignum.c
parent956cc2934d9848fa4c5cc7bcf79edd76f1171053 (diff)
* bignum.c (bigdivrem): optimize the way to retry calculation of
bigdivrem so that the calculation is started from the point where the last interruption was occurred. * bignum.c (bigdivrem1): ditto. * test/ruby/test_bignum.rb: add a test case for rb_bigdivrem in the case that an interruption is occurred during bigdivrem1 is running. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37899 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'bignum.c')
-rw-r--r--bignum.c30
1 files changed, 15 insertions, 15 deletions
diff --git a/bignum.c b/bignum.c
index 798571deba..666305756a 100644
--- a/bignum.c
+++ b/bignum.c
@@ -2655,7 +2655,7 @@ rb_big_mul(VALUE x, VALUE y)
}
struct big_div_struct {
- long nx, ny;
+ long nx, ny, j, nyzero;
BDIGIT *yds, *zds;
volatile VALUE stop;
};
@@ -2664,21 +2664,23 @@ static void *
bigdivrem1(void *ptr)
{
struct big_div_struct *bds = (struct big_div_struct*)ptr;
- long nx = bds->nx, ny = bds->ny;
- long i, j, nyzero;
+ long 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;
- for (nyzero = 0; !yds[nyzero]; nyzero++);
+ j = bds->j;
do {
- if (bds->stop) return 0;
+ if (bds->stop) {
+ bds->j = j;
+ return 0;
+ }
if (zds[j] == yds[ny-1]) q = (BDIGIT)BIGRAD-1;
else q = (BDIGIT)((BIGUP(zds[j]) + zds[j-1])/yds[ny-1]);
if (q) {
- i = nyzero; num = 0; t2 = 0;
+ i = bds->nyzero; num = 0; t2 = 0;
do { /* multiply and subtract */
BDIGIT_DBL ee;
t2 += (BDIGIT_DBL)yds[i] * q;
@@ -2713,22 +2715,16 @@ rb_big_stop(void *ptr)
}
static VALUE
-bigdivrem(VALUE x, VALUE y_, volatile VALUE *divp, volatile VALUE *modp)
+bigdivrem(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
{
- VALUE y;
struct big_div_struct bds;
- long nx, ny;
+ long nx = RBIGNUM_LEN(x), ny = RBIGNUM_LEN(y);
long i, j;
VALUE z, yy, zz;
BDIGIT *xds, *yds, *zds, *tds;
BDIGIT_DBL t2;
BDIGIT dd, q;
- retry:
- y = y_;
- nx = RBIGNUM_LEN(x);
- ny = RBIGNUM_LEN(y);
-
if (BIGZEROP(y)) rb_num_zerodiv();
xds = BDIGITS(x);
yds = BDIGITS(y);
@@ -2799,7 +2795,11 @@ 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;
+ for (bds.nyzero = 0; !yds[bds.nyzero]; bds.nyzero++);
if (nx > 10000 || ny > 10000) {
+ retry:
+ bds.stop = Qfalse;
rb_thread_call_without_gvl(bigdivrem1, &bds, rb_big_stop, &bds);
if (bds.stop == Qtrue) {