- for (i = 0; i < NPRIME; i++) {
- p->r[i] = p->r[i] + j->r[i];
- if (p->r[i] > ptab[i])
- p->r[i] -= ptab[i];
- if (!p->r[i] && rc == PGEN_MAYBE) {
- if (MP_LEN(p->m) == 1 && p->m->v[0] == ptab[i])
- rc = PGEN_PRIME;
- else
- rc = PGEN_COMPOSITE;
+ if (event && event(PGEN_BEGIN, &ev, ectx) == PGEN_ABORT)
+ return (0);
+
+ /* --- Set up for the initial call --- */
+
+ proc = step; ctx = sctx; rq = PGEN_BEGIN;
+
+ /* --- Enter the great maelstrom of state transitions --- */
+
+ for (;;) {
+ unsigned act = 0;
+
+ enum {
+ A_STEP = 1u,
+ A_TEST = 2u,
+ A_EVENT = 4u,
+ A_ENDTEST = 8u,
+ A_ENDSTEP = 16u,
+ A_DONE = 32u
+ };
+
+ /* --- Call the procedure and decide what to do next --- */
+
+ rc = proc(rq, &ev, ctx);
+ switch (rc) {
+ case PGEN_TRY:
+ if (proc == test)
+ rq = PGEN_TRY;
+ else {
+ act |= A_EVENT;
+ proc = test; ctx = tctx;
+ rq = PGEN_BEGIN;
+ }
+ break;
+ case PGEN_PASS:
+ act |= A_TEST | A_EVENT;
+ if (proc == test)
+ rq = PGEN_TRY;
+ else {
+ proc = test; ctx = tctx;
+ rq = PGEN_BEGIN;
+ }
+ break;
+ case PGEN_FAIL:
+ act |= A_STEP;
+ if (proc == test) {
+ act |= A_ENDTEST | A_EVENT;
+ proc = step; ctx = sctx;
+ }
+ rq = PGEN_TRY;
+ break;
+ case PGEN_DONE:
+ act |= A_EVENT | A_DONE | A_ENDSTEP;
+ if (proc == test)
+ act |= A_ENDTEST;
+ break;
+ case PGEN_ABORT:
+ act |= A_EVENT | A_DONE;
+ if (proc == test || rq == PGEN_TRY)
+ act |= A_ENDSTEP;
+ if (proc == test && rq == PGEN_BEGIN)
+ act |= A_ENDTEST;
+ break;
+ default:
+ assert(((void)"Invalid response from function", 0));
+ break;
+ }
+
+ /* --- If decrementing counters is requested, do that --- */
+
+ if ((act & A_STEP) && steps) {
+ ev.steps--;
+ if (!ev.steps) {
+ act |= A_EVENT | A_ENDSTEP | A_DONE;
+ rc = PGEN_ABORT;
+ }
+ ev.tests = tests;
+ }
+
+ if ((act & A_TEST) && tests) {
+ ev.tests--;
+ if (!ev.tests) {
+ act |= A_ENDTEST | A_ENDSTEP | A_DONE;
+ rc = PGEN_DONE;
+ }