X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/397041a943bdba47467a0393d7042c7fc99a5f3d..578a86d91941a0f722b87973d88e84ec2cf9a608:/mp-arith.c diff --git a/mp-arith.c b/mp-arith.c index a070675..736be2f 100644 --- a/mp-arith.c +++ b/mp-arith.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: mp-arith.c,v 1.14 2002/10/15 19:18:31 mdw Exp $ + * $Id: mp-arith.c,v 1.18 2004/04/08 01:36:15 mdw Exp $ * * Basic arithmetic on multiprecision integers * @@ -27,57 +27,6 @@ * MA 02111-1307, USA. */ -/*----- Revision history --------------------------------------------------* - * - * $Log: mp-arith.c,v $ - * Revision 1.14 2002/10/15 19:18:31 mdw - * New operation to negate numbers. - * - * Revision 1.13 2002/10/15 00:19:40 mdw - * Bit setting and clearing functions. - * - * Revision 1.12 2002/10/09 00:36:03 mdw - * Fix bounds on workspace for Karatsuba operations. - * - * Revision 1.11 2002/10/06 22:52:50 mdw - * Pile of changes for supporting two's complement properly. - * - * Revision 1.10 2001/04/03 19:36:05 mdw - * Add some simple bitwise operations so that Perl can use them. - * - * Revision 1.9 2000/10/08 15:48:35 mdw - * Rename Karatsuba constants now that we have @gfx_kmul@ too. - * - * Revision 1.8 2000/10/08 12:02:21 mdw - * Use @MP_EQ@ instead of @MP_CMP@. - * - * Revision 1.7 2000/06/22 19:02:53 mdw - * New function @mp_odd@ to extract powers of two from an integer. This is - * common code from the Rabin-Miller test, RSA key recovery and modular - * square-root extraction. - * - * Revision 1.6 2000/06/17 11:45:09 mdw - * Major memory management overhaul. Added arena support. Use the secure - * arena for secret integers. Replace and improve the MP management macros - * (e.g., replace MP_MODIFY by MP_DEST). - * - * Revision 1.5 1999/12/22 15:54:41 mdw - * Adjust Karatsuba parameters. Calculate destination size better. - * - * Revision 1.4 1999/12/13 15:35:16 mdw - * Slightly different rules on memory allocation. - * - * Revision 1.3 1999/12/11 10:57:43 mdw - * Karatsuba squaring algorithm. - * - * Revision 1.2 1999/12/10 23:18:39 mdw - * Change interface for suggested destinations. - * - * Revision 1.1 1999/11/17 18:02:16 mdw - * New multiprecision integer arithmetic suite. - * - */ - /*----- Header files ------------------------------------------------------*/ #include "mp.h" @@ -88,13 +37,18 @@ /*----- Main code ---------------------------------------------------------*/ -/* --- @mp_lsl@, @mp_lsr@ --- * +/* --- @mp_lsl@, @mp_lslc@, @mp_lsr@ --- * * * Arguments: @mp *d@ = destination * @mp *a@ = source * @size_t n@ = number of bits to move * * Returns: Result, @a@ shifted left or right by @n@. + * + * Use: Bitwise shift operators. @mp_lslc@ fills the bits introduced + * on the right with ones instead of zeroes: it's used + * internally by @mp_lsl2c@, though it may be useful on its + * own. */ mp *mp_lsl(mp *d, mp *a, size_t n) @@ -106,6 +60,15 @@ mp *mp_lsl(mp *d, mp *a, size_t n) return (d); } +mp *mp_lslc(mp *d, mp *a, size_t n) +{ + MP_DEST(d, MP_LEN(a) + (n + MPW_BITS - 1) / MPW_BITS, a->f); + mpx_lslc(d->v, d->vl, a->v, a->vl, n); + d->f = a->f & (MP_NEG | MP_BURN); + MP_SHRINK(d); + return (d); +} + mp *mp_lsr(mp *d, mp *a, size_t n) { MP_DEST(d, MP_LEN(a), a->f); @@ -130,7 +93,7 @@ mp *mp_lsl2c(mp *d, mp *a, size_t n) if (!(a->f & MP_NEG)) return (mp_lsl(d, a, n)); d = mp_not2c(d, a); - d = mp_lsl(d, d, n); + d = mp_lslc(d, d, n); d = mp_not2c(d, d); return (d); } @@ -290,10 +253,10 @@ mp *mp_neg(mp *d, mp *a) MP_SHRINK(a); MP_COPY(a); - if (d) MP_DROP(d); - if (a->v == a->vl) { + if (d) + MP_DROP(d); + if (a->v == a->vl) return (a); - } MP_DEST(a, MP_LEN(a), a->f); a->f ^= MP_NEG; return (a); @@ -318,7 +281,7 @@ mp *mp_neg(mp *d, mp *a) \ mp *mp_bit##string(mp *d, mp *a, mp *b) \ { \ - MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)), a->f | b->f); \ + MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)), (a->f | b->f) & ~MP_NEG); \ mpx_bit##string(d->v, d->vl, a->v, a->vl, b->v, b->vl); \ d->f = (a->f | b->f) & MP_BURN; \ MP_SHRINK(d); \ @@ -599,7 +562,7 @@ void mp_div(mp **qq, mp **rr, mp *a, mp *b) if (r) MP_DROP(r); r = a; - MP_DEST(r, MP_LEN(a) + 2, a->f | b->f); + MP_DEST(r, MAX(MP_LEN(a), MP_LEN(b)) + 2, a->f | b->f); /* --- Fix up the quotient too --- */