return (z);
}
-static PyObject *meth__MP_product(PyObject *me, PyObject *arg)
+#define LOADOP(pre, py, name) \
+ static PyObject *meth__##py##_##name(PyObject *me, PyObject *arg) \
+ { \
+ char *p; \
+ int len; \
+ if (!PyArg_ParseTuple(arg, "Os#:" #name, &me, &p, &len)) return (0); \
+ return (pre##_pywrap(mp_##name(MP_NEW, p, len))); \
+ }
+LOADOP(mp, MP, loadl)
+LOADOP(mp, MP, loadb)
+LOADOP(mp, MP, loadl2c)
+LOADOP(mp, MP, loadb2c)
+LOADOP(gf, GF, loadl)
+LOADOP(gf, GF, loadb)
+#undef LOADOP
+
+/*----- Products of small integers ----------------------------------------*/
+
+typedef struct mpmul_pyobj {
+ PyObject_HEAD
+ int livep;
+ mpmul mm;
+} mpmul_pyobj;
+
+#define MPMUL_LIVEP(o) (((mpmul_pyobj *)(o))->livep)
+#define MPMUL_PY(o) (&((mpmul_pyobj *)(o))->mm)
+
+static void mpmul_pydealloc(PyObject *me)
+{
+ if (MPMUL_LIVEP(me))
+ mp_drop(mpmul_done(MPMUL_PY(me)));
+ FREEOBJ(me);
+}
+
+static PyObject *mmmeth_factor(PyObject *me, PyObject *arg)
{
- mpmul m;
PyObject *q, *i;
mp *x;
- if (PyTuple_Size(arg) != 2) {
+ if (!MPMUL_LIVEP(me)) VALERR("MPMul object invalid");
+ if (PyTuple_Size(arg) != 1)
i = PyObject_GetIter(arg);
- PyIter_Next(i);
- } else {
- if ((q = PyTuple_GetItem(arg, 1)) == 0) return (0);
+ else {
+ if ((q = PyTuple_GetItem(arg, 0)) == 0) goto end;
if ((i = PyObject_GetIter(q)) == 0) {
PyErr_Clear(); /* that's ok */
i = PyObject_GetIter(arg);
}
}
- if (!i) return (0);
- mpmul_init(&m);
+ if (!i) goto end;
while ((q = PyIter_Next(i)) != 0) {
x = getmp(q); Py_DECREF(q); if (!x) {
- MP_DROP(mpmul_done(&m));
Py_DECREF(i);
- return (0);
+ goto end;
}
- mpmul_add(&m, x);
+ mpmul_add(MPMUL_PY(me), x);
MP_DROP(x);
}
- x = mpmul_done(&m);
Py_DECREF(i);
+ RETURN_ME;
+end:
+ return (0);
+}
+
+static PyObject *mmmeth_done(PyObject *me, PyObject *arg)
+{
+ mp *x;
+
+ if (!PyArg_ParseTuple(arg, ":done")) goto end;
+ if (!MPMUL_LIVEP(me)) VALERR("MPMul object invalid");
+ x = mpmul_done(MPMUL_PY(me));
+ MPMUL_LIVEP(me) = 0;
return (mp_pywrap(x));
+end:
+ return (0);
}
-#define LOADOP(pre, py, name) \
- static PyObject *meth__##py##_##name(PyObject *me, PyObject *arg) \
- { \
- char *p; \
- int len; \
- if (!PyArg_ParseTuple(arg, "Os#:" #name, &me, &p, &len)) return (0); \
- return (pre##_pywrap(mp_##name(MP_NEW, p, len))); \
+static PyObject *mpmul_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
+{
+ mpmul_pyobj *mm;
+
+ if (kw) TYERR("keyword arguments not allowed here");
+ mm = (mpmul_pyobj *)ty->tp_alloc(ty, 0);
+ mpmul_init(&mm->mm);
+ mm->livep = 1;
+ if (mmmeth_factor((PyObject *)mm, arg) == 0) {
+ Py_DECREF(mm);
+ goto end;
}
-LOADOP(mp, MP, loadl)
-LOADOP(mp, MP, loadb)
-LOADOP(mp, MP, loadl2c)
-LOADOP(mp, MP, loadb2c)
-LOADOP(gf, GF, loadl)
-LOADOP(gf, GF, loadb)
-#undef LOADOP
+ return ((PyObject *)mm);
+end:
+ return (0);
+}
+
+static PyObject *mmget_livep(PyObject *me, void *hunoz)
+ { return (getbool(MPMUL_LIVEP(me))); }
+
+static PyGetSetDef mpmul_pygetset[] = {
+#define GETSETNAME(op, name) mm##op##_##name
+ GET (livep, "MM.livep -> flag: object still valid?")
+#undef GETSETNAME
+ { 0 }
+};
+
+static PyMethodDef mpmul_pymethods[] = {
+#define METHNAME(name) mmmeth_##name
+ METH (factor, "MM.factor(ITERABLE) or MM.factor(I, ...)")
+ METH (done, "MM.done() -> PRODUCT")
+#undef METHNAME
+ { 0 }
+};
+
+static PyTypeObject *mpmul_pytype, mpmul_pytype_skel = {
+ PyObject_HEAD_INIT(0) 0, /* Header */
+ "catacomb.MPMul", /* @tp_name@ */
+ sizeof(mpmul_pyobj), /* @tp_basicsize@ */
+ 0, /* @tp_itemsize@ */
+
+ mpmul_pydealloc, /* @tp_dealloc@ */
+ 0, /* @tp_print@ */
+ 0, /* @tp_getattr@ */
+ 0, /* @tp_setattr@ */
+ 0, /* @tp_compare@ */
+ 0, /* @tp_repr@ */
+ 0, /* @tp_as_number@ */
+ 0, /* @tp_as_sequence@ */
+ 0, /* @tp_as_mapping@ */
+ 0, /* @tp_hash@ */
+ 0, /* @tp_call@ */
+ 0, /* @tp_str@ */
+ 0, /* @tp_getattro@ */
+ 0, /* @tp_setattro@ */
+ 0, /* @tp_as_buffer@ */
+ Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
+ Py_TPFLAGS_BASETYPE,
+
+ /* @tp_doc@ */
+"An object for multiplying many small integers.",
+
+ 0, /* @tp_traverse@ */
+ 0, /* @tp_clear@ */
+ 0, /* @tp_richcompare@ */
+ 0, /* @tp_weaklistoffset@ */
+ 0, /* @tp_iter@ */
+ 0, /* @tp_iternext@ */
+ mpmul_pymethods, /* @tp_methods@ */
+ 0, /* @tp_members@ */
+ mpmul_pygetset, /* @tp_getset@ */
+ 0, /* @tp_base@ */
+ 0, /* @tp_dict@ */
+ 0, /* @tp_descr_get@ */
+ 0, /* @tp_descr_set@ */
+ 0, /* @tp_dictoffset@ */
+ 0, /* @tp_init@ */
+ PyType_GenericAlloc, /* @tp_alloc@ */
+ mpmul_pynew, /* @tp_new@ */
+ 0, /* @tp_free@ */
+ 0 /* @tp_is_gc@ */
+};
/*----- Montgomery reduction ----------------------------------------------*/
loadb2c(STR) -> X: read big-endian bytes, two's complement")
METH (_MP_frombuf, "\
frombuf(STR) -> (X, REST): read buffer format")
- METH (_MP_product, "\
-product(ITER) -> X: product of things iterated over")
METH (_GF_loadl, "\
loadl(STR) -> X: read little-endian bytes")
METH (_GF_loadb, "\
{
INITTYPE(mp, root);
INITTYPE(gf, root);
+ INITTYPE(mpmul, root);
INITTYPE(mpmont, root);
INITTYPE(mpbarrett, root);
INITTYPE(mpreduce, root);
void mp_pyinsert(PyObject *mod)
{
INSERT("MP", mp_pytype);
+ INSERT("MPMul", mpmul_pytype);
INSERT("MPMont", mpmont_pytype);
INSERT("MPBarrett", mpbarrett_pytype);
INSERT("MPReduce", mpreduce_pytype);