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) \
static PyMethodDef mp_pymethods[] = {
#define METHNAME(func) mpmeth_##func
- METH (jacobi, "X.jacobi(Y) -> Jacobi symbol (Y/X) (NB inversion!)")
+ METH (jacobi, "X.jacobi(Y) -> Jacobi symbol (Y|X) (NB inversion!)")
METH (setbit, "X.setbit(N) -> X with bit N set")
METH (clearbit, "X.clearbit(N) -> X with bit N clear")
METH (testbit, "X.testbit(N) -> true/false if bit N set/clear in X")
"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")
- 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")
- KWMETH(storeb, "X.storeb(len = -1) -> big-endian bytes")
+ 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")
+ KWMETH(storeb, "X.storeb([len = -1]) -> big-endian bytes")
KWMETH(storel2c,
- "X.storel2c(len = -1) -> little-endian bytes, two's complement")
+ "X.storel2c([len = -1]) -> little-endian bytes, two's complement")
KWMETH(storeb2c,
- "X.storeb2c(len = -1) -> big-endian bytes, two's complement")
+ "X.storeb2c([len = -1]) -> big-endian bytes, two's complement")
METH (tobuf, "X.tobuf() -> buffer format")
#undef METHNAME
{ 0 }
/* @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\
for (i = 0; i < n; i++) {
if ((x = PySequence_GetItem(q, i)) == 0) goto end;
xx = getmp(x); Py_DECREF(x); if (!xx) goto end;
+ if (MP_CMP(xx, <=, MP_ZERO)) VALERR("moduli must be positive");
v[i].m = xx; v[i].n = 0; v[i].ni = 0; v[i].nni = 0;
}
c = (mpcrt_pyobj *)ty->tp_alloc(ty, 0);
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;
METH (irreduciblep, "X.irreduciblep() -> true/false")
#undef METHNAME
#define METHNAME(func) mpmeth_##func
- KWMETH(tostring, "X.tostring(radix = 10) -> STR")
- KWMETH(storel, "X.storel(len = -1) -> little-endian bytes")
- KWMETH(storeb, "X.storeb(len = -1) -> big-endian bytes")
+ KWMETH(tostring, "X.tostring([radix = 10]) -> STR")
+ KWMETH(storel, "X.storel([len = -1]) -> little-endian bytes")
+ KWMETH(storeb, "X.storeb([len = -1]) -> big-endian bytes")
KWMETH(storel2c,
- "X.storel2c(len = -1) -> little-endian bytes, two's complement")
+ "X.storel2c([len = -1]) -> little-endian bytes, two's complement")
KWMETH(storeb2c,
- "X.storeb2c(len = -1) -> big-endian bytes, two's complement")
+ "X.storeb2c([len = -1]) -> big-endian bytes, two's complement")
METH (tobuf, "X.tobuf() -> buffer format")
#undef METHNAME
{ 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\
static PyMethodDef methods[] = {
#define METHNAME(func) meth_##func
KWMETH(_MP_fromstring, "\
-fromstring(STR, radix = 0) -> (X, REST)\n\
+fromstring(STR, [radix = 0]) -> (X, REST)\n\
\n\
Parse STR as a large integer, according to radix. If radix is zero,\n\
read a prefix from STR to decide radix: allow `0' for octal, `0x' for hex\n\
or `R_' for other radix R.")
KWMETH(_GF_fromstring, "\
-fromstring(STR, radix = 0) -> (X, REST)\n\
+fromstring(STR, [radix = 0]) -> (X, REST)\n\
\n\
Parse STR as a binary polynomial, according to radix. If radix is zero,\n\
read a prefix from STR to decide radix: allow `0' for octal, `0x' for hex\n\