void prime_iterator_global_startup(void)
{
  primary_sieve = sieve_erat30(primary_limit);
#ifdef NSMALL_PRIMES
  {
    UV p;
    uint32_t *primes32;
    UV *primes64 = sieve_to_n(NSMALL_PRIMES + 180, &num_small_primes);
    New(0, primes32, num_small_primes, uint32_t);
    for (p = 0; p < num_small_primes; p++)  primes32[p] = primes64[p];
    Safefree(primes64);
    small_primes = primes32;
  }
#endif
}
void prime_iterator_global_startup(void)
{
  primary_sieve = sieve_erat30(primary_limit);
}
static int sieve_segment(unsigned char* mem, UV startd, UV endd,
                         const unsigned char* prim_sieve, UV prim_limit)
{
  const unsigned char* sieve;
  UV limit, p;
  UV startp = 30*startd;
  UV endp = (endd >= (UV_MAX/30))  ?  UV_MAX-2  :  30*endd+29;

  MPUassert( (mem != 0) && (endd >= startd) && (endp >= startp),
             "sieve_segment bad arguments");

  /* Fill buffer with marked 7, 11, and 13 */
  sieve_prefill(mem, startd, endd);

  limit = sqrt((double) endp);
  if (limit*limit < endp) limit++;  /* ceil(sqrt(endp)) */
  /* printf("segment sieve from %"UVuf" to %"UVuf" (aux sieve to %"UVuf")\n", startp, endp, limit); */
  if ( (prim_sieve != 0) && (prim_limit <= limit) ) {
    sieve = prim_sieve;
  } else {
    sieve = sieve_erat30(limit);
  }
  MPUassert( sieve != 0, "Could not generate base sieve" );

  for (p = 17; p <= prim_limit; p = next_prime_in_sieve(sieve,p))
  {
    /* p increments from 17 to at least sqrt(endp) */
    UV p2 = p*p;   /* TODO: overflow */
    if (p2 > endp)  break;
    /* Find first multiple of p greater than p*p and larger than startp */
    if (p2 < startp) {
      p2 = (startp / p) * p;
      if (p2 < startp)  p2 += p;
    }
    /* Bump to next multiple that isn't divisible by 2, 3, or 5 */
    while (masktab30[p2%30] == 0) { p2 += p; }
    /* It is possible we've overflowed p2, so check for that */
    if ( (p2 <= endp) && (p2 >= startp) ) {
      /* Sieve from startd to endd starting at p2, stepping p */
      UV d = (p2)/30;
      UV m = (p2) - d*30;
      UV dinc = (2*p)/30;
      UV minc = (2*p) - dinc*30;
      UV wdinc[8];
      unsigned char wmask[8];
      UV offset_endd = endd - startd;

      /* Find the positions of the next composites we will mark */
      FIND_COMPOSITE_POSITIONS(p);
      d -= startd;
      /* Mark composites (unrolled) */
      while ( (d+p) <= offset_endd ) {
        mem[d] |= wmask[0];  d += wdinc[0];
        mem[d] |= wmask[1];  d += wdinc[1];
        mem[d] |= wmask[2];  d += wdinc[2];
        mem[d] |= wmask[3];  d += wdinc[3];
        mem[d] |= wmask[4];  d += wdinc[4];
        mem[d] |= wmask[5];  d += wdinc[5];
        mem[d] |= wmask[6];  d += wdinc[6];
        mem[d] |= wmask[7];  d += wdinc[7];
      }
      while (1) {
        mem[d] |= wmask[0];  d += wdinc[0];  if (d > offset_endd) break;
        mem[d] |= wmask[1];  d += wdinc[1];  if (d > offset_endd) break;
        mem[d] |= wmask[2];  d += wdinc[2];  if (d > offset_endd) break;
        mem[d] |= wmask[3];  d += wdinc[3];  if (d > offset_endd) break;
        mem[d] |= wmask[4];  d += wdinc[4];  if (d > offset_endd) break;
        mem[d] |= wmask[5];  d += wdinc[5];  if (d > offset_endd) break;
        mem[d] |= wmask[6];  d += wdinc[6];  if (d > offset_endd) break;
        mem[d] |= wmask[7];  d += wdinc[7];  if (d > offset_endd) break;
      }
    }
  }

  if (sieve != prim_sieve)  Safefree(sieve);
  return 1;
}