summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2022-03-28 16:01:27 -0400
committerJakob Kaivo <jkk@ung.org>2022-03-28 16:01:27 -0400
commit69a209875107dce06174442d214c92f2fe748aae (patch)
tree1eb0fd486d3268e4354f4208eda0cc5ded89a5c8
parent427349ba1556a2efb131ee05f4f3752e35d06957 (diff)
modify longdiv() and shortdiv() to return structs, eliminating another global, rename bigdiv() and bigmod() to big_divide() and big_remainder() to ensure no call sights are missed
-rw-r--r--big.c61
-rw-r--r--big.h4
-rw-r--r--reduce.c10
3 files changed, 42 insertions, 33 deletions
diff --git a/big.c b/big.c
index a30f890..4ea8726 100644
--- a/big.c
+++ b/big.c
@@ -24,16 +24,21 @@
#define OCTW 5 /* number of factors of 8 in IBASE */
#define DIGITWIDTH 15
+struct big_div {
+ word quo;
+ word rem;
+};
+
word big_one;
static word big_plus(word, word, int);
static word big_sub(word, word);
static word len(word);
-static word longdiv(word, word);
+static struct big_div big__longdiv(word, word);
+static struct big_div shortdiv(word, word);
static word ms2d(word);
static word msd(word);
static word shift(word, word);
-static word shortdiv(word, word);
static word stimes(word, word);
void bigsetup(void)
@@ -359,11 +364,8 @@ word stimes(word x, word n)
return r;
}
-/* TODO: make bigdiv()/bigmod() behave like div()/ldiv()/lldiv() */
-word b_rem; /* contains remainder from last call to longdiv or shortdiv */
-
/* may assume y~=0 */
-word bigdiv(word x, word y)
+word big_divide(word x, word y)
{
word s1 = big_is_negative(y);
word s2 = s1;
@@ -379,10 +381,11 @@ word bigdiv(word x, word y)
s2 = !s1;
}
- word q = rest(y) ? longdiv(x, y) : shortdiv(x, digit(y));
+ struct big_div bd = rest(y) ? big__longdiv(x, y) : shortdiv(x, digit(y));
+ word q = bd.quo;
if (s2) {
- if (!bigzero(b_rem)) {
+ if (!bigzero(bd.rem)) {
x = q;
while ((digit(x) += 1) == IBASE) { /* add 1 to q in situ */
digit(x) = 0;
@@ -402,7 +405,7 @@ word bigdiv(word x, word y)
}
/* may assume y~=0 */
-word bigmod(word x, word y)
+word big_remainder(word x, word y)
{
word s1 = big_is_negative(y);
word s2 = s1;
@@ -412,24 +415,21 @@ word bigmod(word x, word y)
y = make(INT, digit0(y), rest(y));
}
+ /* effect: s1 set iff y negative, s2 set iff signs mixed */
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 {
- shortdiv(x, digit(y));
- }
+ struct big_div bd = rest(y) ? big__longdiv(x, y) : shortdiv(x, digit(y));
if (s2) {
- if (!bigzero(b_rem)) {
- b_rem = bigsub(y, b_rem);
+ if (!bigzero(bd.rem)) {
+ bd.rem = bigsub(y, bd.rem);
}
}
- return (s1 ? bignegate(b_rem) : b_rem);
+
+ return (s1 ? bignegate(bd.rem) : bd.rem);
}
/* NB - above have entier based handling of signed cases (as Miranda) in
@@ -444,7 +444,7 @@ word bigmod(word x, word y)
/* divide big x by single digit n returning big quotient
and setting external b_rem as side effect */
/* may assume - x>=0,n>0 */
-word shortdiv(word x, word n)
+struct big_div shortdiv(word x, word n)
{
word d = digit(x);
word q = 0;
@@ -477,18 +477,24 @@ word shortdiv(word x, word n)
q = tmp;
}
- b_rem = make(INT, s_rem, 0);
- return q;
+ struct big_div bd = {
+ .quo = q,
+ .rem = make(INT, s_rem, 0),
+ };
+ return bd;
}
/* divide big x by big y returning quotient, leaving
remainder in extern variable b_rem */
/* may assume - x>=0,y>0 */
-word longdiv(word x, word y)
+struct big_div big__longdiv(word x, word y)
{
if (bigcmp(x, y) < 0) {
- b_rem = x;
- return (make(INT, 0, 0));
+ struct big_div bd = {
+ .quo = make(INT, 0, 0),
+ .rem = x,
+ };
+ return bd;
}
word y1 = msd(y);
@@ -546,8 +552,11 @@ word longdiv(word x, word y)
q = make(INT, d, q);
if (n-- == 0) {
- b_rem = scale == 1 ? x : shortdiv(x, scale);
- return (q);
+ struct big_div bd = {
+ .quo = q,
+ .rem = scale == 1 ? x : shortdiv(x, scale).rem,
+ };
+ return bd;
}
ly--;
y = rest(y);
diff --git a/big.h b/big.h
index d291512..50099dd 100644
--- a/big.h
+++ b/big.h
@@ -28,8 +28,8 @@ double bigtodbl(word);
double biglog(word);
double biglog10(word);
int bigcmp(word,word);
-word bigdiv(word,word);
-word bigmod(word,word);
+word big_divide(word, word);
+word big_remainder(word,word);
word bignegate(word);
word bigoscan(char *,char *);
word bigplus(word,word);
diff --git a/reduce.c b/reduce.c
index 562d611..6f41d50 100644
--- a/reduce.c
+++ b/reduce.c
@@ -2075,8 +2075,8 @@ L3: if(arg1==NIL)lexfail(lastarg);
GETARG(arg1);
UPLEFT;
if(tag[arg1]==DOUBLE||tag[lastarg]==DOUBLE)int_error("div");
- if(bigzero(lastarg))div_error(); /* build into bigmod ? */
- simpl(bigdiv(arg1,lastarg));
+ if(bigzero(lastarg))div_error(); /* build into big_remainder ? */
+ simpl(big_divide(arg1,lastarg));
goto DONE;
case READY(FDIV):
@@ -2086,7 +2086,7 @@ L3: if(arg1==NIL)lexfail(lastarg);
/* experiment, suppressed
if(tag[lastarg]==INT&&tag[arg1]==INT&&!bigzero(lastarg))
{ extern word b_rem;
- int d = bigdiv(arg1,lastarg);
+ int d = big_divide(arg1,lastarg);
if(bigzero(b_rem)){ simpl(d); goto DONE; }
} /* makes a/b integer if a, b integers dividing exactly */
fa=force_dbl(arg1);
@@ -2100,8 +2100,8 @@ L3: if(arg1==NIL)lexfail(lastarg);
GETARG(arg1);
UPLEFT;
if(tag[arg1]==DOUBLE||tag[lastarg]==DOUBLE)int_error("mod");
- if(bigzero(lastarg))div_error(); /* build into bigmod ? */
- simpl(bigmod(arg1,lastarg));
+ if(bigzero(lastarg))div_error(); /* build into big_remainder ? */
+ simpl(big_remainder(arg1,lastarg));
goto DONE;
case READY(POWER):