diff options
Diffstat (limited to 'big.c')
-rw-r--r-- | big.c | 199 |
1 files changed, 99 insertions, 100 deletions
@@ -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 */ |