Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Segmented Sieve of Eratosthenes?

It's easy enough to make a simple sieve:

for (int i=2; i<=N; i++){     if (sieve[i]==0){         cout << i << " is prime" << endl;         for (int j = i; j<=N; j+=i){             sieve[j]=1;         }     }     cout << i << " has " << sieve[i] << " distinct prime factors\n"; } 

But what about when N is very large and I can't hold that kind of array in memory? I've looked up segmented sieve approaches and they seem to involve finding primes up until sqrt(N) but I don't understand how it works. What if N is very large (say 10^18)?

like image 439
John Smith Avatar asked Apr 20 '12 15:04

John Smith


People also ask

What is a segmented Sieve?

Segmented Sieve first uses Simple Sieve to find primes smaller than or equal to √(n). The idea of this algorithm is to divide the range [0 ... n-1] in different segments and compute primes in all segments one by one.

How is segmented Sieve better than simple sieves?

We also analysed the space and time complexity and found out that both the segmented sieve and the simple sieve algorithms have the same time complexity, but the segmented sieve algorithm takes less space and hence it is used over simple sieve when the value of N is large.

What is the Sieve of Eratosthenes used for?

Sieve of Eratosthenes is a method to find the prime numbers and composite numbers among a group of numbers. This method was introduced by Greek Mathematician Eratosthenes in the third century B.C.

What is the time complexity of segmented Sieve?

To solve such a problem, we can use the idea of the Segmented sieve. We pre-generate all prime numbers up to , and use those primes to mark all composite numbers in the segment . Time complexity of this approach is O ( ( R − L + 1 ) log ⁡ ⁡ ( R ) + R log ⁡ ⁡ .


1 Answers

The basic idea of a segmented sieve is to choose the sieving primes less than the square root of n, choose a reasonably large segment size that nevertheless fits in memory, and then sieve each of the segments in turn, starting with the smallest. At the first segment, the smallest multiple of each sieving prime that is within the segment is calculated, then multiples of the sieving prime are marked as composite in the normal way; when all the sieving primes have been used, the remaining unmarked numbers in the segment are prime. Then, for the next segment, for each sieving prime you already know the first multiple in the current segment (it was the multiple that ended the sieving for that prime in the prior segment), so you sieve on each sieving prime, and so on until you are finished.

The size of n doesn't matter, except that a larger n will take longer to sieve than a smaller n; the size that matters is the size of the segment, which should be as large as convenient (say, the size of the primary memory cache on the machine).

You can see a simple implementation of a segmented sieve here. Note that a segmented sieve will be very much faster than O'Neill's priority-queue sieve mentioned in another answer; if you're interested, there's an implementation here.

EDIT: I wrote this for a different purpose, but I'll show it here because it might be useful:

Though the Sieve of Eratosthenes is very fast, it requires O(n) space. That can be reduced to O(sqrt(n)) for the sieving primes plus O(1) for the bitarray by performing the sieving in successive segments. At the first segment, the smallest multiple of each sieving prime that is within the segment is calculated, then multiples of the sieving prime are marked composite in the normal way; when all the sieving primes have been used, the remaining unmarked numbers in the segment are prime. Then, for the next segment, the smallest multiple of each sieving prime is the multiple that ended the sieving in the prior segment, and so the sieving continues until finished.

Consider the example of sieve from 100 to 200 in segments of 20. The five sieving primes are 3, 5, 7, 11 and 13. In the first segment from 100 to 120, the bitarray has ten slots, with slot 0 corresponding to 101, slot k corresponding to 100+2k+1, and slot 9 corresponding to 119. The smallest multiple of 3 in the segment is 105, corresponding to slot 2; slots 2+3=5 and 5+3=8 are also multiples of 3. The smallest multiple of 5 is 105 at slot 2, and slot 2+5=7 is also a multiple of 5. The smallest multiple of 7 is 105 at slot 2, and slot 2+7=9 is also a multiple of 7. And so on.

Function primesRange takes arguments lo, hi and delta; lo and hi must be even, with lo < hi, and lo must be greater than sqrt(hi). The segment size is twice delta. Ps is a linked list containing the sieving primes less than sqrt(hi), with 2 removed since even numbers are ignored. Qs is a linked list containing the offest into the sieve bitarray of the smallest multiple in the current segment of the corresponding sieving prime. After each segment, lo advances by twice delta, so the number corresponding to an index i of the sieve bitarray is lo + 2i + 1.

function primesRange(lo, hi, delta)     function qInit(p)         return (-1/2 * (lo + p + 1)) % p     function qReset(p, q)         return (q - delta) % p     sieve := makeArray(0..delta-1)     ps := tail(primes(sqrt(hi)))     qs := map(qInit, ps)     while lo < hi         for i from 0 to delta-1             sieve[i] := True         for p,q in ps,qs             for i from q to delta step p                 sieve[i] := False         qs := map(qReset, ps, qs)         for i,t from 0,lo+1 to delta-1,hi step 1,2             if sieve[i]                 output t         lo := lo + 2 * delta 

When called as primesRange(100, 200, 10), the sieving primes ps are [3, 5, 7, 11, 13]; qs is initially [2, 2, 2, 10, 8] corresponding to smallest multiples 105, 105, 105, 121 and 117, and is reset for the second segment to [1, 2, 6, 0, 11] corresponding to smallest multiples 123, 125, 133, 121 and 143.

You can see this program in action at http://ideone.com/iHYr1f. And in addition to the links shown above, if you are interested in programming with prime numbers I modestly recommend this essay at my blog.

like image 74
user448810 Avatar answered Oct 13 '22 20:10

user448810