progs/perftest.c: Use from Glibc syscall numbers.
[catacomb] / math / limlee.c
index b20965a..c99ba7b 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->d.buf, p, p, l->iev, l->iec, 0, pgen_filter, &pf,
+  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;
 }
 
@@ -146,18 +143,12 @@ static const limlee_primeops primeops_simple = { llgen, llfree };
 static int init(pgen_event *ev, limlee_stepctx *l)
 {
   size_t i;
-  unsigned qql;
 
   /* --- First of all, decide on a number of factors to make --- */
 
   l->nf = l->pl / l->ql;
-  qql = l->pl % l->ql;
-  if (!l->nf)
-    return (PGEN_ABORT);
-  else if (qql && l->nf > 1) {
-    l->nf--;
-    qql += l->ql;
-  }
+  if (l->nf < 2) return (PGEN_ABORT);
+  l->nf--;
 
   /* --- Now decide on how many primes I'll actually generate --- *
    *
@@ -180,20 +171,14 @@ static int init(pgen_event *ev, limlee_stepctx *l)
   /* --- Other bits of initialization --- */
 
   l->seq = 0;
-  dstr_create(&l->d);
   if (!l->pops) {
     l->pops = &primeops_simple;
     l->pc = 0;
   }
 
-  /* --- Find a big prime --- */
+  /* --- Find a big prime later --- */
 
-  if (!qql)
-    l->qq.p = 0;
-  else {
-    dstr_putf(&l->d, "%s*", ev->name);
-    l->pops->pgen(&l->qq, qql, l);
-  }
+  l->qq.p = 0;
 
   return (PGEN_TRY);
 }
@@ -211,8 +196,11 @@ static int init(pgen_event *ev, limlee_stepctx *l)
 
 static int next(int rq, pgen_event *ev, limlee_stepctx *l)
 {
-  mp *p;
+  dstr d = DSTR_INIT;
+  mp *p = 0;
   int rc;
+  int dist;
+  unsigned nb;
 
   mp_drop(ev->m);
 
@@ -230,32 +218,68 @@ static int next(int rq, pgen_event *ev, limlee_stepctx *l)
     }
     rq = PGEN_TRY; /* For next time through */
 
+    /* --- If the large factor is performing badly, make a new one --- */
+
+    if (l->qq.p) {
+      dist = l->u.s.disp < 0 ? -l->u.s.disp : l->u.s.disp;
+      if (dist && dist > l->u.s.steps/3) {
+       l->pops->pfree(&l->qq, l);
+       l->qq.p = 0;
+      }
+    }
+
     /* --- Gather up some factors --- */
 
-    if (l->qq.p)
-      mpmul_add(&mm, l->qq.p);
+    if (l->qq.p) mpmul_add(&mm, l->qq.p);
     for (i = 0; i < l->poolsz; i++) {
       if (!l->c[i])
        continue;
       if (!l->v[i].p) {
-       DRESET(&l->d);
-       dstr_putf(&l->d, "%s_%lu", ev->name, l->seq++);
+       DRESET(&d);
+       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);
     }
 
-    /* --- Check it for small factors --- */
+    /* --- Check on the large factor --- */
 
     p = mpmul_done(&mm);
+    if (!l->qq.p) {
+      DRESET(&d);
+      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);
+    }
     p = mp_lsl(p, p, 1);
     p->v[0] |= 1;
+
+    nb = mp_bits(p);
+    l->u.s.steps++;
+    if (nb < l->pl) {
+      l->u.s.disp--;
+      continue;
+    } else if (nb > l->pl) {
+      l->u.s.disp++;
+      continue;
+    }
+
+    /* --- Check it for small factors --- */
+
     if ((rc = pfilt_smallfactor(p)) != PGEN_FAIL)
       break;
-    mp_drop(p);
+    MP_DROP(p); p = 0;
   }
 
+end:
   ev->m = p;
+  DDESTROY(&d);
   return (rc);
 }
 
@@ -305,7 +329,6 @@ static int done(pgen_event *ev, limlee_stepctx *l)
   /* --- Free other resources --- */
 
   xfree(l->c);
-  dstr_destroy(&l->d);
 
   /* --- Done --- */
 
@@ -367,6 +390,8 @@ mp *limlee(const char *name, mp *d, mp *newp,
 {
   limlee_stepctx l;
   rabin rr;
+  mp **v;
+  size_t i;
 
   l.f = 0; if (f) l.f |= LIMLEE_KEEPFACTORS;
   l.newp = newp;
@@ -379,15 +404,18 @@ mp *limlee(const char *name, mp *d, mp *newp,
   d = pgen(name, d, 0, oev, oec, on, limlee_step, &l,
           rabin_iters(pl), pgen_test, &rr);
 
-  if (d && f) {
-    mp **v;
-    size_t i;
-    v = xmalloc(l.nf * sizeof(mp *));
-    for (i = 0; i < l.nf; i++)
-      v[i] = l.v[i].p;
-    xfree(l.v);
-    *f = v;
-    *nf = l.nf;
+  if (f) {
+    if (!d) {
+      for (i = 0; i < l.nf; i++)
+       if (l.v[i].p) llfree(&l.v[i], &l);
+    } else {
+      v = xmalloc(l.nf * sizeof(mp *));
+      for (i = 0; i < l.nf; i++)
+       v[i] = l.v[i].p;
+      xfree(l.v);
+      *f = v;
+      *nf = l.nf;
+    }
   }
 
   return (d);