From 69a209875107dce06174442d214c92f2fe748aae Mon Sep 17 00:00:00 2001 From: Jakob Kaivo Date: Mon, 28 Mar 2022 16:01:27 -0400 Subject: 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 --- big.c | 61 +++++++++++++++++++++++++++++++++++-------------------------- big.h | 4 ++-- reduce.c | 10 +++++----- 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): -- cgit v1.2.1