Some time ago I used the (blazing fast) primesieve in python that I found here: Fastest way to list all primes below N
To be precise, this implementation:
I'll try to explain as much as I can. The sieve
array has an unusual indexing scheme; it stores a bit for each number that is congruent to 1 or 5 mod 6. Thus, a number 6*k + 1
will be stored in position 2*k
and k*6 + 5
will be stored in position 2*k + 1
. The 3*i+1|1
operation is the inverse of that: it takes numbers of the form 2*n
and converts them into 6*n + 1
, and takes 2*n + 1
and converts it into 6*n + 5
(the +1|1
thing converts 0
to 1
and 3
to 5
). The main loop iterates k
through all numbers with that property, starting with 5
(when i
is 1); i
is the corresponding index into sieve
for the number k
. The first slice update to sieve
then clears all bits in the sieve with indexes of the form k*k/3 + 2*m*k
(for m
a natural number); the corresponding numbers for those indexes start at k^2
and increase by 6*k
at each step. The second slice update starts at index k*(k-2*(i&1)+4)/3
(number k * (k+4)
for k
congruent to 1
mod 6
and k * (k+2)
otherwise) and similarly increases the number by 6*k
at each step.
Here's another attempt at an explanation: let candidates
be the set of all numbers that are at least 5 and are congruent to either 1
or 5
mod 6
. If you multiply two elements in that set, you get another element in the set. Let succ(k)
for some k
in candidates
be the next element (in numerical order) in candidates
that is larger than k
. In that case, the inner loop of the sieve is basically (using normal indexing for sieve
):
for k in candidates:
for (l = k; ; l += 6) sieve[k * l] = False
for (l = succ(k); ; l += 6) sieve[k * l] = False
Because of the limitations on which elements are stored in sieve
, that is the same as:
for k in candidates:
for l in candidates where l >= k:
sieve[k * l] = False
which will remove all multiples of k
in candidates
(other than k
itself) from the sieve at some point (either when the current k
was used as l
earlier or when it is used as k
now).
As an aside, you can "approximate" prime numbers. Call the approximate prime P. Here are a few formulas:
P = 2*k+1 // not divisible by 2
P = 6*k + {1, 5} // not divisible 2, 3
P = 30*k + {1, 7, 11, 13, 17, 19, 23, 29} // not divisble by 2, 3, 5
The properties of the set of numbers found by these formulas is that P may not be prime, however all primes are in the set P. I.e. if you only test numbers in the set P for prime, you won't miss any.
You can reformulate these formulas to:
P = X*k + {-i, -j, -k, k, j, i}
if that is more convenient for you.
Here is some code that uses this technique with a formula for P not divisible by 2, 3, 5, 7.
This link may represent the extent to which this technique can be practically leveraged.
Piggy-Backing onto Howard Hinnant's response, Howard, you don't have to test numbers in the set of all natural numbers not divisible by 2, 3 or 5 for primality, per se. You need simply multiply each number in the array (except 1, which self-eliminates) times itself and every subsequent number in the array. These overlapping products will give you all the non-primes in the array up to whatever point you extend the deterministic-multiplicative process. Thus the first non-prime in the array will be 7 squared, or 49. The 2nd, 7 times 11, or 77, etc. A full explanation here: http://www.primesdemystified.com