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

* bignum.c (bary_subb): Support xn < yn.

(bigsub_core): Removed.
  (bigsub): Don't compare before subtraction.  Just subtract and
  get the two's complement if the subtraction causes a borrow.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41962 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2013-07-14 13:24:44 +00:00
parent 651f762c17
commit b0eacd027a
2 changed files with 42 additions and 38 deletions

View file

@ -1,3 +1,10 @@
Sun Jul 14 22:21:11 2013 Tanaka Akira <akr@fsij.org>
* bignum.c (bary_subb): Support xn < yn.
(bigsub_core): Removed.
(bigsub): Don't compare before subtraction. Just subtract and
get the two's complement if the subtraction causes a borrow.
Sun Jul 14 00:36:03 2013 Tanaka Akira <akr@fsij.org> Sun Jul 14 00:36:03 2013 Tanaka Akira <akr@fsij.org>
* bignum.c (DIGSPERLONG): Unused macro removed. * bignum.c (DIGSPERLONG): Unused macro removed.

View file

@ -1353,22 +1353,34 @@ bary_subb(BDIGIT *zds, size_t zn, BDIGIT *xds, size_t xn, BDIGIT *yds, size_t yn
{ {
BDIGIT_DBL_SIGNED num; BDIGIT_DBL_SIGNED num;
size_t i; size_t i;
size_t sn;
assert(yn <= xn);
assert(xn <= zn); assert(xn <= zn);
assert(yn <= zn);
sn = xn < yn ? xn : yn;
num = borrow ? -1 : 0; num = borrow ? -1 : 0;
for (i = 0; i < yn; i++) { for (i = 0; i < sn; i++) {
num += (BDIGIT_DBL_SIGNED)xds[i] - yds[i]; num += (BDIGIT_DBL_SIGNED)xds[i] - yds[i];
zds[i] = BIGLO(num); zds[i] = BIGLO(num);
num = BIGDN(num); num = BIGDN(num);
} }
if (yn <= xn) {
for (; i < xn; i++) { for (; i < xn; i++) {
if (num == 0) goto num_is_zero; if (num == 0) goto num_is_zero;
num += xds[i]; num += xds[i];
zds[i] = BIGLO(num); zds[i] = BIGLO(num);
num = BIGDN(num); num = BIGDN(num);
} }
}
else {
for (; i < yn; i++) {
num -= yds[i];
zds[i] = BIGLO(num);
num = BIGDN(num);
}
}
if (num == 0) goto num_is_zero; if (num == 0) goto num_is_zero;
for (; i < zn; i++) { for (; i < zn; i++) {
zds[i] = BDIGMAX; zds[i] = BDIGMAX;
@ -4237,42 +4249,27 @@ rb_big_neg(VALUE x)
return bignorm(z); return bignorm(z);
} }
static void
bigsub_core(BDIGIT *xds, long xn, BDIGIT *yds, long yn, BDIGIT *zds, long zn)
{
bary_sub(zds, zn, xds, xn, yds, yn);
}
static VALUE static VALUE
bigsub(VALUE x, VALUE y) bigsub(VALUE x, VALUE y)
{ {
VALUE z = 0; VALUE z;
long i = RBIGNUM_LEN(x); BDIGIT *xds, *yds, *zds;
BDIGIT *xds, *yds; long xn, yn, zn;
xn = RBIGNUM_LEN(x);
yn = RBIGNUM_LEN(y);
zn = xn < yn ? yn : xn;
z = bignew(zn, 1);
/* if x is smaller than y, swap */
if (RBIGNUM_LEN(x) < RBIGNUM_LEN(y)) {
z = x; x = y; y = z; /* swap x y */
}
else if (RBIGNUM_LEN(x) == RBIGNUM_LEN(y)) {
xds = BDIGITS(x); xds = BDIGITS(x);
yds = BDIGITS(y); yds = BDIGITS(y);
while (i > 0) { zds = BDIGITS(z);
i--;
if (xds[i] > yds[i]) {
break;
}
if (xds[i] < yds[i]) {
z = x; x = y; y = z; /* swap x y */
break;
}
}
}
z = bignew(RBIGNUM_LEN(x), z==0); if (bary_sub(zds, zn, xds, xn, yds, yn)) {
bigsub_core(BDIGITS(x), RBIGNUM_LEN(x), bary_2comp(zds, zn);
BDIGITS(y), RBIGNUM_LEN(y), RBIGNUM_SET_NEGATIVE_SIGN(z);
BDIGITS(z), RBIGNUM_LEN(z)); }
return z; return z;
} }