3 * Prime number generation
5 * (c) 2005 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of the Python interface to Catacomb.
12 * Catacomb/Python is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * Catacomb/Python is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with Catacomb/Python; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 /*----- Header files ------------------------------------------------------*/
29 #include "catacomb-python.h"
31 /*----- Filters -----------------------------------------------------------*/
33 PyTypeObject *pfilt_pytype;
35 static PyObject *pfilt_pywrap(pfilt *f)
38 o = PyObject_New(pfilt_pyobj, pfilt_pytype);
40 o->st = pfilt_step(f, 0);
41 return ((PyObject *)o);
44 static PyObject *pfilt_pymake(PyTypeObject *ty, PyObject *xobj)
49 if (PFILT_PYCHECK(xobj)) RETURN_OBJ(xobj);
50 if ((x = getmp(xobj)) == 0) goto end;
51 o = (pfilt_pyobj *)ty->tp_alloc(ty, 0);
52 o->st = pfilt_create(&o->f, x);
55 return ((PyObject *)o);
58 static PyObject *pfilt_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
60 char *kwlist[] = { "x", 0 };
63 if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:new", kwlist, &xobj))
65 return (pfilt_pymake(ty, xobj));
68 static void pfilt_pydealloc(PyObject *me)
69 { pfilt_destroy(PFILT_F(me)); FREEOBJ(me); }
71 static PyObject *pfmeth_step(PyObject *me, PyObject *arg)
75 if (!PyArg_ParseTuple(arg, "O&:step", convmpw, &x)) return (0);
76 PFILT_ST(me) = pfilt_step(PFILT_F(me), x);
80 static PyObject *pfmeth_muladd(PyObject *me, PyObject *arg)
85 if (!PyArg_ParseTuple(arg, "O&O&:muladd", convmpw, &m, convmpw, &a))
87 o = PyObject_New(pfilt_pyobj, pfilt_pytype);
88 o->st = pfilt_muladd(&o->f, PFILT_F(me), m, a);
89 return ((PyObject *)o);
92 static CONVFUNC(pfilt, pfilt *, PFILT_F)
94 static PyObject *pfmeth_jump(PyObject *me, PyObject *arg)
98 if (!PyArg_ParseTuple(arg, "O&:jump", convpfilt, &f)) return (0);
99 PFILT_ST(me) = pfilt_jump(PFILT_F(me), f);
103 static PyObject *meth__PrimeFilter_smallfactor(PyObject *me, PyObject *arg)
108 if (!PyArg_ParseTuple(arg, "OO&:smallfactor", &me, convmp, &x)) goto end;
109 rc = PyInt_FromLong(pfilt_smallfactor(x));
115 static int pfilt_pynonzerop(PyObject *me)
116 { return (PFILT_ST(me) != PGEN_FAIL); }
118 static PyObject *pfilt_pyint(PyObject *me)
123 if (!mp_tolong_checked(PFILT_F(me)->m, &l, 0)) rc = PyInt_FromLong(l);
124 else rc = mp_topylong(PFILT_F(me)->m);
128 static PyObject *pfilt_pylong(PyObject *me)
129 { return (mp_topylong(PFILT_F(me)->m)); }
131 static PyObject *pfget_x(PyObject *me, void *hunoz)
132 { return (mp_pywrap(MP_COPY(PFILT_F(me)->m))); }
134 static PyObject *pfget_status(PyObject *me, void *hunoz)
135 { return (PyInt_FromLong(PFILT_ST(me))); }
137 static PyGetSetDef pfilt_pygetset[] = {
138 #define GETSETNAME(op, name) pf##op##_##name
139 GET (x, "F.x -> current position of filter")
140 GET (status, "F.status -> primality status of filter")
145 static PyMethodDef pfilt_pymethods[] = {
146 #define METHNAME(name) pfmeth_##name
147 METH (step, "F.step(N)")
148 METH (muladd, "F.muladd(M, A)")
149 METH (jump, "F.jump(FF)")
154 static PyNumberMethods pfilt_pynumber = {
156 0, /* @nb_subtract@ */
157 0, /* @nb_multiply@ */
159 0, /* @nb_remainder@ */
162 0, /* @nb_negative@ */
163 0, /* @nb_positive@ */
164 0, /* @nb_absolute@ */
165 pfilt_pynonzerop, /* @nb_nonzero@ */
173 pfilt_pyint, /* @nb_int@ */
174 pfilt_pylong, /* @nb_long@ */
179 0, /* @nb_inplace_add@ */
180 0, /* @nb_inplace_subtract@ */
181 0, /* @nb_inplace_multiply@ */
182 0, /* @nb_inplace_divide@ */
183 0, /* @nb_inplace_remainder@ */
184 0, /* @nb_inplace_power@ */
185 0, /* @nb_inplace_lshift@ */
186 0, /* @nb_inplace_rshift@ */
187 0, /* @nb_inplace_and@ */
188 0, /* @nb_inplace_xor@ */
189 0, /* @nb_inplace_or@ */
191 0, /* @nb_floor_divide@ */
192 0, /* @nb_true_divide@ */
193 0, /* @nb_inplace_floor_divide@ */
194 0, /* @nb_inplace_true_divide@ */
197 static PyTypeObject pfilt_pytype_skel = {
198 PyObject_HEAD_INIT(0) 0, /* Header */
199 "PrimeFilter", /* @tp_name@ */
200 sizeof(pfilt_pyobj), /* @tp_basicsize@ */
201 0, /* @tp_itemsize@ */
203 pfilt_pydealloc, /* @tp_dealloc@ */
205 0, /* @tp_getattr@ */
206 0, /* @tp_setattr@ */
207 0, /* @tp_compare@ */
209 &pfilt_pynumber, /* @tp_as_number@ */
210 0, /* @tp_as_sequence@ */
211 0, /* @tp_as_mapping@ */
215 0, /* @tp_getattro@ */
216 0, /* @tp_setattro@ */
217 0, /* @tp_as_buffer@ */
218 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
222 "Small-primes filter.",
224 0, /* @tp_traverse@ */
226 0, /* @tp_richcompare@ */
227 0, /* @tp_weaklistoffset@ */
229 0, /* @tp_iternext@ */
230 pfilt_pymethods, /* @tp_methods@ */
231 0, /* @tp_members@ */
232 pfilt_pygetset, /* @tp_getset@ */
235 0, /* @tp_descr_get@ */
236 0, /* @tp_descr_set@ */
237 0, /* @tp_dictoffset@ */
239 PyType_GenericAlloc, /* @tp_alloc@ */
240 pfilt_pynew, /* @tp_new@ */
245 /*----- Rabin-Miller testing ----------------------------------------------*/
247 typedef struct rabin_pyobj {
252 static PyTypeObject *rabin_pytype;
253 #define RABIN_R(o) (&((rabin_pyobj *)(o))->r)
255 static PyObject *rabin_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
259 char *kwlist[] = { "x", 0 };
261 if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", kwlist, convmp, &x))
263 if (!MP_POSP(x) || MP_EVENP(x)) VALERR("must be positive and odd");
264 o = (rabin_pyobj *)ty->tp_alloc(ty, 0);
265 rabin_create(&o->r, x);
267 return ((PyObject *)o);
270 static void rabin_pydealloc(PyObject *me)
272 rabin_destroy(RABIN_R(me));
276 static PyObject *rmeth_test(PyObject *me, PyObject *arg)
281 if (!PyArg_ParseTuple(arg, "O&:test", convmp, &w)) goto end;
282 rc = PyInt_FromLong(rabin_test(RABIN_R(me), w));
288 static PyObject *rmeth_rtest(PyObject *me, PyObject *arg)
293 if (!PyArg_ParseTuple(arg, "O&:rtest", convmp, &w)) goto end;
294 rc = PyInt_FromLong(rabin_rtest(RABIN_R(me), w));
300 static PyObject *rget_niters(PyObject *me, void *hunoz)
301 { return (PyInt_FromLong(rabin_iters(mp_bits(RABIN_R(me)->mm.m)))); }
303 static PyObject *rget_x(PyObject *me, void *hunoz)
304 { return (mp_pywrap(MP_COPY(RABIN_R(me)->mm.m))); }
306 static PyObject *meth__RabinMiller_iters(PyObject *me, PyObject *arg)
310 if (!PyArg_ParseTuple(arg, "OO&:iters", &me, convuint, &n)) return (0);
311 return (PyInt_FromLong(rabin_iters(n)));
314 static PyGetSetDef rabin_pygetset[] = {
315 #define GETSETNAME(op, name) r##op##_##name
316 GET (x, "R.x -> number under test")
317 GET (niters, "R.niters -> suggested number of tests")
322 static PyMethodDef rabin_pymethods[] = {
323 #define METHNAME(name) rmeth_##name
324 METH (test, "R.test(W) -> PGST")
325 METH (rtest, "R.rtest(W) -> PGST")
330 static PyTypeObject rabin_pytype_skel = {
331 PyObject_HEAD_INIT(0) 0, /* Header */
332 "RabinMiller", /* @tp_name@ */
333 sizeof(rabin_pyobj), /* @tp_basicsize@ */
334 0, /* @tp_itemsize@ */
336 rabin_pydealloc, /* @tp_dealloc@ */
338 0, /* @tp_getattr@ */
339 0, /* @tp_setattr@ */
340 0, /* @tp_compare@ */
342 0, /* @tp_as_number@ */
343 0, /* @tp_as_sequence@ */
344 0, /* @tp_as_mapping@ */
348 0, /* @tp_getattro@ */
349 0, /* @tp_setattro@ */
350 0, /* @tp_as_buffer@ */
351 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
355 "Rabin-Miller strong primality test.",
357 0, /* @tp_traverse@ */
359 0, /* @tp_richcompare@ */
360 0, /* @tp_weaklistoffset@ */
362 0, /* @tp_iternext@ */
363 rabin_pymethods, /* @tp_methods@ */
364 0, /* @tp_members@ */
365 rabin_pygetset, /* @tp_getset@ */
368 0, /* @tp_descr_get@ */
369 0, /* @tp_descr_set@ */
370 0, /* @tp_dictoffset@ */
372 PyType_GenericAlloc, /* @tp_alloc@ */
373 rabin_pynew, /* @tp_new@ */
378 /*----- Events ------------------------------------------------------------*/
380 typedef struct pgevent_pyobj {
385 static PyTypeObject *pgevent_pytype;
386 #define PGEVENT_EV(o) (((pgevent_pyobj *)(o))->ev)
388 static PyObject *pgevent_pywrap(pgen_event *ev)
390 pgevent_pyobj *o = PyObject_New(pgevent_pyobj, pgevent_pytype);
392 return ((PyObject *)o);
395 static CONVFUNC(pgevent, pgen_event *, PGEVENT_EV)
397 static void pgevent_kill(PyObject *me) { PGEVENT_EV(me) = 0; }
398 static void pgevent_pydealloc(PyObject *me) { FREEOBJ(me); }
400 #define PGEVENT_CHECK(me) do { \
401 if (!PGEVENT_EV(me)) { \
402 PyErr_SetString(PyExc_ValueError, "event object is dead"); \
407 static PyObject *peget_name(PyObject *me, void *hunoz)
408 { PGEVENT_CHECK(me); return (PyString_FromString(PGEVENT_EV(me)->name)); }
410 static PyObject *peget_x(PyObject *me, void *hunoz)
411 { PGEVENT_CHECK(me); return (mp_pywrap(MP_COPY(PGEVENT_EV(me)->m))); }
413 static PyObject *peget_steps(PyObject *me, void *hunoz)
414 { PGEVENT_CHECK(me); return (PyInt_FromLong(PGEVENT_EV(me)->steps)); }
416 static PyObject *peget_tests(PyObject *me, void *hunoz)
417 { PGEVENT_CHECK(me); return (PyInt_FromLong(PGEVENT_EV(me)->tests)); }
419 static PyObject *peget_rng(PyObject *me, void *hunoz)
420 { PGEVENT_CHECK(me); return (grand_pywrap(PGEVENT_EV(me)->r, 0)); }
422 static int peset_x(PyObject *me, PyObject *xobj, void *hunoz)
425 pgen_event *ev = PGEVENT_EV(me);
428 if ((x = getmp(xobj)) == 0) goto end;
437 static PyGetSetDef pgevent_pygetset[] = {
438 #define GETSETNAME(op, name) pe##op##_##name
439 GET (name, "EV.name -> value being generated")
440 GETSET(x, "EV.x -> value under test")
441 GET (steps, "EV.steps -> number of steps left")
442 GET (tests, "EV.tests -> tests before passing")
443 GET (rng, "EV.rng -> (noncrypto) random number generator")
448 static PyTypeObject pgevent_pytype_skel = {
449 PyObject_HEAD_INIT(0) 0, /* Header */
450 "PrimeGenEvent", /* @tp_name@ */
451 sizeof(pgevent_pyobj), /* @tp_basicsize@ */
452 0, /* @tp_itemsize@ */
454 pgevent_pydealloc, /* @tp_dealloc@ */
456 0, /* @tp_getattr@ */
457 0, /* @tp_setattr@ */
458 0, /* @tp_compare@ */
460 0, /* @tp_as_number@ */
461 0, /* @tp_as_sequence@ */
462 0, /* @tp_as_mapping@ */
466 0, /* @tp_getattro@ */
467 0, /* @tp_setattro@ */
468 0, /* @tp_as_buffer@ */
469 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
473 "Prime-generation event.",
475 0, /* @tp_traverse@ */
477 0, /* @tp_richcompare@ */
478 0, /* @tp_weaklistoffset@ */
480 0, /* @tp_iternext@ */
481 0, /* @tp_methods@ */
482 0, /* @tp_members@ */
483 pgevent_pygetset, /* @tp_getset@ */
486 0, /* @tp_descr_get@ */
487 0, /* @tp_descr_set@ */
488 0, /* @tp_dictoffset@ */
490 PyType_GenericAlloc, /* @tp_alloc@ */
491 abstract_pynew, /* @tp_new@ */
496 /*----- Event handlers ----------------------------------------------------*/
498 PyTypeObject *pgev_pytype;
500 typedef struct pgstep_pyobj {
505 static PyTypeObject *pgstep_pytype;
506 #define PGSTEP_STEP(o) (((pgstep_pyobj *)(o))->f.step)
508 typedef struct pgjump_pyobj {
514 static PyTypeObject *pgjump_pytype;
515 #define PGJUMP_FOBJ(o) (((pgjump_pyobj *)(o))->fobj)
516 #define PGJUMP_J(o) (&((pgjump_pyobj *)(o))->j)
518 typedef struct pgtest_pyobj {
523 static PyTypeObject *pgtest_pytype;
525 static int pgev_python(int rq, pgen_event *ev, void *p)
533 "pg_abort", "pg_done", "pg_begin", "pg_try", "pg_fail", "pg_pass"
538 if (rq > N(meth)) SYSERR("event code out of range");
539 pyev = pgevent_pywrap(ev);
540 if ((rc = PyObject_CallMethod(py, meth[rq], "(O)", pyev)) == 0)
544 else if ((l = PyInt_AsLong(rc)) == -1 && PyErr_Occurred())
546 else if (l < PGEN_ABORT || l > PGEN_PASS)
547 VALERR("return code out of range");
560 static PyObject *pgev_pywrap(const pgev *pg)
564 o = PyObject_New(pgev_pyobj, pgev_pytype);
566 return ((PyObject *)o);
569 int convpgev(PyObject *o, void *p)
576 pg->proc = pgev_python;
583 void droppgev(pgev *p)
585 if (p->proc == pgev_python) {
586 PyObject *py = p->ctx;
591 static PyObject *pgmeth_common(PyObject *me, PyObject *arg, int rq)
594 pgev *pg = PGEV_PG(me);
597 if (!PyArg_ParseTuple(arg, "O&", convpgevent, &ev)) goto end;
598 rc = PyInt_FromLong(!pg->proc ? rq : pg->proc(rq, ev, pg->ctx));
603 #define PGMETH(lc, uc) \
604 static PyObject *pgmeth_pg_##lc(PyObject *me, PyObject *arg) \
605 { return pgmeth_common(me, arg, PGEN_##uc); }
614 static PyObject *pgev_stdev(pgen_proc *proc)
615 { pgev pg; pg.proc = proc; pg.ctx = 0; return (pgev_pywrap(&pg)); }
617 static PyMethodDef pgev_pymethods[] = {
618 #define METHNAME(name) pgmeth_##name
619 METH (pg_abort, "E.pg_abort() -> PGRC -- prime generation aborted")
620 METH (pg_done, "E.pg_done() -> PGRC -- prime generation finished")
621 METH (pg_begin, "E.pg_begin() -> PGRC -- commence stepping/testing")
622 METH (pg_try, "E.pg_try() -> PGRC -- found new candidate")
623 METH (pg_pass, "E.pg_pass() -> PGRC -- passed primality test")
624 METH (pg_fail, "E.pg_fail() -> PGRC -- failed primality test")
629 static PyTypeObject pgev_pytype_skel = {
630 PyObject_HEAD_INIT(0) 0, /* Header */
631 "PrimeGenBuiltinHandler", /* @tp_name@ */
632 sizeof(pgev_pyobj), /* @tp_basicsize@ */
633 0, /* @tp_itemsize@ */
635 0, /* @tp_dealloc@ */
637 0, /* @tp_getattr@ */
638 0, /* @tp_setattr@ */
639 0, /* @tp_compare@ */
641 0, /* @tp_as_number@ */
642 0, /* @tp_as_sequence@ */
643 0, /* @tp_as_mapping@ */
647 0, /* @tp_getattro@ */
648 0, /* @tp_setattro@ */
649 0, /* @tp_as_buffer@ */
650 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
654 "Built-in prime-generation event handler, base class.",
656 0, /* @tp_traverse@ */
658 0, /* @tp_richcompare@ */
659 0, /* @tp_weaklistoffset@ */
661 0, /* @tp_iternext@ */
662 pgev_pymethods, /* @tp_methods@ */
663 0, /* @tp_members@ */
667 0, /* @tp_descr_get@ */
668 0, /* @tp_descr_set@ */
669 0, /* @tp_dictoffset@ */
671 PyType_GenericAlloc, /* @tp_alloc@ */
672 abstract_pynew, /* @tp_new@ */
677 static PyObject *pgstep_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
680 pgstep_pyobj *rc = 0;
681 char *kwlist[] = { "step", 0 };
683 if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", kwlist, convmpw, &s))
685 rc = (pgstep_pyobj *)ty->tp_alloc(ty, 0);
687 rc->pg.proc = pgen_filter;
690 return ((PyObject *)rc);
693 static PyObject *psget_step(PyObject *me, void *hunoz)
694 { return (PyInt_FromLong(PGSTEP_STEP(me))); }
696 static PyGetSetDef pgstep_pygetset[] = {
697 #define GETSETNAME(op, name) ps##op##_##name
698 GET (step, "S.step -> step size for the stepper")
703 static PyTypeObject pgstep_pytype_skel = {
704 PyObject_HEAD_INIT(0) 0, /* Header */
705 "PrimeGenStepper", /* @tp_name@ */
706 sizeof(pgstep_pyobj), /* @tp_basicsize@ */
707 0, /* @tp_itemsize@ */
709 0, /* @tp_dealloc@ */
711 0, /* @tp_getattr@ */
712 0, /* @tp_setattr@ */
713 0, /* @tp_compare@ */
715 0, /* @tp_as_number@ */
716 0, /* @tp_as_sequence@ */
717 0, /* @tp_as_mapping@ */
721 0, /* @tp_getattro@ */
722 0, /* @tp_setattro@ */
723 0, /* @tp_as_buffer@ */
724 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
728 "Simple prime-number stepper with small-factors filter.",
730 0, /* @tp_traverse@ */
732 0, /* @tp_richcompare@ */
733 0, /* @tp_weaklistoffset@ */
735 0, /* @tp_iternext@ */
736 0, /* @tp_methods@ */
737 0, /* @tp_members@ */
738 pgstep_pygetset, /* @tp_getset@ */
741 0, /* @tp_descr_get@ */
742 0, /* @tp_descr_set@ */
743 0, /* @tp_dictoffset@ */
745 PyType_GenericAlloc, /* @tp_alloc@ */
746 pgstep_pynew, /* @tp_new@ */
751 static PyObject *pgjump_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
754 pgjump_pyobj *rc = 0;
755 char *kwlist[] = { "jump", 0 };
757 if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:new", kwlist, &o) ||
758 (fobj = pfilt_pymake(pfilt_pytype, o)) == 0)
760 rc = (pgjump_pyobj *)ty->tp_alloc(ty, 0);
762 rc->j.j = PFILT_F(fobj);
763 rc->pg.proc = pgen_jump;
766 return ((PyObject *)rc);
769 static void pgjump_pydealloc(PyObject *me)
771 Py_DECREF(PGJUMP_FOBJ(me));
775 static PyObject *pjget_jump(PyObject *me, void *hunoz)
776 { RETURN_OBJ(PGJUMP_FOBJ(me)); }
778 static PyGetSetDef pgjump_pygetset[] = {
779 #define GETSETNAME(op, name) pj##op##_##name
780 GET (jump, "S.jump -> jump size for the stepper")
785 static PyTypeObject pgjump_pytype_skel = {
786 PyObject_HEAD_INIT(0) 0, /* Header */
787 "PrimeGenJumper", /* @tp_name@ */
788 sizeof(pgjump_pyobj), /* @tp_basicsize@ */
789 0, /* @tp_itemsize@ */
791 pgjump_pydealloc, /* @tp_dealloc@ */
793 0, /* @tp_getattr@ */
794 0, /* @tp_setattr@ */
795 0, /* @tp_compare@ */
797 0, /* @tp_as_number@ */
798 0, /* @tp_as_sequence@ */
799 0, /* @tp_as_mapping@ */
803 0, /* @tp_getattro@ */
804 0, /* @tp_setattro@ */
805 0, /* @tp_as_buffer@ */
806 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
810 "Stepper for larger steps, with small-factors filter.",
812 0, /* @tp_traverse@ */
814 0, /* @tp_richcompare@ */
815 0, /* @tp_weaklistoffset@ */
817 0, /* @tp_iternext@ */
818 0, /* @tp_methods@ */
819 0, /* @tp_members@ */
820 pgjump_pygetset, /* @tp_getset@ */
823 0, /* @tp_descr_get@ */
824 0, /* @tp_descr_set@ */
825 0, /* @tp_dictoffset@ */
827 PyType_GenericAlloc, /* @tp_alloc@ */
828 pgjump_pynew, /* @tp_new@ */
833 static PyObject *pgtest_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
835 pgtest_pyobj *rc = 0;
836 char *kwlist[] = { 0 };
838 if (!PyArg_ParseTupleAndKeywords(arg, kw, ":new", kwlist)) goto end;
839 rc = (pgtest_pyobj *)ty->tp_alloc(ty, 0);
840 rc->pg.proc = pgen_test;
843 return ((PyObject *)rc);
846 static PyTypeObject pgtest_pytype_skel = {
847 PyObject_HEAD_INIT(0) 0, /* Header */
848 "PrimeGenTester", /* @tp_name@ */
849 sizeof(pgtest_pyobj), /* @tp_basicsize@ */
850 0, /* @tp_itemsize@ */
852 0, /* @tp_dealloc@ */
854 0, /* @tp_getattr@ */
855 0, /* @tp_setattr@ */
856 0, /* @tp_compare@ */
858 0, /* @tp_as_number@ */
859 0, /* @tp_as_sequence@ */
860 0, /* @tp_as_mapping@ */
864 0, /* @tp_getattro@ */
865 0, /* @tp_setattro@ */
866 0, /* @tp_as_buffer@ */
867 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
871 "Rabin-Miller tester.",
873 0, /* @tp_traverse@ */
875 0, /* @tp_richcompare@ */
876 0, /* @tp_weaklistoffset@ */
878 0, /* @tp_iternext@ */
879 0, /* @tp_methods@ */
880 0, /* @tp_members@ */
884 0, /* @tp_descr_get@ */
885 0, /* @tp_descr_set@ */
886 0, /* @tp_dictoffset@ */
888 PyType_GenericAlloc, /* @tp_alloc@ */
889 pgtest_pynew, /* @tp_new@ */
894 /*----- Prime generation functions ----------------------------------------*/
898 if (!PyErr_Occurred())
899 PyErr_SetString(PyExc_ValueError, "prime generation failed");
902 static PyObject *meth_pgen(PyObject *me, PyObject *arg, PyObject *kw)
908 pgen_filterctx fc = { 2 };
910 pgev step = { 0 }, test = { 0 }, evt = { 0 };
911 unsigned nsteps = 0, ntests = 0;
912 char *kwlist[] = { "start", "name", "stepper", "tester", "event",
913 "nsteps", "ntests", 0 };
915 step.proc = pgen_filter; step.ctx = &fc;
916 test.proc = pgen_test; test.ctx = &tc;
917 if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|sO&O&O&O&O&:pgen", kwlist,
918 convmp, &x, &p, convpgev, &step,
919 convpgev, &test, convpgev, &evt,
920 convuint, &nsteps, convuint, &ntests))
922 if (!ntests) ntests = rabin_iters(mp_bits(x));
923 if ((r = pgen(p, MP_NEW, x, evt.proc, evt.ctx,
924 nsteps, step.proc, step.ctx,
925 ntests, test.proc, test.ctx)) == 0)
927 if (PyErr_Occurred()) goto end;
931 mp_drop(r); mp_drop(x);
932 droppgev(&step); droppgev(&test); droppgev(&evt);
936 static PyObject *meth_strongprime_setup(PyObject *me,
937 PyObject *arg, PyObject *kw)
941 grand *r = &rand_global;
947 char *kwlist[] = { "nbits", "name", "event", "rng", "nsteps", 0 };
949 if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|sO&O&O&", kwlist,
950 convuint, &nbits, &name,
951 convpgev, &evt, convgrand, &r,
954 if ((x = strongprime_setup(name, MP_NEW, &f, nbits,
955 r, n, evt.proc, evt.ctx)) == 0)
957 rc = Py_BuildValue("(NN)", mp_pywrap(x), pfilt_pywrap(&f));
965 static PyObject *meth_strongprime(PyObject *me, PyObject *arg, PyObject *kw)
968 grand *r = &rand_global;
974 char *kwlist[] = { "nbits", "name", "event", "rng", "nsteps", 0 };
976 if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|sO&O&O&", kwlist,
977 convuint, &nbits, &name,
978 convpgev, &evt, convgrand, &r,
981 if ((x = strongprime(name, MP_NEW, nbits,
982 r, n, evt.proc, evt.ctx)) == 0)
992 static PyObject *meth_limlee(PyObject *me, PyObject *arg, PyObject *kw)
995 pgev ie = { 0 }, oe = { 0 };
997 grand *r = &rand_global;
1000 PyObject *rc = 0, *vec;
1001 char *kwlist[] = { "pbits", "qbits", "name", "event", "ievent",
1002 "rng", "nsteps", 0 };
1005 if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|sO&O&O&O&:limlee", kwlist,
1006 convuint, &pl, convuint, &ql,
1007 &p, convpgev, &oe, convpgev, &ie,
1008 convgrand, &r, convuint, &on))
1010 if ((x = limlee(p, MP_NEW, MP_NEW, ql, pl, r, on,
1011 oe.proc, oe.ctx, ie.proc, ie.ctx, &nf, &v)) == 0)
1013 vec = PyList_New(nf);
1014 for (i = 0; i < nf; i++)
1015 PyList_SetItem(vec, i, mp_pywrap(v[i]));
1017 rc = Py_BuildValue("(NN)", mp_pywrap(x), vec);
1019 droppgev(&oe); droppgev(&ie);
1023 /*----- Global stuff ------------------------------------------------------*/
1025 static PyMethodDef methods[] = {
1026 #define METHNAME(name) meth_##name
1027 METH (_PrimeFilter_smallfactor, "smallfactor(X) -> PGRC")
1028 METH (_RabinMiller_iters, "iters(NBITS) -> NITERS")
1030 pgen(START, [name = 'p', stepper = PrimeGenStepper(2),\n\
1031 tester = PrimeGenTester(), event = pgen_nullev,\n\
1032 nsteps = 0, ntests = RabinMiller.iters(START.nbits)]) -> P")
1033 KWMETH(strongprime_setup, "\
1034 strongprime_setup(NBITS, [name = 'p', event = pgen_nullev,\n\
1035 rng = rand, nsteps = 0]) -> (START, JUMP)")
1036 KWMETH(strongprime, "\
1037 strongprime(NBITS, [name = 'p', event = pgen_nullev,\n\
1038 rng = rand, nsteps = 0]) -> P")
1040 limlee(PBITS, QBITS, [name = 'p', event = pgen_nullev,\n\
1041 ievent = pgen_nullev, rng = rand, nsteps = 0]) -> (P, [Q, ...])")
1046 void pgen_pyinit(void)
1048 INITTYPE(pfilt, root);
1049 INITTYPE(rabin, root);
1050 INITTYPE(pgevent, root);
1051 INITTYPE(pgev, root);
1052 INITTYPE(pgstep, pgev);
1053 INITTYPE(pgjump, pgev);
1054 INITTYPE(pgtest, pgev);
1055 addmethods(methods);
1058 static PyObject *obj;
1060 void pgen_pyinsert(PyObject *mod)
1062 INSERT("PrimeFilter", pfilt_pytype);
1063 INSERT("RabinMiller", rabin_pytype);
1064 INSERT("PrimeGenEvent", pgevent_pytype);
1065 INSERT("PrimeGenBuiltinHandler", pgev_pytype);
1066 INSERT("PrimeGenStepper", pgstep_pytype);
1067 INSERT("PrimeGenJumper", pgjump_pytype);
1068 INSERT("PrimeGenTester", pgtest_pytype);
1069 INSERT("pgen_nullev", obj = pgev_stdev(0));
1070 INSERT("pgen_stdev", pgev_stdev(pgen_ev));
1071 INSERT("pgen_spinev", pgev_stdev(pgen_evspin));
1072 INSERT("pgen_subev", pgev_stdev(pgen_subev));
1075 /*----- That's all, folks -------------------------------------------------*/