/* -*-c-*-
- *
- * $Id$
*
* Multiprecision arithmetic
*
* (c) 2004 Straylight/Edgeware
*/
-/*----- Licensing notice --------------------------------------------------*
+/*----- Licensing notice --------------------------------------------------*
*
* This file is part of the Python interface to Catacomb.
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* Catacomb/Python 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 General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with Catacomb/Python; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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 (PyFloat_FromDouble(f));
}
-#define COERCE(pre, PRE) \
+#define COERCE(pre, PRE) \
static int pre##_pycoerce(PyObject **x, PyObject **y) \
{ \
mp *z; \
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;
PyObject *z = 0;
if (!PyArg_ParseTuple(arg, "O&:jacobi", convmp, &y)) goto end;
- if (MP_NEGP(MP_X(me)) || MP_EVENP(MP_X(me)))
- VALERR("must be positive and odd");
z = PyInt_FromLong(mp_jacobi(y, MP_X(me)));
end:
if (y) MP_DROP(y);
}
BITOP(mp, setbit, 2c);
BITOP(mp, clearbit, 2c);
-BITOP(gf, setbit, );
+BITOP(gf, setbit, );
BITOP(gf, clearbit, );
#undef BITOP
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) \
{ \
buf b; \
char *p; \
- int sz; \
+ Py_ssize_t sz; \
PyObject *rc = 0; \
mp *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")
+ 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@ */
{
int r = 0;
char *p;
- int len;
+ Py_ssize_t len;
PyObject *z = 0;
mp *zz;
mptext_stringctx sc;
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);
}
+static PyObject *meth__MP_factorial(PyObject *me, PyObject *arg)
+{
+ unsigned long i;
+ mp *x;
+ if (!PyArg_ParseTuple(arg, "OO&:factorial", &me, convulong, &i))
+ return (0);
+ x = mp_factorial(i);
+ 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@ */
static PyObject *mm_mexpr(PyObject *me, void *v, int n)
{ return mp_pywrap(mpmont_mexpr(MPMONT_PY(me), MP_NEW, v, n)); }
-
+
static void mp_mexp_drop(void *p)
{
mp_expfactor *f = p;
static PyObject *mm_mexp(PyObject *me, void *v, int n)
{ return mp_pywrap(mpmont_mexp(MPMONT_PY(me), MP_NEW, v, n)); }
-
+
static PyObject *mmmeth_mexp(PyObject *me, PyObject *arg)
{
return mexp_common(me, arg, sizeof(mp_expfactor),
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@ */
static PyObject *mb_mexp(PyObject *me, void *v, int n)
{ return mp_pywrap(mpbarrett_mexp(MPBARRETT_PY(me), MP_NEW, v, n)); }
-
+
static PyObject *mbmeth_mexp(PyObject *me, PyObject *arg)
{
return mexp_common(me, arg, sizeof(mp_expfactor),
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@ */
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@ */
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@ */
METH (gcdx,
"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 (irreduciblep, "X.irreduciblep() -> true/false")
+ METH (irreduciblep, "X.irreduciblep() -> true/false")
#undef METHNAME
#define METHNAME(func) mpmeth_##func
KWMETH(tostring, "X.tostring(radix = 10) -> STR")
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@ */
{
int r = 0;
char *p;
- int len;
+ Py_ssize_t len;
PyObject *z = 0;
mp *zz;
mptext_stringctx sc;
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);
}
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@ */
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@ */
static PyMethodDef methods[] = {
#define METHNAME(func) meth_##func
- KWMETH(_MP_fromstring, "\
+ KWMETH(_MP_fromstring, "\
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, "\
+ KWMETH(_GF_fromstring, "\
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\
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, "\