Algorithm
The algorithm used by your prime generator code is called "Sieve of Eratosthenes". In general, it creates a list of numbers, and iterates over the list. All multiplications of the current number are removed from the list, and the remaining numbers are prime.
For example, let us consider [2,3,4,5,6,7,8,9,10,11,12,13,14,15]
. We encounter 2, so we remove all even numbers from the list:
[2,3,5,7,9,11,13,15]
Same for 3:
[2,3,5,7,11,13]
5
, 7
, 11
and 13
have no multiplications in the list, so we remove nothing and remain with a list of primes.
Visual example
In this example (courtesy of Wikipedia), all multiplications of 2, 3 and 5 were removed from the list - multiplications of 2 were painted pink, multiplication of 3 were painted in green, and multiplications of 5 in dark blue. 7 will be iterated next, so it's highlighted. The dark colored numbers are prime, the light colored numbers are not prime, and the gray numbers have net yet been reached.
Optimizations in your code
As mentioned by @BenJackson, your code is optimized twice:
- Firstly, it only stores odd numbers only starting from 3, because we know that even numbers are not prime (except 2).
- Secondly, for the number p, it only starts to sieve from p². This is correct because if
n<p
thenn*p
was already sieved when multiplications ofn
were sieved.
This is the reason why the cryptic comment:
// sieving from p^2, whose index is 2i^2 + 6i + 3
Suppose that our algorithm has reached the second item in the vector, therefore i=2
. The number in question is 5, because the index i
denotes the number 2i+3
(first optimization).
We should sieve all multiplications of 5
from 25
onwards. The index that represents 25
is 11
, because 25=2*11+3
. Following your printouts, it removes indices 11, 16, 21, 26, ...
, which correspond to the numbers 25, 35, 45, 55, ..
- all odd multiplications of 5 we'd like to remove.
You can read more about it at Wikipedia or Wolfram MathWorld, and there's a nice javascript on-line demonstration here.