X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/42684bdb717221e41ad97cfefed2242e0553f835..283b9af095a5b24ae71b49a6d2dcbdcdaae47c40:/mpx.c diff --git a/mpx.c b/mpx.c index e63750f..f89a89b 100644 --- a/mpx.c +++ b/mpx.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: mpx.c,v 1.6 1999/11/20 22:43:44 mdw Exp $ + * $Id: mpx.c,v 1.11 2001/04/03 19:36:05 mdw Exp $ * * Low-level multiprecision arithmetic * @@ -30,6 +30,21 @@ /*----- Revision history --------------------------------------------------* * * $Log: mpx.c,v $ + * Revision 1.11 2001/04/03 19:36:05 mdw + * Add some simple bitwise operations so that Perl can use them. + * + * Revision 1.10 2000/10/08 12:06:12 mdw + * Provide @mpx_ueq@ for rapidly testing equality of two integers. + * + * Revision 1.9 2000/06/26 07:52:50 mdw + * Portability fix for the bug fix. + * + * Revision 1.8 2000/06/25 12:59:02 mdw + * (mpx_udiv): Fix bug in quotient digit estimation. + * + * Revision 1.7 1999/12/22 15:49:07 mdw + * New function for division by a small integer. + * * Revision 1.6 1999/11/20 22:43:44 mdw * Integrate testing for MPX routines. * @@ -388,6 +403,50 @@ void mpx_lsr(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n) done:; } +/*----- Bitwise operations ------------------------------------------------*/ + +/* --- @mpx_and@, @mpx_or@, @mpx_xor@, @mpx_not@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector + * @const mpw *av, *avl@ = first source vector + * @const mpw *bv, *bvl@ = second source vector + * + * Returns: --- + * + * Use; Does the obvious bitwise operations. + */ + +#define MPX_BITBINOP(name, op) \ + \ +void mpx_##name(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, \ + const mpw *bv, const mpw *bvl) \ +{ \ + MPX_SHRINK(av, avl); \ + MPX_SHRINK(bv, bvl); \ + \ + while (dv < dvl) { \ + mpw a, b; \ + a = (av < avl) ? *av++ : 0; \ + b = (bv < bvl) ? *bv++ : 0; \ + *dv++ = a op b; \ + } \ +} + +MPX_BITBINOP(and, &) +MPX_BITBINOP(or, |) +MPX_BITBINOP(xor, ^) + +void mpx_not(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl) +{ + MPX_SHRINK(av, avl); + + while (dv < dvl) { + mpw a; + a = (av < avl) ? *av++ : 0; + *dv++ = ~a; + } +} + /*----- Unsigned arithmetic -----------------------------------------------*/ /* --- @mpx_2c@ --- * @@ -414,6 +473,29 @@ void mpx_2c(mpw *dv, mpw *dvl, const mpw *v, const mpw *vl) MPX_UADDN(dv, dvl, 1); } +/* --- @mpx_ueq@ --- * + * + * Arguments: @const mpw *av, *avl@ = first argument vector base and limit + * @const mpw *bv, *bvl@ = second argument vector base and limit + * + * Returns: Nonzero if the two vectors are equal. + * + * Use: Performs an unsigned integer test for equality. + */ + +int mpx_ueq(const mpw *av, const mpw *avl, const mpw *bv, const mpw *bvl) +{ + MPX_SHRINK(av, avl); + MPX_SHRINK(bv, bvl); + if (avl - av != bvl - bv) + return (0); + while (av < avl) { + if (*av++ != *bv++) + return (0); + } + return (1); +} + /* --- @mpx_ucmp@ --- * * * Arguments: @const mpw *av, *avl@ = first argument vector base and limit @@ -444,7 +526,7 @@ int mpx_ucmp(const mpw *av, const mpw *avl, const mpw *bv, const mpw *bvl) } return (0); } - + /* --- @mpx_uadd@ --- * * * Arguments: @mpw *dv, *dvl@ = destination vector base and limit @@ -821,21 +903,19 @@ void mpx_udiv(mpw *qv, mpw *qvl, mpw *rv, mpw *rvl, { mpd yh = (mpd)d * q; - mpd yl = (mpd)dd * q; + mpd yy = (mpd)dd * q; + mpw yl; - if (yl > MPW_MAX) { - yh += yl >> MPW_BITS; - yl &= MPW_MAX; - } + if (yy > MPW_MAX) + yh += yy >> MPW_BITS; + yl = MPW(yy); while (yh > rh || (yh == rh && yl > rrr)) { q--; yh -= d; - if (yl < dd) { - yh++; - yl += MPW_MAX; - } - yl -= dd; + if (yl < dd) + yh--; + yl = MPW(yl - dd); } } @@ -900,6 +980,35 @@ void mpx_udiv(mpw *qv, mpw *qvl, mpw *rv, mpw *rvl, mpx_lsr(rv, rvl, rv, rvl, norm); } +/* --- @mpx_udivn@ --- * + * + * Arguments: @mpw *qv, *qvl@ = storage for the quotient (may overlap + * dividend) + * @const mpw *rv, *rvl@ = dividend + * @mpw d@ = single-precision divisor + * + * Returns: Remainder after divison. + * + * Use: Performs a single-precision division operation. + */ + +mpw mpx_udivn(mpw *qv, mpw *qvl, const mpw *rv, const mpw *rvl, mpw d) +{ + size_t i; + size_t ql = qvl - qv; + mpd r = 0; + + i = rvl - rv; + while (i > 0) { + i--; + r = (r << MPW_BITS) | rv[i]; + if (i < ql) + qv[i] = r / d; + r %= d; + } + return (MPW(r)); +} + /*----- Test rig ----------------------------------------------------------*/ #ifdef TEST_RIG @@ -1034,7 +1143,7 @@ static int lsl(dstr *v) ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS); mpx_lsl(d, dl, a, al, n); - if (MPX_UCMP(d, dl, !=, c, cl)) { + if (!mpx_ueq(d, dl, c, cl)) { fprintf(stderr, "\n*** lsl(%i) failed\n", n); dumpmp(" a", a, al); dumpmp("expected", c, cl); @@ -1059,7 +1168,7 @@ static int lsr(dstr *v) ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS + 1); mpx_lsr(d, dl, a, al, n); - if (MPX_UCMP(d, dl, !=, c, cl)) { + if (!mpx_ueq(d, dl, c, cl)) { fprintf(stderr, "\n*** lsr(%i) failed\n", n); dumpmp(" a", a, al); dumpmp("expected", c, cl); @@ -1085,7 +1194,7 @@ static int uadd(dstr *v) ALLOC(d, dl, MAX(al - a, bl - b) + 1); mpx_uadd(d, dl, a, al, b, bl); - if (MPX_UCMP(d, dl, !=, c, cl)) { + if (!mpx_ueq(d, dl, c, cl)) { fprintf(stderr, "\n*** uadd failed\n"); dumpmp(" a", a, al); dumpmp(" b", b, bl); @@ -1112,7 +1221,7 @@ static int usub(dstr *v) ALLOC(d, dl, al - a); mpx_usub(d, dl, a, al, b, bl); - if (MPX_UCMP(d, dl, !=, c, cl)) { + if (!mpx_ueq(d, dl, c, cl)) { fprintf(stderr, "\n*** usub failed\n"); dumpmp(" a", a, al); dumpmp(" b", b, bl); @@ -1139,7 +1248,7 @@ static int umul(dstr *v) ALLOC(d, dl, (al - a) + (bl - b)); mpx_umul(d, dl, a, al, b, bl); - if (MPX_UCMP(d, dl, !=, c, cl)) { + if (!mpx_ueq(d, dl, c, cl)) { fprintf(stderr, "\n*** umul failed\n"); dumpmp(" a", a, al); dumpmp(" b", b, bl); @@ -1164,7 +1273,7 @@ static int usqr(dstr *v) ALLOC(d, dl, 2 * (al - a)); mpx_usqr(d, dl, a, al); - if (MPX_UCMP(d, dl, !=, c, cl)) { + if (!mpx_ueq(d, dl, c, cl)) { fprintf(stderr, "\n*** usqr failed\n"); dumpmp(" a", a, al); dumpmp("expected", c, cl); @@ -1194,8 +1303,8 @@ static int udiv(dstr *v) ALLOC(s, sl, (bl - b) + 1); mpx_udiv(qq, qql, a, al, b, bl, s, sl); - if (MPX_UCMP(qq, qql, !=, q, ql) || - MPX_UCMP(a, al, !=, r, rl)) { + if (!mpx_ueq(qq, qql, q, ql) || + !mpx_ueq(a, al, r, rl)) { fprintf(stderr, "\n*** udiv failed\n"); dumpmp(" divisor", b, bl); dumpmp("expect r", r, rl); @@ -1227,7 +1336,6 @@ int main(int argc, char *argv[]) return (0); } - #endif /*----- That's all, folks -------------------------------------------------*/