1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* bignum.c (bigmul1_karatsuba): fix calculation order to prevent

underflow.  [ruby-core:29088]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27425 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
mame 2010-04-20 15:31:46 +00:00
parent adfe4f3930
commit 52998fa591
2 changed files with 23 additions and 15 deletions

View file

@ -1,3 +1,8 @@
Wed Apr 21 00:29:39 2010 Yusuke Endoh <mame@tsg.ne.jp>
* bignum.c (bigmul1_karatsuba): fix calculation order to prevent
underflow. [ruby-core:29088]
Wed Apr 21 00:26:17 2010 Yusuke Endoh <mame@tsg.ne.jp>
* compile.c (NODE_NEXT, NODE_REDO): add dummy putnil instruction to

View file

@ -2077,7 +2077,7 @@ static VALUE
bigmul1_karatsuba(VALUE x, VALUE y)
{
long i, n, xn, yn, t1n, t2n;
VALUE xh, xl, yh, yl, z, t1, t2;
VALUE xh, xl, yh, yl, z, t1, t2, t3;
BDIGIT *zds;
xn = RBIGNUM_LEN(x);
@ -2122,24 +2122,19 @@ bigmul1_karatsuba(VALUE x, VALUE y)
/* copy t2 into low bytes of the result (z0) */
MEMCPY(zds, BDIGITS(t2), BDIGIT, t2n);
for (i = t2n; i < 2 * n; i++) zds[i] = 0;
/* subtract t2 from middle bytes of the result (z1) */
i = xn + yn - n;
bigsub_core(zds + n, i, BDIGITS(t2), t2n, zds + n, i);
}
else {
t2 = Qundef;
/* copy 0 into low bytes of the result (z0) */
for (i = 0; i < 2 * n; i++) zds[i] = 0;
}
/* subtract t1 from middle bytes of the result (z1) */
i = xn + yn - n;
bigsub_core(zds + n, i, BDIGITS(t1), t1n, zds + n, i);
/* xh <- xh + xl */
if (RBIGNUM_LEN(xl) > RBIGNUM_LEN(xh)) {
t1 = xl; xl = xh; xh = t1;
t3 = xl; xl = xh; xh = t3;
}
/* xh has a margin for carry */
bigadd_core(BDIGITS(xh), RBIGNUM_LEN(xh),
BDIGITS(xl), RBIGNUM_LEN(xl),
BDIGITS(xh), RBIGNUM_LEN(xh));
@ -2147,19 +2142,27 @@ bigmul1_karatsuba(VALUE x, VALUE y)
/* yh <- yh + yl */
if (x != y) {
if (RBIGNUM_LEN(yl) > RBIGNUM_LEN(yh)) {
t1 = yl; yl = yh; yh = t1;
t3 = yl; yl = yh; yh = t3;
}
/* yh has a margin for carry */
bigadd_core(BDIGITS(yh), RBIGNUM_LEN(yh),
BDIGITS(yl), RBIGNUM_LEN(yl),
BDIGITS(yh), RBIGNUM_LEN(yh));
}
else yh = xh;
/* t1 <- xh * yh */
t1 = bigmul0(xh, yh);
/* t3 <- xh * yh */
t3 = bigmul0(xh, yh);
/* add t1 to middle bytes of the result (z1) */
bigadd_core(zds + n, i, BDIGITS(t1), big_real_len(t1), zds + n, i);
i = xn + yn - n;
/* add t3 to middle bytes of the result (z1) */
bigadd_core(zds + n, i, BDIGITS(t3), big_real_len(t3), zds + n, i);
/* subtract t1 from middle bytes of the result (z1) */
bigsub_core(zds + n, i, BDIGITS(t1), t1n, zds + n, i);
/* subtract t2 from middle bytes of the result (z1) */
if (t2 != Qundef) bigsub_core(zds + n, i, BDIGITS(t2), t2n, zds + n, i);
return z;
}