mdw_CHECK_MANYLIBS(socket, socket)
AC_CHECK_FUNCS(mlock)
+dnl --- Debugging things ---
+
+AC_ARG_ENABLE([mpw],
+ [AS_HELP_STRING([--enable-mpw],
+ [force small-width mp digits])],
+ [case "$enableval" in
+ y*|t*|short)
+ AC_DEFINE([FORCE_MPW_SHORT], [1],
+ [Define to force small-width mp digits.])
+ ;;
+ cussid)
+ AC_DEFINE([FORCE_MPW_CUSSID], [1],
+ [Define to force strange-width mp digits.])
+ ;;
+ esac])
+
dnl --- Done ---
mdw_MLIB(2.0.0)
e = ec_checkinfo(&ei, gr);
ec_freeinfo(&ei);
if (e) {
- printf(" [%s fails: %s]", ee->name, e);
+ printf(" [%s fails: %s]", ee->name, e);
ok = 0;
} else
printf(" %s", ee->name);
static void usage(FILE *fp)
{
- pquis(fp, "Usage: $ [-r radix] integer\n");
+ pquis(fp, "Usage: $ [-r RADIX] INTEGER\n");
}
static void version(FILE *fp)
unsigned long i;
gfreduce_instr *ip;
unsigned f = 0;
- size_t w, ww, wi, wl, ll;
+ size_t w, ww, wi, wl, ll, bb;
/* --- Sort out the easy stuff --- */
wi = DA_LEN(&iv);
f = 0;
ll = 0;
+ bb = MPW_BITS - dw;
for (i = 0, mp_scan(&sc, p); mp_step(&sc) && i < d; i++) {
if (!mp_bit(&sc))
continue;
w = ww;
wi = DA_LEN(&iv);
}
- INSTR(GFRI_LSL, (MPW_BITS + i - d)%MPW_BITS);
- if ((MPW_BITS + i - d)%MPW_BITS)
+ INSTR(GFRI_LSL, (bb + i)%MPW_BITS);
+ if ((bb + i)%MPW_BITS)
f |= f_lsr;
}
wl = DA_LEN(&iv);
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;
}
}
MP_DEST(_d, _sz, 0); \
_d->f &= ~(MP_NEG | MP_UNDEF); \
\
- /* --- Set the sign on the MP --- * \
- * \
- * If the input integer is *not* negative, then negate it. This \
- * fixes a problem with two's complement machines where the most \
- * negative value actually has larger magnitude than the most \
- * positive, and hence -TYPE_MIN == TYPE_MIN but TYPE_MIN != 0. If \
- * all the work is carried out on negative numbers there isn't a \
- * problem. \
- */ \
- \
- if (_i >= 0) \
- _i = -_i; \
- else \
+ if (_i >= 0) { \
+ while (_i) { \
+ if (_o == _sz) { \
+ _sz <<= 1; \
+ MP_ENSURE(_d, _sz); \
+ } \
+ _d->v[_o++] = MPW(_i); \
+ if (_i < MPW_MAX) \
+ break; \
+ else \
+ _i /= (type)MPW_MAX + 1; \
+ } \
+ } else { \
_d->f |= MP_NEG; \
- \
- while (_i) { \
- if (_o == _sz) { \
- _sz <<= 1; \
- MP_ENSURE(_d, _sz); \
+ while (_i) { \
+ if (_o == _sz) { \
+ _sz <<= 1; \
+ MP_ENSURE(_d, _sz); \
+ } \
+ _d->v[_o++] = MPW(-_i); \
+ if (_i > -MPW_MAX) \
+ break; \
+ else \
+ _i /= (type)MPW_MAX + 1; \
} \
- _d->v[_o++] = MPW(-_i); \
- \
- /* --- More subtlety --- * \
- * \
- * Ideally, I'd like to just shift @i@ right by @MPW_BITS@. But I \
- * can't, because that might be more than I'm allowed. I can't \
- * divide by @MPW_MAX + 1@ because that might turn out to be zero \
- * in my current type, and besides which it's unsigned which messes \
- * up all of my negative arithmetic. So do an explicit test here. \
- */ \
- \
- if (_i >= -MPW_MAX) \
- break; \
- else \
- _i /= (type)MPW_MAX + 1; \
} \
+ \
_d->vl = _d->v + _o; \
(d) = _d; \
} while (0)
return ok;
}
-
static test_chunk tests[] = {
{ "exp", texp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
{ 0, 0, { 0 } },
instr_v iv = DA_INIT;
unsigned long d, i;
unsigned op;
- size_t w, b;
+ size_t w, b, bb;
/* --- Fill in the easy stuff --- */
case X0 | 0: st = Z; printf("+ %lu\n", i - 1); break;
}
}
- if (st >= X) printf("+ %lu\n", i);
+ if (st >= X) printf("+ %lu\n", i - 1);
+ st = Z;
#endif
- for (i = 0, mp_scan(&sc, p); i < d - 1 && mp_step(&sc); i++) {
+ bb = MPW_BITS - (d + 1)%MPW_BITS;
+ for (i = 0, mp_scan(&sc, p); i < d && mp_step(&sc); i++) {
switch (st | mp_bit(&sc)) {
case Z | 1: st = Z1; break;
case Z1 | 0: st = Z; op = MPRI_SUB; goto instr;
case X0 | 0: st = Z; op = MPRI_SUB; goto instr;
instr:
w = (d - i)/MPW_BITS + 1;
- b = (MPW_BITS + i - d - 1)%MPW_BITS;
+ b = (bb + i)%MPW_BITS;
INSTR(op | !!b, w, b);
}
}
- if ((DA(&iv)[DA_LEN(&iv) - 1].op & ~1u) == MPRI_SUB) {
+ if (DA_LEN(&iv) && (DA(&iv)[DA_LEN(&iv) - 1].op & ~1u) == MPRI_SUB) {
mp_drop(r->p);
DA_DESTROY(&iv);
return (-1);
/* --- Wrap up --- */
r->in = DA_LEN(&iv);
- if (!r->s) {
+ if (!r->in)
+ r->iv = 0;
+ else if (!r->s) {
r->iv = xmalloc(r->in * sizeof(mpreduce_instr));
memcpy(r->iv, DA(&iv), r->in * sizeof(mpreduce_instr));
} else {
}
}
DA_DESTROY(&iv);
+
+#ifdef DEBUG
+ mpreduce_dump(r, stdout);
+#endif
return (0);
}
void mpreduce_destroy(mpreduce *r)
{
mp_drop(r->p);
- xfree(r->iv);
+ if (r->iv) xfree(r->iv);
}
/* --- @mpreduce_dump@ --- *
*vl = 0;
run(r->iv, il, vl, z);
#ifdef DEBUG
- MP_PRINTX("x", x);
- mp_div(0, &_rr, x, r->p);
- assert(MP_EQ(_r, _rr));
+ MP_PRINTX("x", x);
+ mp_div(0, &_rr, x, r->p);
+ assert(MP_EQ(_r, _rr));
#endif
}
}
*vl &= ((1 << r->s) - 1);
run(r->iv + r->in, il + r->in, vl, z);
#ifdef DEBUG
- MP_PRINTX("x", x);
- mp_div(0, &_rr, x, r->p);
- assert(MP_EQ(_r, _rr));
+ MP_PRINTX("x", x);
+ mp_div(0, &_rr, x, r->p);
+ assert(MP_EQ(_r, _rr));
#endif
}
}
/*----- Header files ------------------------------------------------------*/
#define _GNU_SOURCE
+#include "config.h"
+
#include <stdio.h>
#include <limits.h>
#if __STDC_VERSION__ >= 199900l
typedef uintmax_t umax;
# define P_UMAX PRIuMAX
#elif defined(ULLONG_MAX)
- __extension__ typedef unsigned long long umax;
+ EXT typedef unsigned long long umax;
# define P_UMAX "llu"
#else
typedef unsigned long umax;
itype *i;
itype *largest, *mpw, *mpd;
const static char *extstr = "CATACOMB_MPTYPES_EXTENSION ";
+ unsigned p2;
/* --- Find the bitcounts --- */
* which is twice as big as that one.
*/
+#if defined(FORCE_MPW_CUSSID)
+ largest = mpd = &tytab[3];
+ mpw = &tytab[2];
+ mpw->bits = 19; mpw->max = 0x7ffff;
+ mpd->bits = 38; mpd->max = 0x3fffffffffll;
+#elif defined(FORCE_MPW_SHORT)
+ largest = mpd = &tytab[2];
+ mpw = &tytab[1];
+ mpw->bits = 16; mpw->max = 0xffff;
+ mpd->bits = 32; mpd->max = 0xffffffff;
+#else
largest = tytab;
for (i = tytab; i->name; i++) {
if (i->bits > largest->bits)
d.bits = w.bits * 2; d.max = ~(~((umax)0) << d.bits);
mpw = &w; mpd = &d;
}
+#endif
+ for (p2 = 1; (p2 << 1) < mpw->bits; p2 <<= 1);
/* --- Output time --- */
printf("\
%stypedef %s mpw;\n\
#define MPW_BITS %u\n\
+#define MPW_P2 %u\n\
#define MPW_MAX %s%" P_UMAX "%s\n\
\n\
%stypedef %s mpd;\n\
#endif\n\
",
mpw->flags & f_ext ? extstr : "", mpw->name,
- mpw->bits,
+ mpw->bits, p2,
mpw->flags & f_ext ? extstr : "", mpw->max, mpw->suff,
mpd->flags & f_ext ? extstr : "", mpd->name,
mpd->bits,
while (avl > av) {
mpw t = *--avl;
- *--dvl = (t >> nr) | w;
+ *--dvl = MPW((t >> nr) | w);
w = t << nb;
}
- *--dvl = w;
+ *--dvl = MPW(w);
MPX_ZERO(dv, dvl);
}
while (avl > av) {
mpw t = *--avl;
- *--dvl = (t >> nr) | w;
+ *--dvl = MPW((t >> nr) | w);
w = t << nb;
}
- *--dvl = (MPW_MAX >> nr) | w;
+ *--dvl = MPW((MPW_MAX >> nr) | w);
MPX_ONE(dv, dvl);
}
a <<= o;
if (dv < dvl) {
- mpd x = (mpd)*dv - (mpd)a;
+ mpd x = (mpd)*dv - MPW(a);
*dv++ = MPW(x);
if (x >> MPW_BITS)
b++;
*/
void mpx_umuln(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, mpw m)
-{
- MPX_UMULN(dv, dvl, av, avl, m);
-}
+ { MPX_UMULN(dv, dvl, av, avl, m); }
/* --- @mpx_umlan@ --- *
*
*/
void mpx_umlan(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, mpw m)
-{
- MPX_UMLAN(dv, dvl, av, avl, m);
-}
+ { MPX_UMLAN(dv, dvl, av, avl, m); }
/* --- @mpx_usqr@ --- *
*
unsigned b;
d = dvl[-1];
- for (b = MPW_BITS / 2; b; b >>= 1) {
+ for (b = MPW_P2; b; b >>= 1) {
if (d <= (MPW_MAX >> b)) {
d <<= b;
norm += b;
else { \
unsigned long _b = MPW_BITS * (_vl - _v - 1) + 1; \
mpw _w = _vl[-1]; \
- unsigned _k = MPW_BITS / 2; \
+ unsigned _k = MPW_P2; \
while (_k) { \
if (_w >> _k) { \
_w >>= _k; \
0 0;
1 1;
-5 0xfffffffb;
+ 0x7ffff 0x7ffff;
+ 0x80000 0x80000;
+ 0xfffff 0xfffff;
0x7fffffff 0x7fffffff;
0x80000000 0x80000000; # Bastard torture test
0xffffffff 0xffffffff;
0 0;
1 1;
-5 -5;
+ 0x7ffff 0x7ffff;
+ 0x80000 0x80000;
+ 0xfffff 0xfffff;
0x7fffffff 0x7fffffff;
-0x80000000 -0x80000000; # Bastard torture test
}
0 0;
1 1;
-5 -5;
+ 0x7ffff 0x7ffff;
+ 0x80000 0x80000;
+ 0xfffff 0xfffff;
0x7fffffff 0x7fffffff;
0x80000000 -0x80000000; # Bastard torture test
0xffffffff 0xffffffff;
0 0;
1 1;
-5 -5;
+ 0x7ffff 0x7ffff;
+ 0x80000 0x80000;
+ 0xfffff 0xfffff;
0x7fffffff 0x7fffffff;
-0x80000000 -0x80000000; # Bastard torture test
}
# Tests for efficient reduction
reduce {
+ 0xc000 0x16cb3 0xacb3;
+ 0x8000 0x345545 0x5545;
+
+ 0xfffef 0x100000 0x11;
+
+ 0x1ffffffe 0x26fc6567 0x6fc6569;
+ 0x3ffffffe 0x45445dc0 0x5445dc2;
+ 0x7ffffffe 0xd4827a70 0x54827a72;
+
0x72e2c37447f8bca34c4a39b130ea8e5c9a7d8b54564aa88ea773
0x367aa8f5ba9ac4e8e2ea198b8af2c3b3081deab392ffc05715783b245a62a6fa
0x08e8c03ebf398c63d71d8fd7ca4ece12367a8dde180ca650afb6;
}
modexp {
- 0xfffffffdffffffffffffffffffffffff 0xfffffffdfffffffffffffffffffffffe 0 1;
+ 0xfffffffdffffffffffffffffffffffff 0xfffffffdfffffffffffffffffffffffe 0 1;
0xfffffffdffffffffffffffffffffffff 2
0xfffffffdfffffffffffffffffffffffe 1;
0xfffffffdffffffffffffffffffffffff 2
ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff
7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31d1b107fffffffffffffff
02 01;
+
+ 26737e 0ffffc 02 067386;
}
--- /dev/null
+#! /usr/bin/python
+
+import random as R
+
+print "# mpreduce torture"
+
+print "reduce {"
+first = True
+for i in xrange(16, 90):
+ for j in xrange(1, i - 1):
+ m = (1L << i) - (1L << j)
+ for k in xrange(i + 1, i + 16):
+ x = R.randrange(1L << k)
+ print " 0x%x" % m
+ print " 0x%x" % x
+ print " 0x%x;" % (x%m)
+ if not first:
+ print
+ first = False
+print "}"