math/limlee.c: Handle an abort from `pgen' correctly.
authorMark Wooding <mdw@distorted.org.uk>
Thu, 14 Nov 2019 19:53:27 +0000 (19:53 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Mon, 16 Dec 2019 16:25:29 +0000 (16:25 +0000)
The `llgen' function just tries again if `pgen' reports an abort.  This
is entirely contrary to the intend of the `PGEN_ABORT' protocol, so I've
no idea why I thought this was a good idea.

Instead, leave the prime slot null (because adding a return code to the
`pgen' callback breaks the API), and arrange for the caller to notice
and clean up.  This is annoyingly because there may be an `mpmul' in
progress.

math/limlee.c

index fbed738..28975d0 100644 (file)
@@ -114,13 +114,10 @@ static void llgen(limlee_factor *f, unsigned pl, limlee_stepctx *l)
   rabin r;
   mp *p;
 
-again:
   p = mprand(l->newp, pl, l->r, 1);
   pf.step = 2;
   p = pgen(l->u.s.name, p, p, l->iev, l->iec, 0, pgen_filter, &pf,
           rabin_iters(pl), pgen_test, &r);
-  if (!p)
-    goto again;
   f->p = p;
 }
 
@@ -200,7 +197,7 @@ static int init(pgen_event *ev, limlee_stepctx *l)
 static int next(int rq, pgen_event *ev, limlee_stepctx *l)
 {
   dstr d = DSTR_INIT;
-  mp *p;
+  mp *p = 0;
   int rc;
   int dist;
   unsigned nb;
@@ -242,6 +239,8 @@ static int next(int rq, pgen_event *ev, limlee_stepctx *l)
        dstr_putf(&d, "%s_%lu", ev->name, l->seq++);
        l->u.s.name = d.buf;
        l->pops->pgen(&l->v[i], l->ql, l);
+       if (!l->v[i].p)
+         { mp_drop(mpmul_done(&mm)); rc = PGEN_ABORT; goto end; }
       }
       mpmul_add(&mm, l->v[i].p);
     }
@@ -254,6 +253,7 @@ static int next(int rq, pgen_event *ev, limlee_stepctx *l)
       dstr_putf(&d, "%s*_%lu", ev->name, l->seq++);
       l->u.s.name = d.buf;
       l->pops->pgen(&l->qq, l->pl - mp_bits(p), l);
+      if (!l->qq.p) { MP_DROP(p); p = 0; rc = PGEN_ABORT; break; }
       l->u.s.steps = l->u.s.disp = 0;
       p = mp_mul(p, p, l->qq.p);
     }
@@ -274,9 +274,10 @@ static int next(int rq, pgen_event *ev, limlee_stepctx *l)
 
     if ((rc = pfilt_smallfactor(p)) != PGEN_FAIL)
       break;
-    mp_drop(p);
+    MP_DROP(p); p = 0;
   }
 
+end:
   ev->m = p;
   DDESTROY(&d);
   return (rc);