X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/b817bfc642225b8c3c0b6a7e42d1fb949b61a606..ba6e6b64033b1f9de49feccb5c9cd438354481f7:/mp-arith.c diff --git a/mp-arith.c b/mp-arith.c index 736be2f..f00af54 100644 --- a/mp-arith.c +++ b/mp-arith.c @@ -1,13 +1,13 @@ /* -*-c-*- * - * $Id: mp-arith.c,v 1.18 2004/04/08 01:36:15 mdw Exp $ + * $Id$ * * Basic arithmetic on multiprecision integers * * (c) 1999 Straylight/Edgeware */ -/*----- Licensing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of Catacomb. * @@ -15,12 +15,12 @@ * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + * * Catacomb is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with Catacomb; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, @@ -90,7 +90,7 @@ mp *mp_lsr(mp *d, mp *a, size_t n) mp *mp_lsl2c(mp *d, mp *a, size_t n) { - if (!(a->f & MP_NEG)) + if (!MP_NEGP(a)) return (mp_lsl(d, a, n)); d = mp_not2c(d, a); d = mp_lslc(d, d, n); @@ -100,7 +100,7 @@ mp *mp_lsl2c(mp *d, mp *a, size_t n) mp *mp_lsr2c(mp *d, mp *a, size_t n) { - if (!(a->f & MP_NEG)) + if (!MP_NEGP(a)) return (mp_lsr(d, a, n)); d = mp_not2c(d, a); d = mp_lsr(d, d, n); @@ -135,7 +135,7 @@ int mp_testbit(mp *x, unsigned long n) int mp_testbit2c(mp *x, unsigned long n) { int r; - if (!(x->f & MP_NEG)) + if (!MP_NEGP(x)) return (mp_testbit(x, n)); x = mp_not2c(MP_NEW, x); r = !mp_testbit(x, n); @@ -192,7 +192,7 @@ mp *mp_clearbit(mp *d, mp *x, unsigned long n) mp *mp_setbit2c(mp *d, mp *x, unsigned long n) { - if (!(x->f & MP_NEG)) + if (!MP_NEGP(x)) return mp_setbit(d, x, n); d = mp_not2c(d, x); d = mp_clearbit(d, d, n); @@ -202,7 +202,7 @@ mp *mp_setbit2c(mp *d, mp *x, unsigned long n) mp *mp_clearbit2c(mp *d, mp *x, unsigned long n) { - if (!(x->f & MP_NEG)) + if (!MP_NEGP(x)) return mp_clearbit(d, x, n); d = mp_not2c(d, x); d = mp_setbit(d, d, n); @@ -229,9 +229,12 @@ int mp_eq(const mp *a, const mp *b) { return (MP_EQ(a, b)); } int mp_cmp(const mp *a, const mp *b) { - if (!((a->f ^ b->f) & MP_NEG)) - return (mpx_ucmp(a->v, a->vl, b->v, b->vl)); - else if (a->f & MP_NEG) + if (!((a->f ^ b->f) & MP_NEG)) { + if (a->f & MP_NEG) + return (-mpx_ucmp(a->v, a->vl, b->v, b->vl)); + else + return (mpx_ucmp(a->v, a->vl, b->v, b->vl)); + } else if (a->f & MP_NEG) return (-1); else return (+1); @@ -296,7 +299,7 @@ MPX_DOBIN(MP_BITBINOP) * @mp *a@ = source * * Returns: The bitwise complement of the source. - */ + */ mp *mp_not(mp *d, mp *a) { @@ -330,10 +333,10 @@ mp *mp_not(mp *d, mp *a) * negative at the end, we preinvert the output and then invert again with a * sign-swap. * - * Start with: wxyz WXYZ + * Start with: wxyz WXYZ * If @a@ negative: yzwx or YZWX - * If @b@ negative: xwzy XWZY - * If both negative: zyxw ZYXW + * If @b@ negative: xwzy XWZY + * If both negative: zyxw ZYXW */ #define MP_BIT2CBINOP(n, base, an, bn, abn, p_base, p_an, p_bn, p_abn) \ @@ -357,7 +360,7 @@ mp *mp_bit##n##2c(mp *d, mp *a, mp *b) \ p_bn \ } else { /* Both negative */ \ mp *t = mp_not2c(MP_NEW, a); \ - mp *d = mp_not2c(d, b); \ + d = mp_not2c(d, b); \ d = mp_bit##abn(d, t, d); \ MP_DROP(t); \ p_abn \ @@ -400,12 +403,12 @@ mp *mp_not2c(mp *d, mp *a) MP_DEST(d, MP_LEN(a) + 1, a->f); if (d == a) { - if (a->f & MP_NEG) + if (MP_NEGP(a)) MPX_USUBN(d->v, d->vl, 1); else MPX_UADDN(d->v, d->vl, 1); } else { - if (a->f & MP_NEG) + if (MP_NEGP(a)) mpx_usub(d->v, d->vl, a->v, a->vl, &one, &one + 1); else mpx_uadd(d->v, d->vl, a->v, a->vl, &one, &one + 1); @@ -590,7 +593,7 @@ void mp_div(mp **qq, mp **rr, mp *a, mp *b) */ q->f = ((r->f | b->f) & MP_BURN) | ((r->f ^ b->f) & MP_NEG); - if (q->f & MP_NEG) { + if (MP_NEGP(q)) { mpw *v; for (v = r->v; v < r->vl; v++) { if (*v) { @@ -649,16 +652,16 @@ mp *mp_odd(mp *d, mp *m, size_t *s) ss = 0; else { mpw x = *v; - mpw mask = MPW_MAX; - unsigned z = MPW_BITS / 2; + unsigned z = MPW_P2; + mpw mask = ((mpw)1 << z) - 1; while (z) { - mask >>= z; if (!(x & mask)) { x >>= z; ss += z; } z >>= 1; + mask >>= z; } } @@ -674,8 +677,8 @@ static int verify(const char *op, mp *expect, mp *result, mp *a, mp *b) { if (!MP_EQ(expect, result)) { fprintf(stderr, "\n*** %s failed", op); - fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 10); - fputs("\n*** b = ", stderr); mp_writefile(b, stderr, 10); + fputs("\n*** a = ", stderr); mp_writefile(a, stderr, 10); + fputs("\n*** b = ", stderr); mp_writefile(b, stderr, 10); fputs("\n*** result = ", stderr); mp_writefile(result, stderr, 10); fputs("\n*** expect = ", stderr); mp_writefile(expect, stderr, 10); fputc('\n', stderr); @@ -723,6 +726,7 @@ RIG(lsr2c, mp_lsr2c) RIG(add, mp_add) RIG(sub, mp_sub) RIG(mul, mp_mul) +RIG(exp, mp_exp) #undef RIG @@ -745,7 +749,7 @@ static int tdiv(dstr *v) static int tbin(dstr *v) { static mp *(*fn[])(mp *, mp *, mp *) = { -#define DO(string) mp_bit##string##2c, +#define DO(string) mp_bit##string##2c, MPX_DOBIN(DO) #undef DO }; @@ -755,7 +759,7 @@ MPX_DOBIN(DO) mp *b = *(mp **)v[2].buf; mp *r = *(mp **)v[3].buf; mp *c; - + if (strcmp(v[0].buf, "and") == 0) op = 1; else if (strcmp(v[0].buf, "or") == 0) op = 7; else if (strcmp(v[0].buf, "nand") == 0) op = 14; @@ -868,7 +872,7 @@ static int tneg(dstr *v) mp_drop(a); mp_drop(r); assert(mparena_count(MPARENA_GLOBAL) == 0); - return (ok); + return (ok); } static int todd(dstr *v) @@ -908,6 +912,7 @@ static test_chunk tests[] = { { "sub", tsub, { &type_mp, &type_mp, &type_mp, 0 } }, { "mul", tmul, { &type_mp, &type_mp, &type_mp, 0 } }, { "div", tdiv, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } }, + { "exp", texp, { &type_mp, &type_mp, &type_mp, 0 } }, { "bin2c", tbin, { &type_string, &type_mp, &type_mp, &type_mp, 0 } }, { "odd", todd, { &type_mp, &type_uint32, &type_mp, 0 } }, { "neg", tneg, { &type_mp, &type_mp, 0 } },