summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2022-03-27 21:01:31 -0400
committerJakob Kaivo <jkk@ung.org>2022-03-27 21:01:31 -0400
commit4fc923247e286f73ff873f5562a1d30f0316348f (patch)
tree02c069513f424d261ceab9cade9c003922bb25e8
parent3b89bde227c043133449f51f759f62b7fbcb5786 (diff)
more idiomaticization
-rw-r--r--big.c432
1 files changed, 270 insertions, 162 deletions
diff --git a/big.c b/big.c
index 4b20d04..255c15c 100644
--- a/big.c
+++ b/big.c
@@ -15,7 +15,7 @@
#include <errno.h>
/* contains remainder from last call to longdiv or shortdiv */
-word b_rem;
+static word b_rem;
extern char *dicp;
@@ -43,69 +43,73 @@ void bigsetup(void)
int isnat(word x)
{
- return (tag[x] == INT && poz(x));
+ return (tag[x] == INT && big_is_positive(x));
}
/* store C long long as mira bigint */
word sto_int(long long i)
{
- word s, x;
+ word s = 0;
+
if (i < 0) {
- s = SIGNBIT, i = -i;
- } else {
- s = 0;
+ s = SIGNBIT;
+ i = -i;
}
- x = make(INT, (s | i) & MAXDIGIT, 0);
- if (i >>= DIGITWIDTH) {
- word *p = &rest(x);
- *p = make(INT, i & MAXDIGIT, 0), p = &rest(*p);
- while (i >>= DIGITWIDTH) {
- *p = make(INT, i & MAXDIGIT, 0), p = &rest(*p);
- }
+
+ word x = make(INT, (s | i) & MAXDIGIT, 0);
+
+ for (word *p = &rest(x); i >>= DIGITWIDTH; p = &rest(*p)) {
+ *p = make(INT, i & MAXDIGIT, 0);
}
- return (x);
+
+ return x;
}
/* mira bigint to C long long */
long long get_int(word x)
{
long long n = digit0(x);
- word sign = neg(x);
+ word sign = big_is_negative(x);
+
if (!(x = rest(x))) {
return (sign ? -n : n);
}
- word w = DIGITWIDTH;
- while (x && w < 60) {
- n += (long long)digit(x) << w, w += DIGITWIDTH, x = rest(x);
+
+ for (word w = DIGITWIDTH; x && w < 60; w += DIGITWIDTH) {
+ n += (long long)digit(x) << w;
+ x = rest(x);
}
+
if (x) {
n = maxval; /* overflow, return large value */
}
+
return (sign ? -n : n);
}
word bignegate(word x)
{
if (bigzero(x)) {
- return (x);
+ return x;
}
- return (make
- (INT, hd[x] & SIGNBIT ? hd[x] & MAXDIGIT : SIGNBIT | hd[x], tl[x]));
+ return make(INT, (hd[x] & SIGNBIT) ? (hd[x] & MAXDIGIT) : (SIGNBIT | hd[x]),
+ tl[x]);
}
word bigplus(word x, word y)
{
- if (poz(x)) {
- if (poz(y)) {
+ if (big_is_positive(x)) {
+ if (big_is_positive(y)) {
return (big_plus(x, y, 0));
} else {
return (big_sub(x, y));
}
- } else if (poz(y)) {
+
+ } else if (big_is_positive(y)) {
return (big_sub(y, x));
- } else {
- return (big_plus(x, y, SIGNBIT)); /* both negative */
}
+
+ return (big_plus(x, y, SIGNBIT)); /* both negative */
}
/* ignore input signs, treat x,y as positive */
@@ -117,6 +121,7 @@ word big_plus(word x, word y, int signbit)
word *z = &rest(r); /* pointer to rest of result */
x = rest(x);
y = rest(y);
+
while (x && y) { /* this loop has been unwrapped once, see above */
d = carry + digit(x) + digit(y);
carry = ((d & IBASE) != 0);
@@ -125,9 +130,11 @@ word big_plus(word x, word y, int signbit)
y = rest(y);
z = &rest(*z);
}
+
if (y) {
x = y; /* by convention x is the longer one */
}
+
while (x) {
d = carry + digit(x);
carry = ((d & IBASE) != 0);
@@ -135,25 +142,28 @@ word big_plus(word x, word y, int signbit)
x = rest(x);
z = &rest(*z);
}
+
if (carry) {
*z = make(INT, 1, 0);
}
- return (r);
+
+ return r;
}
word bigsub(word x, word y)
{
- if (poz(x)) {
- if (poz(y)) {
+ if (big_is_positive(x)) {
+ if (big_is_positive(y)) {
return (big_sub(x, y));
} else {
return (big_plus(x, y, 0)); /* poz x, negative y */
}
- } else if (poz(y)) {
+
+ } else if (big_is_positive(y)) {
return (big_plus(x, y, SIGNBIT)); /* negative x, poz y */
- } else {
- return (big_sub(y, x)); /* both negative */
}
+
+ return (big_sub(y, x)); /* both negative */
}
/* ignore input signs, treat x,y as positive */
@@ -166,6 +176,7 @@ word big_sub(word x, word y)
word *p = NULL; /* pointer to trailing zeros, if any */
x = rest(x);
y = rest(y);
+
while (x && y) { /* this loop has been unwrapped once, see above */
d = digit(x) - digit(y) - borrow;
borrow = (d & IBASE) != 0;
@@ -179,6 +190,7 @@ word big_sub(word x, word y)
y = rest(y);
z = &rest(*z);
}
+
while (y) { /* at most one of these two loops will be invoked */
d = -digit(y) - borrow;
borrow = ((d & IBASE) != 0);
@@ -191,18 +203,21 @@ word big_sub(word x, word y)
y = rest(y);
z = &rest(*z);
}
+
while (x) { /* alternative loop */
d = digit(x) - borrow;
borrow = ((d & IBASE) != 0);
d = d & MAXDIGIT;
*z = make(INT, d, 0);
- if (d)
+ if (d) {
p = NULL;
- else if (!p)
+ } else if (!p) {
p = z;
+ }
x = rest(x);
z = &rest(*z);
}
+
if (borrow) { /* result is negative - take complement and add 1 */
p = NULL;
d = (digit(r) ^ MAXDIGIT) + 1;
@@ -213,29 +228,36 @@ word big_sub(word x, word y)
d = (digit(*z) ^ MAXDIGIT) + borrow;
borrow = ((d & IBASE) != 0);
digit(*z) = d = d & MAXDIGIT;
- if (d)
+ if (d) {
p = NULL;
- else if (!p)
+ } else if (!p) {
p = z;
+ }
z = &rest(*z);
}
}
- if (p)
+
+ if (p) {
*p = 0; /* remove redundant (ie trailing) zeros */
- return (r);
+ }
+
+ return r;
}
/* returns +ve,0,-ve as x greater than, equal, less than y */
int bigcmp(word x, word y)
{
- word d, r, s = neg(x);
- if (neg(y) != s) {
+ word s = big_is_negative(x);
+
+ if (big_is_negative(y) != s) {
return (s ? -1 : 1);
}
- r = digit0(x) - digit0(y);
+
+ word r = digit0(x) - digit0(y);
for (;;) {
x = rest(x);
y = rest(y);
+
if (!x) {
if (y) {
return (s ? 1 : -1);
@@ -243,10 +265,12 @@ int bigcmp(word x, word y)
return (s ? -r : r);
}
}
+
if (!y) {
return (s ? -1 : 1);
}
- d = digit(x) - digit(y);
+
+ word d = digit(x) - digit(y);
if (d) {
r = d;
}
@@ -256,27 +280,34 @@ int bigcmp(word x, word y)
/* naive multiply - quadratic */
word bigtimes(word x, word y)
{
+ word r = make(INT, 0, 0);
+
if (len(x) < len(y)) {
word hold = x;
x = y;
y = hold;
} /* important optimisation */
- word r = make(INT, 0, 0);
- word d = digit0(y);
- word s = neg(y);
- word n = 0;
+
if (bigzero(x)) {
- return (r); /* short cut */
+ return r; /* short cut */
}
+
+ word d = digit0(y);
+ word s = big_is_negative(y);
+ word n = 0;
+
for (;;) {
if (d) {
r = bigplus(r, shift(n, stimes(x, d)));
}
+
n++;
y = rest(y);
+
if (!y) {
- return (s != neg(x) ? bignegate(r) : r);
+ return (s != big_is_negative(x) ? bignegate(r) : r);
}
+
d = digit(y);
}
}
@@ -288,7 +319,7 @@ word shift(word n, word x)
while (n--) {
x = make(INT, 0, x);
}
- return (x);
+ return x;
}
/* multiply big x (>=0) by digit n (>0) */
@@ -298,37 +329,39 @@ word stimes(word x, word n)
word carry = d >> DIGITWIDTH;
word r = make(INT, d & MAXDIGIT, 0);
word *y = &rest(r);
+
while ((x = rest(x))) {
- d = n * digit(x) + carry,
- *y = make(INT, d & MAXDIGIT, 0), y = &rest(*y), carry = d >> DIGITWIDTH;
+ d = n * digit(x) + carry;
+ *y = make(INT, d & MAXDIGIT, 0);
+ y = &rest(*y);
+ carry = d >> DIGITWIDTH;
}
+
if (carry) {
*y = make(INT, carry, 0);
}
- return (r);
+
+ return r;
}
/* may assume y~=0 */
word bigdiv(word x, word y)
{
- word s1, s2, q;
-
/* make x,y positive and remember signs */
- if ((s1 = neg(y))) {
+ word s1 = big_is_negative(y);
+ if (s1) {
y = make(INT, digit0(y), rest(y));
}
- if (neg(x)) {
- x = make(INT, digit0(x), rest(x)), s2 = !s1;
- } else {
- s2 = s1;
+
+ word s2 = s1;
+ if (big_is_negative(x)) {
+ x = make(INT, digit0(x), rest(x));
+ s2 = !s1;
}
/* effect: s1 set iff y negative, s2 set iff signs mixed */
- if (rest(y)) {
- q = longdiv(x, y);
- } else {
- q = shortdiv(x, digit(y));
- }
+
+ word q = rest(y) ? longdiv(x, y) : shortdiv(x, digit(y));
if (s2) {
if (!bigzero(b_rem)) {
@@ -343,30 +376,33 @@ word bigdiv(word x, word y)
}
}
}
+
if (!bigzero(q)) {
digit(q) = SIGNBIT | digit(q);
}
}
- return (q);
+
+ return q;
}
/* may assume y~=0 */
word bigmod(word x, word y)
{
- word s1, s2;
+ word s1 = big_is_negative(y);
/* make x,y positive and remember signs */
- if ((s1 = neg(y))) {
+ if (s1) {
y = make(INT, digit0(y), rest(y));
}
- if (neg(x)) {
- x = make(INT, digit0(x), rest(x)), s2 = !s1;
- } else {
- s2 = s1;
+ word s2 = s1;
+ if (big_is_negative(x)) {
+ x = make(INT, digit0(x), rest(x));
+ s2 = !s1;
}
/* effect: s1 set iff y negative, s2 set iff signs mixed */
+
if (rest(y)) {
longdiv(x, y);
} else {
@@ -378,6 +414,7 @@ word bigmod(word x, word y)
b_rem = bigsub(y, b_rem);
}
}
+
return (s1 ? bignegate(b_rem) : b_rem);
}
@@ -396,14 +433,15 @@ word bigmod(word x, word y)
/* may assume - x>=0,n>0 */
word shortdiv(word x, word n)
{
- word d = digit(x), s_rem, q = 0;
+ word d = digit(x);
+ word q = 0;
+
while ((x = rest(x))) { /* reverse rest(x) into q */
- q = make(INT, d, q), d = digit(x); /* leaving most sig. digit in d */
+ q = make(INT, d, q);
+ d = digit(x); /* leaving most sig. digit in d */
}
- word tmp;
x = q;
- s_rem = d % n;
d = d / n;
if (d || !q) {
@@ -412,14 +450,20 @@ word shortdiv(word x, word n)
q = 0;
}
+ word s_rem = d % n;
while (x) { /* in situ division of q by n AND destructive reversal */
- d = s_rem * IBASE + digit(x), digit(x) = d / n, s_rem = d % n,
- tmp = x, x = rest(x), rest(tmp) = q, q = tmp;
+ d = s_rem * IBASE + digit(x);
+ digit(x) = d / n;
+ s_rem = d % n;
+ word tmp = x;
+ x = rest(x);
+ rest(tmp) = q;
+ q = tmp;
}
b_rem = make(INT, s_rem, 0);
- return (q);
+ return q;
}
/* divide big x by big y returning quotient, leaving
@@ -427,56 +471,66 @@ word shortdiv(word x, word n)
/* may assume - x>=0,y>0 */
word longdiv(word x, word y)
{
- word n, q, ly, y1, scale;
if (bigcmp(x, y) < 0) {
b_rem = x;
return (make(INT, 0, 0));
}
- y1 = msd(y);
- if ((scale = IBASE / (y1 + 1)) > 1) { /* rescale if necessary */
- x = stimes(x, scale), y = stimes(y, scale), y1 = msd(y);
+
+ word y1 = msd(y);
+ word scale = IBASE / (y1 + 1);
+ if (scale > 1) { /* rescale if necessary */
+ x = stimes(x, scale);
+ y = stimes(y, scale);
+ y1 = msd(y);
}
- n = q = 0;
- ly = len(y);
+ word n = 0;
+ word ly = len(y);
while (bigcmp(x, y = make(INT, 0, y)) >= 0) {
n++;
}
y = rest(y); /* want largest y not exceeding x */
ly += n;
+ word q = 0;
for (;;) {
- word d, lx = len(x);
- if (lx < ly) {
- d = 0;
- } else if (lx == ly) {
+ word d = 0;
+ word lx = len(x);
+
+ if (lx == ly) {
if (bigcmp(x, y) >= 0) {
- x = bigsub(x, y), d = 1;
- } else {
- d = 0;
+ x = bigsub(x, y);
+ d = 1;
}
- } else {
+
+ } else if (lx > ly) {
d = ms2d(x) / y1;
if (d > MAXDIGIT) {
d = MAXDIGIT;
}
+
if ((d -= 2) > 0) {
x = bigsub(x, stimes(y, d));
} else {
d = 0;
}
+
if (bigcmp(x, y) >= 0) {
- x = bigsub(x, y), d++;
+ x = bigsub(x, y);
+ d++;
if (bigcmp(x, y) >= 0) {
- x = bigsub(x, y), d++;
+ x = bigsub(x, y);
+ d++;
}
}
}
+
q = make(INT, d, q);
if (n-- == 0) {
- b_rem = scale == 1 ? x : shortdiv(x, scale);
- return (q);
+ b_rem = (scale == 1) ? x : shortdiv(x, scale);
+ return q;
}
+
ly--;
y = rest(y);
}
@@ -489,7 +543,7 @@ word len(word x)
while ((x = rest(x))) {
n++;
}
- return (n);
+ return n;
}
/* most significant digit of big x */
@@ -498,7 +552,7 @@ word msd(word x)
while (rest(x)) {
x = rest(x);
}
- return (digit(x)); /* sign? */
+ return digit(x); /* sign? */
}
/* most significant 2 digits of big x (len>=2) */
@@ -507,7 +561,8 @@ word ms2d(word x)
word d = digit(x);
x = rest(x);
while (rest(x)) {
- d = digit(x), x = rest(x);
+ d = digit(x);
+ x = rest(x);
}
return (digit(x) * IBASE + d);
}
@@ -515,10 +570,10 @@ word ms2d(word x)
/* assumes y poz */
word bigpow(word x, word y)
{
- word d, r = make(INT, 1, 0);
- while (rest(y)) { /* this loop has been unwrapped once, see below */
+ word r = make(INT, 1, 0);
+ while (rest(y)) {
word i = DIGITWIDTH;
- d = digit(y);
+ word d = digit(y);
while (i--) {
if (d & 1) {
r = bigtimes(r, x);
@@ -528,31 +583,35 @@ word bigpow(word x, word y)
}
y = rest(y);
}
- d = digit(y);
+
+ word d = digit(y);
if (d & 1) {
r = bigtimes(r, x);
}
+
while (d >>= 1) {
x = bigtimes(x, x);
if (d & 1) {
r = bigtimes(r, x);
}
}
- return (r);
+
+ return r;
}
double bigtodbl(word x)
{
- word s = neg(x);
- double b = 1.0, r = (double)digit0(x);
+ double b = 1.0;
+ double r = (double)digit0(x);
+
x = rest(x);
while (x) {
- b = b * IBASE, r = r + b * digit(x), x = rest(x);
- }
- if (s) {
- return (-r);
+ b = b * IBASE;
+ r = r + b * digit(x);
+ x = rest(x);
}
- return (r);
+
+ return big_is_negative(x) ? -r : r;
} /* small end first */
/* note: can return oo, -oo
@@ -561,40 +620,40 @@ double bigtodbl(word x)
/* not currently used */
long double bigtoldbl(word x)
{
- int s=neg(x);
- long double b=1.0L, r=digit0(x);
+ long double b = 1.0L;
+ long double r = (long double)digit0(x);
+
x = rest(x);
while (x) {
- b=b*IBASE,r=r+b*digit(x),x=rest(x);
- }
- if (s) {
- return(-r);
+ b = b * IBASE;
+ r = r + b * digit(x);
+ x = rest(x);
}
- return(r);
+
+ return big_is_negative(x) ? -r : r;
} /* not compatible with std=c90, lib fns eg sqrtl broken */
/* entier */
word dbltobig(double x)
{
- word s = (x < 0);
word r = make(INT, 0, 0);
word *p = &r;
- double y = floor(x);
+ double y = fabs(floor(x));
- for (y = fabs(y);;) {
+ while (y > 0.0) {
double n = fmod(y, (double)IBASE);
digit(*p) = (word) n;
y = (y - n) / (double)IBASE;
if (y > 0.0) {
rest(*p) = make(INT, 0, 0), p = &rest(*p);
- } else {
- break;
}
}
- if (s) {
+
+ if (x < 0) {
digit(r) = SIGNBIT | digit(r);
}
- return (r);
+
+ return r;
}
/* produces junk in low order digits if x exceeds range in which integer
@@ -612,28 +671,35 @@ word dbltobig(double x)
/* logarithm of big x */
double biglog(word x)
{
+ if (big_is_negative(x) || bigzero(x)) {
+ errno = EDOM;
+ math_error("log");
+ }
+
word n = 0;
double r = digit(x);
- if (neg(x) || bigzero(x)) {
- errno = EDOM, math_error("log");
- }
while ((x = rest(x))) {
- n++, r = digit(x) + r / IBASE;
+ n++;
+ r = digit(x) + r / IBASE;
}
+
return (log(r) + n * logIBASE);
}
/* logarithm of big x */
double biglog10(word x)
{
+ if (big_is_negative(x) || bigzero(x)) {
+ errno = EDOM;
+ math_error("log10");
+ }
+
word n = 0;
double r = digit(x);
- if (neg(x) || bigzero(x)) {
- errno = EDOM, math_error("log10");
- }
while ((x = rest(x))) {
n++, r = digit(x) + r / IBASE;
}
+
return (log10(r) + n * log10IBASE);
}
@@ -642,16 +708,22 @@ double biglog10(word x)
/* read a big number (in decimal) */
word bigscan(char *p)
{
- word s = 0, r = make(INT, 0, 0);
+ word s = 0;
+ word r = make(INT, 0, 0);
if (*p == '-') {
- s = 1, p++; /* optional leading `-' (for NUMVAL) */
+ s = 1;
+ p++; /* optional leading `-' (for NUMVAL) */
}
while (*p) {
- word d = *p - '0', f = 10;
+ word d = *p - '0';
+ word f = 10;
p++;
+
while (*p && f < PTEN) {
- d = 10 * d + *p - '0', f = 10 * f, p++;
+ d = 10 * d + *p - '0';
+ f = 10 * f;
+ p++;
}
/* rest of loop does r=f*r+d; (in situ) */
@@ -659,18 +731,24 @@ word bigscan(char *p)
word carry = d >> DIGITWIDTH;
word *x = &rest(r);
digit(r) = d & MAXDIGIT;
+
while (*x) {
- d = f * digit(*x) + carry,
- digit(*x) = d & MAXDIGIT, carry = d >> DIGITWIDTH, x = &rest(*x);
+ d = f * digit(*x) + carry;
+ digit(*x) = d & MAXDIGIT;
+ carry = d >> DIGITWIDTH;
+ x = &rest(*x);
}
+
if (carry) {
*x = make(INT, carry, 0);
}
}
+
if (s && !bigzero(r)) {
digit(r) = digit(r) | SIGNBIT;
}
- return (r);
+
+ return r;
}
/* code to handle (unsigned) exponent commented out */
@@ -679,21 +757,26 @@ word bigscan(char *p)
/* read unsigned hex number in '\0'-terminated string p to q */
word bigxscan(char *p, char *q)
{
- word r; /* will hold result */
- word *x = &r;
if (*p == '0' && !p[1]) {
return make(INT, 0, 0);
}
+
+ word r; /* will hold result */
+ word *x = &r;
+
while (q > p) {
unsigned long long hold;
- q = q - p < 15 ? p : q - 15; /* read upto 15 hex digits from small end */
+ q = (q - p < 15) ? p : (q - 15); /* read upto 15 hex digits from small end */
sscanf(q, "%llx", &hold);
*q = '\0';
word count = 4; /* 15 hex digits => 4 bignum digits */
while (count-- && !(hold == 0 && q == p)) {
- *x = make(INT, hold & MAXDIGIT, 0), hold >>= DIGITWIDTH, x = &rest(*x);
+ *x = make(INT, hold & MAXDIGIT, 0);
+ hold >>= DIGITWIDTH;
+ x = &rest(*x);
}
}
+
return r;
}
@@ -703,6 +786,7 @@ word bigoscan(char *p, char *q)
{
word r; /* will hold result */
word *x = &r;
+
while (q > p) {
unsigned hold;
q = q - p < 5 ? p : q - 5; /* read (upto) 5 octal digits from small end */
@@ -710,6 +794,7 @@ word bigoscan(char *p, char *q)
*q = '\0';
*x = make(INT, hold, 0), x = &rest(*x);
}
+
return r;
}
@@ -723,8 +808,10 @@ word digitval(char c)
done and that z fully evaluated */
word strtobig(word z, int base)
{
- word s = 0, r = make(INT, 0, 0), PBASE = PTEN;
+ word s = 0;
+ word r = make(INT, 0, 0);
+ word PBASE = PTEN;
if (base == 16) {
PBASE = PSIXTEEN;
} else if (base == 8) {
@@ -732,7 +819,8 @@ word strtobig(word z, int base)
}
if (z != NIL && hd[z] == '-') {
- s = 1, z = tl[z]; /* optional leading `-' (for NUMVAL) */
+ s = 1;
+ z = tl[z]; /* optional leading `-' (for NUMVAL) */
}
if (base != 10) {
@@ -742,8 +830,11 @@ word strtobig(word z, int base)
while (z != NIL) {
word d = digitval(hd[z]), f = base;
z = tl[z];
+
while (z != NIL && f < PBASE) {
- d = base * d + digitval(hd[z]), f = base * f, z = tl[z];
+ d = base * d + digitval(hd[z]);
+ f = base * f;
+ z = tl[z];
}
/* rest of loop does r=f*r+d; (in situ) */
@@ -751,10 +842,12 @@ word strtobig(word z, int base)
word carry = d >> DIGITWIDTH;
word *x = &rest(r);
digit(r) = d & MAXDIGIT;
+
while (*x) {
d = f * digit(*x) + carry,
digit(*x) = d & MAXDIGIT, carry = d >> DIGITWIDTH, x = &rest(*x);
}
+
if (carry) {
*x = make(INT, carry, 0);
}
@@ -764,19 +857,19 @@ word strtobig(word z, int base)
digit(r) = digit(r) | SIGNBIT;
}
- return (r);
+ return r;
}
word bigtostr(word x) /* number to decimal string (as Miranda list) */
{
- word x1, sign, s = NIL;
+ word sign = big_is_negative(x);
+ word s = NIL;
#ifdef DEBUG
extern int debug;
if (debug & 04) { /* print octally */
word d = digit0(x);
- sign = neg(x);
for (;;) {
word i = OCTW;
while (i-- || d) {
@@ -798,15 +891,15 @@ word bigtostr(word x) /* number to decimal string (as Miranda list) */
return (str_conv(dicp));
}
- sign = neg(x);
- x1 = make(INT, digit0(x), 0); /* reverse x into x1 */
+ word x1 = make(INT, digit0(x), 0); /* reverse x into x1 */
while ((x = rest(x))) {
x1 = make(INT, digit(x), x1);
}
x = x1;
for (;;) { /* in situ division of (reversed order) x by PTEN */
- word d = digit(x), rem = d % PTEN;
+ word d = digit(x);
+ word rem = d % PTEN;
d = d / PTEN;
x1 = rest(x);
@@ -817,8 +910,10 @@ word bigtostr(word x) /* number to decimal string (as Miranda list) */
}
while (x1) {
- d = rem * IBASE + digit(x1),
- digit(x1) = d / PTEN, rem = d % PTEN, x1 = rest(x1);
+ d = rem * IBASE + digit(x1);
+ digit(x1) = d / PTEN;
+ rem = d % PTEN;
+ x1 = rest(x1);
}
/* end of in situ division (also uses x1 as temporary) */
@@ -839,7 +934,8 @@ word bigtostr(word x) /* number to decimal string (as Miranda list) */
/* integer to hexadecimal string (as Miranda list) */
word bigtostrx(word x)
{
- word r = NIL, s = neg(x);
+ word r = NIL;
+ word sign = big_is_negative(x);
while (x) {
word count = 4; /* 60 bits => 20 octal digits => 4 bignum digits */
unsigned long long factor = 1;
@@ -854,22 +950,25 @@ word bigtostrx(word x)
r = cons(*q, r);
}
}
+
while (digit(r) == '0' && rest(r) != NIL) {
r = rest(r); /* remove redundant leading 0's */
}
r = cons('0', cons('x', r));
- if (s) {
+ if (sign) {
r = cons('-', r);
}
- return (r);
+ return r;
}
/* integer to octal string (as Miranda list) */
word bigtostr8(word x)
{
- word r = NIL, s = neg(x);
+ word r = NIL;
+ word sign = big_is_negative(x);
+
while (x) {
char *q = dicp + 5;
sprintf(dicp, "%.5lo", digit0(x));
@@ -878,14 +977,18 @@ word bigtostr8(word x)
}
x = rest(x);
}
+
while (digit(r) == '0' && rest(r) != NIL) {
r = rest(r); /* remove redundant leading 0's */
}
+
r = cons('0', cons('o', r));
- if (s) {
+
+ if (sign) {
r = cons('-', r);
}
- return (r);
+
+ return r;
}
#ifdef DEBUG
@@ -896,9 +999,11 @@ wff(word x)
if (tag[x] != INT) {
printf("BAD TAG %d\n", tag[x]);
}
- if (neg(x) && !digit0(x) && !rest(x)) {
+
+ if (big_is_negative(x) && !digit0(x) && !rest(x)) {
printf("NEGATIVE ZERO!\n");
}
+
if (digit0(x) & (~MAXDIGIT)) {
printf("OVERSIZED DIGIT!\n");
}
@@ -912,6 +1017,7 @@ wff(word x)
printf("TRAILING ZERO!\n");
}
}
+
return (y);
}
@@ -921,7 +1027,8 @@ normalise(word x)
if (rest(x)) {
rest(x) = norm1(rest(x));
}
- return (wff(x));
+
+ return wff(x);
}
norm1(word x)
@@ -929,6 +1036,7 @@ norm1(word x)
if (rest(x)) {
rest(x) = norm1(rest(x));
}
+
return (!digit(x) && !rest(x) ? 0 : x);
}