- /* --- Gallivant through the residue table --- */
-
- for (i = 0; i < NPRIME; i++) {
- p->r[i] = (q->r[i] * m + a) % 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;
+ /* --- Set up for the initial call --- */
+
+ proc = step; ctx = sctx; p = P_STEP; rq = PGEN_BEGIN;
+
+ /* --- Enter the great maelstrom of state transitions --- */
+
+ for (;;) {
+ unsigned act = 0;
+
+#define A_STEP 1u
+#define A_TEST 2u
+#define A_EVENT 4u
+#define A_ENDTEST 8u
+#define A_ENDSTEP 16u
+#define A_DONE 32u
+
+ /* --- Call the procedure and decide what to do next --- */
+
+ rc = proc(rq, &ev, ctx);
+ switch (rc) {
+ case PGEN_TRY:
+ if (p == P_TEST)
+ rq = PGEN_TRY;
+ else {
+ act |= A_EVENT;
+ proc = test; ctx = tctx; p = P_TEST;
+ rq = PGEN_BEGIN;
+ }
+ break;
+ case PGEN_PASS:
+ act |= A_TEST | A_EVENT;
+ if (p == P_TEST)
+ rq = PGEN_TRY;
+ else {
+ proc = test; ctx = tctx; p = P_TEST;
+ rq = PGEN_BEGIN;
+ }
+ break;
+ case PGEN_FAIL:
+ act |= A_STEP;
+ if (p == P_TEST) {
+ act |= A_ENDTEST | A_EVENT;
+ proc = step; ctx = sctx; p = P_STEP;
+ }
+ rq = PGEN_TRY;
+ break;
+ case PGEN_DONE:
+ act |= A_EVENT | A_DONE | A_ENDSTEP;
+ if (p == P_TEST)
+ act |= A_ENDTEST;
+ break;
+ case PGEN_ABORT:
+ act |= A_EVENT | A_DONE;
+ if (p == P_TEST || rq == PGEN_TRY)
+ act |= A_ENDSTEP;
+ if (p == P_TEST && rq != PGEN_BEGIN)
+ act |= A_ENDTEST;
+ break;
+ default:
+ assert(((void)"Invalid response from function", 0));
+ break;