summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--big.c199
1 files changed, 99 insertions, 100 deletions
diff --git a/big.c b/big.c
index bbd1e38..5bf1772 100644
--- a/big.c
+++ b/big.c
@@ -40,7 +40,6 @@ struct big_div {
word big_one;
-static word big_sub(word, word);
static word len(word);
static struct big_div big__longdiv(word, word);
static struct big_div shortdiv(word, word);
@@ -50,7 +49,7 @@ static word shift(word, word);
static word stimes(word, word);
/* ignore input signs, treat x,y as positive */
-word big__plus(word x, word y, int signbit)
+static word big__plus(word x, word y, int signbit)
{
word d = digit0(x) + digit0(y);
word r = make(INT, signbit | (d & MAXDIGIT), 0); /* result */
@@ -88,6 +87,100 @@ word big__plus(word x, word y, int signbit)
return r;
}
+/* ignore input signs, treat x,y as positive */
+word big__sub(word x, word y)
+{
+ word d = digit0(x) - digit0(y);
+ word borrow = (d & IBASE) != 0;
+ word r = make(INT, d & MAXDIGIT, 0); /* result */
+ word *z = &rest(r);
+ word *p = NULL; /* pointer to trailing zeros, if any */
+ x = rest(x);
+ y = rest(y);
+
+ /* this loop has been unwrapped once, see above */
+ while (x && y) {
+ d = digit(x) - digit(y) - borrow;
+ borrow = (d & IBASE) != 0;
+ d = d & MAXDIGIT;
+ *z = make(INT, d, 0);
+
+ if (d) {
+ p = NULL;
+ } else if (!p) {
+ p = z;
+ }
+
+ x = rest(x);
+ y = rest(y);
+ z = &rest(*z);
+ }
+
+ /* at most one of these two loops will be invoked */
+ while (y) {
+ d = -digit(y) - borrow;
+ borrow = ((d & IBASE) != 0);
+ d = d & MAXDIGIT;
+ *z = make(INT, d, 0);
+
+ if (d) {
+ p = NULL;
+ } else if (!p) {
+ p = z;
+ }
+
+ y = rest(y);
+ z = &rest(*z);
+ }
+
+ /* alternative loop */
+ while (x) {
+ d = digit(x) - borrow;
+ borrow = ((d & IBASE) != 0);
+ d = d & MAXDIGIT;
+ *z = make(INT, d, 0);
+
+ if (d) {
+ p = NULL;
+ } else if (!p) {
+ p = z;
+ }
+
+ x = rest(x);
+ z = &rest(*z);
+ }
+
+ /* result is negative - take complement and add 1 */
+ if (borrow) {
+ p = NULL;
+ d = (digit(r) ^ MAXDIGIT) + 1;
+ borrow = ((d & IBASE) != 0); /* borrow now means `carry' (sorry) */
+ digit(r) = SIGNBIT | d; /* set sign bit of result */
+ z = &rest(r);
+
+ while (*z) {
+ d = (digit(*z) ^ MAXDIGIT) + borrow;
+ borrow = ((d & IBASE) != 0);
+ digit(*z) = d = d & MAXDIGIT;
+
+ if (d) {
+ p = NULL;
+ } else if (!p) {
+ p = z;
+ }
+
+ z = &rest(*z);
+ }
+ }
+
+ /* remove redundant (ie trailing) zeros */
+ if (p) {
+ *p = 0;
+ }
+
+ return r;
+}
+
void bigsetup(void)
{
big_one = make(INT, 1, 0);
@@ -161,11 +254,11 @@ word bigplus(word x, word y)
if (big_is_positive(y)) {
return (big__plus(x, y, 0));
}
- return (big_sub(x, y));
+ return (big__sub(x, y));
}
if (big_is_positive(y)) {
- return (big_sub(y, x));
+ return (big__sub(y, x));
}
return (big__plus(x, y, SIGNBIT)); /* both negative */
@@ -176,7 +269,7 @@ word bigsub(word x, word y)
{
if (big_is_positive(x)) {
if (big_is_positive(y)) {
- return (big_sub(x, y)); /* both positive */
+ return (big__sub(x, y)); /* both positive */
}
return (big__plus(x, y, 0)); /* positive x, negative y */
}
@@ -185,101 +278,7 @@ word bigsub(word x, word y)
return (big__plus(x, y, SIGNBIT)); /* negative x, positive y */
}
- return (big_sub(y, x)); /* both negative */
-}
-
-/* ignore input signs, treat x,y as positive */
-word big_sub(word x, word y)
-{
- word d = digit0(x) - digit0(y);
- word borrow = (d & IBASE) != 0;
- word r = make(INT, d & MAXDIGIT, 0); /* result */
- word *z = &rest(r);
- word *p = NULL; /* pointer to trailing zeros, if any */
- x = rest(x);
- y = rest(y);
-
- /* this loop has been unwrapped once, see above */
- while (x && y) {
- d = digit(x) - digit(y) - borrow;
- borrow = (d & IBASE) != 0;
- d = d & MAXDIGIT;
- *z = make(INT, d, 0);
-
- if (d) {
- p = NULL;
- } else if (!p) {
- p = z;
- }
-
- x = rest(x);
- y = rest(y);
- z = &rest(*z);
- }
-
- /* at most one of these two loops will be invoked */
- while (y) {
- d = -digit(y) - borrow;
- borrow = ((d & IBASE) != 0);
- d = d & MAXDIGIT;
- *z = make(INT, d, 0);
-
- if (d) {
- p = NULL;
- } else if (!p) {
- p = z;
- }
-
- y = rest(y);
- z = &rest(*z);
- }
-
- /* alternative loop */
- while (x) {
- d = digit(x) - borrow;
- borrow = ((d & IBASE) != 0);
- d = d & MAXDIGIT;
- *z = make(INT, d, 0);
-
- if (d) {
- p = NULL;
- } else if (!p) {
- p = z;
- }
-
- x = rest(x);
- z = &rest(*z);
- }
-
- /* result is negative - take complement and add 1 */
- if (borrow) {
- p = NULL;
- d = (digit(r) ^ MAXDIGIT) + 1;
- borrow = ((d & IBASE) != 0); /* borrow now means `carry' (sorry) */
- digit(r) = SIGNBIT | d; /* set sign bit of result */
- z = &rest(r);
-
- while (*z) {
- d = (digit(*z) ^ MAXDIGIT) + borrow;
- borrow = ((d & IBASE) != 0);
- digit(*z) = d = d & MAXDIGIT;
-
- if (d) {
- p = NULL;
- } else if (!p) {
- p = z;
- }
-
- z = &rest(*z);
- }
- }
-
- /* remove redundant (ie trailing) zeros */
- if (p) {
- *p = 0;
- }
-
- return r;
+ return (big__sub(y, x)); /* both negative */
}
/* returns +ve,0,-ve as x greater than, equal, less than y */