/* -*-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
*
* 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"
/*----- 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)
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);
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);
}
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);
\
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); \
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 --- */