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))); }
mp *z;
mp_pyobj *zz = 0;
int radix = 0;
- char *kwlist[] = { "x", "radix", 0 };
+ static const char *const kwlist[] = { "x", "radix", 0 };
- if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|i:new", kwlist, &x, &radix))
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|i:new", KWLIST, &x, &radix))
goto end;
if (MP_PYCHECK(x)) RETURN_OBJ(x);
if (!good_radix_p(radix, 1)) VALERR("bad radix");
static PyObject *mpmeth_tostring(PyObject *me, PyObject *arg, PyObject *kw)
{
int radix = 10;
- char *kwlist[] = { "radix", 0 };
- if (!PyArg_ParseTupleAndKeywords(arg, kw, "|i:tostring", kwlist, &radix))
+ static const char *const kwlist[] = { "radix", 0 };
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "|i:tostring", KWLIST, &radix))
goto end;
if (!good_radix_p(radix, 0)) VALERR("bad radix");
return (mp_topystring(MP_X(me), radix, 0, 0, 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) \
{ \
long len = -1; \
- char *kwlist[] = { "len", 0 }; \
+ static const char *const kwlist[] = { "len", 0 }; \
PyObject *rc = 0; \
\
if (!PyArg_ParseTupleAndKeywords(arg, kw, "|l:" #name, \
- kwlist, &len)) \
+ KWLIST, &len)) \
goto end; \
if (len < 0) { \
len = mp_octets##c(MP_X(me)); \
{ \
buf b; \
char *p; \
- int sz; \
+ Py_ssize_t sz; \
PyObject *rc = 0; \
mp *x; \
\
static PyObject *mpmeth_primep(PyObject *me, PyObject *arg, PyObject *kw)
{
grand *r = &rand_global;
- char *kwlist[] = { "rng", 0 };
+ static const char *const kwlist[] = { "rng", 0 };
PyObject *rc = 0;
- if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&", kwlist, convgrand, &r))
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&", KWLIST, convgrand, &r))
goto end;
rc = getbool(pgen_primep(MP_X(me), r));
end:
"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")
static PyTypeObject mp_pytype_skel = {
PyObject_HEAD_INIT(0) 0, /* Header */
- "catacomb.MP", /* @tp_name@ */
+ "MP", /* @tp_name@ */
sizeof(mp_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
"Multiprecision integers, similar to `long' but more efficient and\n\
versatile. Support all the standard arithmetic operations.\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\
\n\
Notes:\n\
\n\
- * Use `//' for division. MPs don't have `/' division.",
+ * Use `//' for integer division. `/' gives exact rational division.",
0, /* @tp_traverse@ */
0, /* @tp_clear@ */
{
int r = 0;
char *p;
- int len;
+ Py_ssize_t len;
PyObject *z = 0;
mp *zz;
mptext_stringctx sc;
- char *kwlist[] = { "class", "x", "radix", 0 };
+ static const char *const kwlist[] = { "class", "x", "radix", 0 };
if (!PyArg_ParseTupleAndKeywords(arg, kw, "Os#|i:fromstring",
- kwlist, &me, &p, &len, &r))
+ KWLIST, &me, &p, &len, &r))
goto end;
if (!good_radix_p(r, 1)) VALERR("bad radix");
sc.buf = p; sc.lim = p + len;
if ((zz = mp_read(MP_NEW, r, &mptext_stringops, &sc)) == 0)
- SYNERR("bad integer");
- z = Py_BuildValue("(Ns#)", mp_pywrap(zz), sc.buf, (int)(sc.lim - sc.buf));
+ VALERR("bad integer");
+ z = Py_BuildValue("(Ns#)", mp_pywrap(zz),
+ sc.buf, (Py_ssize_t)(sc.lim - sc.buf));
end:
return (z);
}
return mp_pywrap(x);
}
+static PyObject *meth__MP_fibonacci(PyObject *me, PyObject *arg)
+{
+ long i;
+ mp *x;
+ if (!PyArg_ParseTuple(arg, "Ol:fibonacci", &me, &i)) return (0);
+ x = mp_fibonacci(i);
+ return mp_pywrap(x);
+}
+
#define LOADOP(pre, py, name) \
static PyObject *meth__##py##_##name(PyObject *me, PyObject *arg) \
{ \
char *p; \
- int len; \
+ Py_ssize_t len; \
if (!PyArg_ParseTuple(arg, "Os#:" #name, &me, &p, &len)) return (0); \
return (pre##_pywrap(mp_##name(MP_NEW, p, len))); \
}
static PyTypeObject *mpmul_pytype, mpmul_pytype_skel = {
PyObject_HEAD_INIT(0) 0, /* Header */
- "catacomb.MPMul", /* @tp_name@ */
+ "MPMul", /* @tp_name@ */
sizeof(mpmul_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
Py_TPFLAGS_BASETYPE,
/* @tp_doc@ */
-"An object for multiplying many small integers.",
+"MPMul(N_0, N_1, ....): an object for multiplying many small integers.",
0, /* @tp_traverse@ */
0, /* @tp_clear@ */
static PyObject *mpmont_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
{
mpmont_pyobj *mm = 0;
- char *kwlist[] = { "m", 0 };
+ static const char *const kwlist[] = { "m", 0 };
mp *xx = 0;
- if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", kwlist, convmp, &xx))
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convmp, &xx))
goto end;
if (!MP_POSP(xx) || !MP_ODDP(xx)) VALERR("m must be positive and odd");
mm = (mpmont_pyobj *)ty->tp_alloc(ty, 0);
static PyMethodDef mpmont_pymethods[] = {
#define METHNAME(name) mmmeth_##name
- METH (int, "M.out(X) -> XR")
+ METH (int, "M.int(X) -> XR")
METH (mul, "M.mul(XR, YR) -> ZR where Z = X Y")
METH (expr, "M.expr(XR, N) -> ZR where Z = X^N mod M.m")
METH (mexpr, "\
-B.mexp([(XR0, N0), (XR1, N1), ...]) = ZR where Z = X0^N0 X1^N1 mod B.m\n\
+M.mexpr([(XR0, N0), (XR1, N1), ...]) = ZR where Z = X0^N0 X1^N1 ... mod M.m\n\
\t(the list may be flattened if this more convenient.)")
METH (reduce, "M.reduce(XR) -> X")
METH (ext, "M.ext(XR) -> X")
METH (exp, "M.exp(X, N) -> X^N mod M.m")
METH (mexp, "\
-B.mexp([(X0, N0), (X1, N1), ...]) = X0^N0 X1^N1 mod B.m\n\
+M.mexp([(X0, N0), (X1, N1), ...]) = X0^N0 X1^N1 ... mod M.m\n\
\t(the list may be flattened if this more convenient.)")
#undef METHNAME
{ 0 }
static PyTypeObject *mpmont_pytype, mpmont_pytype_skel = {
PyObject_HEAD_INIT(0) 0, /* Header */
- "catacomb.MPMont", /* @tp_name@ */
+ "MPMont", /* @tp_name@ */
sizeof(mpmont_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
Py_TPFLAGS_BASETYPE,
/* @tp_doc@ */
-"A Montgomery reduction context.",
+"MPMont(N): a Montgomery reduction context.",
0, /* @tp_traverse@ */
0, /* @tp_clear@ */
PyObject *arg, PyObject *kw)
{
mpbarrett_pyobj *mb = 0;
- char *kwlist[] = { "m", 0 };
+ static const char *const kwlist[] = { "m", 0 };
mp *xx = 0;
- if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", kwlist, convmp, &xx))
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convmp, &xx))
goto end;
if (!MP_POSP(xx)) VALERR("m must be positive");
mb = (mpbarrett_pyobj *)ty->tp_alloc(ty, 0);
METH (reduce, "B.reduce(X) -> X mod B.m")
METH (exp, "B.exp(X, N) -> X^N mod B.m")
METH (mexp, "\
-B.mexp([(X0, N0), (X1, N1), ...]) = X0^N0 X1^N1 mod B.m\n\
+B.mexp([(X0, N0), (X1, N1), ...]) = X0^N0 X1^N1 ... mod B.m\n\
\t(the list may be flattened if this more convenient.)")
#undef METHNAME
{ 0 }
static PyTypeObject *mpbarrett_pytype, mpbarrett_pytype_skel = {
PyObject_HEAD_INIT(0) 0, /* Header */
- "catacomb.MPBarrett", /* @tp_name@ */
+ "MPBarrett", /* @tp_name@ */
sizeof(mpbarrett_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
Py_TPFLAGS_BASETYPE,
/* @tp_doc@ */
-"A Barrett reduction context.",
+"MPBarrett(N): a Barrett reduction context.",
0, /* @tp_traverse@ */
0, /* @tp_clear@ */
{
mpreduce_pyobj *mr = 0;
mpreduce r;
- char *kwlist[] = { "m", 0 };
+ static const char *const kwlist[] = { "m", 0 };
mp *xx = 0;
- if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", kwlist, convmp, &xx))
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convmp, &xx))
goto end;
if (!MP_POSP(xx)) VALERR("m must be positive");
if (mpreduce_create(&r, xx)) VALERR("bad modulus (must be 2^k - ...)");
static PyTypeObject *mpreduce_pytype, mpreduce_pytype_skel = {
PyObject_HEAD_INIT(0) 0, /* Header */
- "catacomb.MPReduce", /* @tp_name@ */
+ "MPReduce", /* @tp_name@ */
sizeof(mpreduce_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
Py_TPFLAGS_BASETYPE,
/* @tp_doc@ */
-"A reduction context for reduction modulo primes of special form.",
+"MPReduce(N): a reduction context for reduction modulo Solinas primes.",
0, /* @tp_traverse@ */
0, /* @tp_clear@ */
{
mpcrt_mod *v = 0;
int n, i = 0;
- char *kwlist[] = { "mv", 0 };
+ static const char *const kwlist[] = { "mv", 0 };
PyObject *q = 0, *x;
mp *xx;
mpcrt_pyobj *c = 0;
if (PyTuple_Size(arg) > 1)
q = arg;
- else if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:new", kwlist, &q))
+ else if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:new", KWLIST, &q))
goto end;
Py_INCREF(q);
if (!PySequence_Check(q)) TYERR("want a sequence of moduli");
static PyTypeObject *mpcrt_pytype, mpcrt_pytype_skel = {
PyObject_HEAD_INIT(0) 0, /* Header */
- "catacomb.MPCRT", /* @tp_name@ */
+ "MPCRT", /* @tp_name@ */
sizeof(mpcrt_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
Py_TPFLAGS_BASETYPE,
/* @tp_doc@ */
-"A context for the solution of Chinese Remainder Theorem problems.",
+"MPCRT(SEQ): a context for solving Chinese Remainder Theorem problems.",
0, /* @tp_traverse@ */
0, /* @tp_clear@ */
mp *z;
mp_pyobj *zz = 0;
int radix = 0;
- char *kwlist[] = { "x", "radix", 0 };
+ static const char *const kwlist[] = { "x", "radix", 0 };
- if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|i:gf", kwlist, &x, &radix))
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|i:gf", KWLIST, &x, &radix))
goto end;
if (GF_PYCHECK(x)) RETURN_OBJ(x);
if (!good_radix_p(radix, 1)) VALERR("radix out of range");
static PyTypeObject gf_pytype_skel = {
PyObject_HEAD_INIT(0) 0, /* Header */
- "catacomb.GF", /* @tp_name@ */
+ "GF", /* @tp_name@ */
sizeof(mp_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
\n\
Notes:\n\
\n\
- * Use `//' for division. GFs don't have `/' division.",
+ * Use `//' for Euclidean division. `/' gives exact rational division.",
0, /* @tp_traverse@ */
0, /* @tp_clear@ */
{
int r = 0;
char *p;
- int len;
+ Py_ssize_t len;
PyObject *z = 0;
mp *zz;
mptext_stringctx sc;
- char *kwlist[] = { "class", "x", "radix", 0 };
+ static const char *const kwlist[] = { "class", "x", "radix", 0 };
if (!PyArg_ParseTupleAndKeywords(arg, kw, "Os#|i:fromstring",
- kwlist, &me, &p, &len, &r))
+ KWLIST, &me, &p, &len, &r))
goto end;
if (!good_radix_p(r, 1)) VALERR("bad radix");
sc.buf = p; sc.lim = p + len;
if ((zz = mp_read(MP_NEW, r, &mptext_stringops, &sc)) == 0 ||
MP_NEGP(zz)) {
if (zz) MP_DROP(zz);
- SYNERR("bad binary polynomial");
+ VALERR("bad binary polynomial");
}
- z = Py_BuildValue("(Ns#)", gf_pywrap(zz), sc.buf, (int)(sc.lim - sc.buf));
+ z = Py_BuildValue("(Ns#)", gf_pywrap(zz),
+ sc.buf, (Py_ssize_t)(sc.lim - sc.buf));
end:
return (z);
}
{
gfreduce_pyobj *mr = 0;
gfreduce r;
- char *kwlist[] = { "m", 0 };
+ static const char *const kwlist[] = { "m", 0 };
mp *xx = 0;
- if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", kwlist, convgf, &xx))
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convgf, &xx))
goto end;
if (MP_ZEROP(xx)) ZDIVERR("modulus is zero!");
gfreduce_create(&r, xx);
static PyTypeObject *gfreduce_pytype, gfreduce_pytype_skel = {
PyObject_HEAD_INIT(0) 0, /* Header */
- "catacomb.GFReduce", /* @tp_name@ */
+ "GFReduce", /* @tp_name@ */
sizeof(gfreduce_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
Py_TPFLAGS_BASETYPE,
/* @tp_doc@ */
-"A reduction context for reduction modulo sparse irreducible polynomials.",
+"GFReduce(N): a context for reduction modulo sparse polynomials.",
0, /* @tp_traverse@ */
0, /* @tp_clear@ */
{
mp *p = 0, *beta = 0;
gfn_pyobj *gg = 0;
- char *kwlist[] = { "p", "beta", 0 };
+ static const char *const kwlist[] = { "p", "beta", 0 };
- if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", kwlist,
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", KWLIST,
convgf, &p, convgf, &beta))
goto end;
gg = PyObject_New(gfn_pyobj, ty);
static PyTypeObject gfn_pytype_skel = {
PyObject_HEAD_INIT(0) 0, /* Header */
- "catacomb.GFN", /* @tp_name@ */
+ "GFN", /* @tp_name@ */
sizeof(gfn_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
Py_TPFLAGS_BASETYPE,
/* @tp_doc@ */
-"An object for transforming elements of binary fields between polynomial\n\
-and normal basis representations.",
+"GFN(P, BETA): an object for transforming elements of binary fields\n\
+ between polynomial and normal basis representations.",
0, /* @tp_traverse@ */
0, /* @tp_clear@ */
or `R_' for other radix R.")
METH (_MP_factorial, "\
factorial(I) -> I!: compute factorial")
+ METH (_MP_fibonacci, "\
+fibonacci(I) -> F(I): compute Fibonacci number")
METH (_MP_loadl, "\
loadl(STR) -> X: read little-endian bytes")
METH (_MP_loadb, "\