X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/a297c21674d7453888b13597d5c12b1ff5853a90..81578196d5732e443c75768ba9118c581c407cc7:/mp-arith.c diff --git a/mp-arith.c b/mp-arith.c index 759056b..3d565ae 100644 --- a/mp-arith.c +++ b/mp-arith.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: mp-arith.c,v 1.15 2002/10/19 17:56:50 mdw Exp $ + * $Id: mp-arith.c,v 1.16 2003/05/16 09:09:24 mdw Exp $ * * Basic arithmetic on multiprecision integers * @@ -30,6 +30,9 @@ /*----- Revision history --------------------------------------------------* * * $Log: mp-arith.c,v $ + * Revision 1.16 2003/05/16 09:09:24 mdw + * Fix @mp_lsl2c@. Turns out to be surprisingly tricky. + * * Revision 1.15 2002/10/19 17:56:50 mdw * Fix bit operations. Test them (a bit) better. * @@ -91,13 +94,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) @@ -109,6 +117,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); @@ -133,7 +150,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); } @@ -293,10 +310,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);