return ((PyObject *)z);
}
-int mp_tolong_checked(mp *x, long *l)
+int mp_tolong_checked(mp *x, long *l, int must)
{
static mp *longmin = 0, *longmax = 0;
int rc = -1;
longmin = mp_fromlong(MP_NEW, LONG_MIN);
longmax = mp_fromlong(MP_NEW, LONG_MAX);
}
- if (MP_CMP(x, <, longmin) || MP_CMP(x, >, longmax))
- VALERR("mp out of range for int");
+ if (MP_CMP(x, <, longmin) || MP_CMP(x, >, longmax)) {
+ if (must) VALERR("mp out of range for int");
+ else goto end;
+ }
*l = mp_tolong(x);
rc = 0;
end:
PyObject *z = 0; \
long n; \
if (pre##binop(x, y, &xx, &yy)) RETURN_NOTIMPL; \
- if (mp_tolong_checked(yy, &n)) goto end; \
+ if (mp_tolong_checked(yy, &n, 1)) goto end; \
if (n < 0) \
z = pre##_pywrap(mp_##rname(MP_NEW, xx, -n)); \
else \
static PyObject *mp_pyint(PyObject *x)
{
long l;
- if (mp_tolong_checked(MP_X(x), &l)) return (0);
- return (PyInt_FromLong(l));
+ if (!mp_tolong_checked(MP_X(x), &l, 0)) return (PyInt_FromLong(l));
+ else return mp_topylong(MP_X(x));
}
static PyObject *mp_pylong(PyObject *x)
{ return (mp_topylong(MP_X(x))); }
return ((PyObject *)zz);
}
-static long mp_pyhash(PyObject *me)
+long mphash(mp *x)
{
- long h;
- PyObject *l = mp_topylong(MP_X(me)); h = PyObject_Hash(l);
+ PyObject *l = mp_topylong(x);
+ long h = PyObject_Hash(l);
Py_DECREF(l); return (h);
}
+static long mp_pyhash(PyObject *me) { return (mphash(MP_X(me))); }
+
static PyObject *mpmeth_jacobi(PyObject *me, PyObject *arg)
{
mp *y = 0;
return (z);
}
+static PyObject *mpmeth_leastcongruent(PyObject *me, PyObject *arg)
+{
+ mp *z, *b, *m;
+ PyObject *rc = 0;
+
+ if (!PyArg_ParseTuple(arg, "O&O&:leastcongruent", convmp, &b, convmp, &m))
+ goto end;
+ z = mp_leastcongruent(MP_NEW, b, MP_X(me), m);
+ rc = mp_pywrap(z);
+end:
+ return (rc);
+}
+
#define STOREOP(name, c) \
static PyObject *mpmeth_##name(PyObject *me, \
PyObject *arg, PyObject *kw) \
"X.gcdx(Y) -> (gcd(X, Y), U, V) with X U + Y V = gcd(X, Y)")
METH (modinv, "X.modinv(Y) -> multiplicative inverse of Y mod X")
METH (modsqrt, "X.modsqrt(Y) -> square root of Y mod X, if X prime")
+ METH (leastcongruent,
+ "X.leastcongruent(B, M) -> smallest Z >= B with Z == X (mod M)")
KWMETH(primep, "X.primep(rng = rand) -> true/false if X is prime")
KWMETH(tostring, "X.tostring(radix = 10) -> STR")
KWMETH(storel, "X.storel(len = -1) -> little-endian bytes")
/* @tp_doc@ */
"Multiprecision integers, similar to `long' but more efficient and\n\
-versatile. Support all the standard arithmetic operations.\n\
+versatile. Support all the standard arithmetic operations, with\n\
+implicit conversions from `PrimeFilter', and other objects which\n\
+convert to `long'.\n\
\n\
-Constructor mp(X, radix = R) attempts to convert X to an `mp'. If\n\
+Constructor MP(X, radix = R) attempts to convert X to an `MP'. If\n\
X is a string, it's read in radix-R form, or we look for a prefix\n\
-if R = 0. Other acceptable things are ints and longs.\n\
+if R = 0. Other acceptable things are field elements, elliptic curve\n\
+points, group elements, Python `int' and `long' objects, and anything\n\
+with an integer conversion.\n\
\n\
Notes:\n\
\n\
return ((PyObject *)zz);
}
-static long gf_pyhash(PyObject *me)
-{
- long i = mp_tolong(MP_X(me));
- i ^= 0xc7ecd67c; /* random perturbance */
- if (i == -1)
- i = -2;
- return (i);
-}
-
static PyObject *gf_pyexp(PyObject *x, PyObject *y, PyObject *z)
{
mp *xx = 0, *yy = 0, *zz = 0;
&gf_pynumber, /* @tp_as_number@ */
0, /* @tp_as_sequence@ */
0, /* @tp_as_mapping@ */
- gf_pyhash, /* @tp_hash@ */
+ mp_pyhash, /* @tp_hash@ */
0, /* @tp_call@ */
mp_pyhex, /* @tp_str@ */
0, /* @tp_getattro@ */
"Binary polynomials. Support almost all the standard arithmetic\n\
operations.\n\
\n\
-Constructor gf(X, radix = R) attempts to convert X to a `gf'. If\n\
+Constructor GF(X, radix = R) attempts to convert X to a `GF'. If\n\
X is a string, it's read in radix-R form, or we look for a prefix\n\
-if R = 0. Other acceptable things are ints and longs.\n\
+if R = 0. Other acceptable things are field elements, elliptic curve\n\
+points, group elements, Python `int' and `long' objects, and anything\n\
+with an integer conversion.\n\
\n\
The name is hopelessly wrong from a technical point of view, but\n\
but it's much easier to type than `p2' or `c2' or whatever.\n\