/* -*-c-*-
*
- * $Id: mp-arith.c,v 1.16.2.2 2004/03/20 00:14:03 mdw Exp $
+ * $Id$
*
* Basic arithmetic on multiprecision integers
*
* (c) 1999 Straylight/Edgeware
*/
-/*----- Licensing notice --------------------------------------------------*
+/*----- Licensing notice --------------------------------------------------*
*
* This file is part of Catacomb.
*
* 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,
* MA 02111-1307, USA.
*/
-/*----- Revision history --------------------------------------------------*
- *
- * $Log: mp-arith.c,v $
- * Revision 1.16.2.2 2004/03/20 00:14:03 mdw
- * Bug fix.
- *
- * Revision 1.16.2.1 2003/06/10 13:21:10 mdw
- * Fix bug dividing small things by large ones.
- *
- * 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.
- *
- * 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"
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);
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);
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);
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);
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);
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);
* @mp *a@ = source
*
* Returns: The bitwise complement of the source.
- */
+ */
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) \
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 \
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);
*/
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) {
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;
}
}
{
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);
RIG(add, mp_add)
RIG(sub, mp_sub)
RIG(mul, mp_mul)
+RIG(exp, mp_exp)
#undef RIG
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
};
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;
mp_drop(a);
mp_drop(r);
assert(mparena_count(MPARENA_GLOBAL) == 0);
- return (ok);
+ return (ok);
}
static int todd(dstr *v)
{ "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 } },