# Generating Prime Numbers

Problem

You want to generate a sequence of prime numbers, or find all prime numbers below a certain threshold.

Solution

Instantiate the Prime class to create a prime number generator. Call Prime#succ to get the next prime number in the sequence.

```	require 'mathn'
primes = Prime.new
primes.succ # => 2
primes.succ # => 3
```

Use Prime#each to iterate over the prime numbers:

```	primes.each { |x| puts x; break if x > 15; }
# 5
# 7
# 11
# 13
# 17
primes.succ # => 19
```

Discussion

Because prime numbers are both mathematically interesting and useful in cryptographic applications, a lot of study has been lavished on them. Many algorithms have been devised for generating prime numbers and determining whether a number is prime. The code in this recipe walks a line between efficiency and ease of implementation.

The best-known prime number algorithm is the Sieve of Eratosthenes, which finds all primes in a certain range by iterating over that range multiple times. On the first pass, it eliminates every even number greater than 2, on the second pass every third number after 3, on the third pass every fifth number after 5, and so on. This implementation of the Sieve is based on a sample program packaged with the Ruby distribution:

```	def sieve(max=100)
sieve = []
(2..max).each { |i| sieve[i] = i }
(2..Math.sqrt(max)).each do |i|
(i*i).step(max, i) { |j| sieve[j] = nil } if sieve[i]
end
sieve.compact
end

sieve(10)
# => [2, 3, 5, 7]
sieve(100000).size
# => 9592
```

The Sieve is a fast way to find the primes smaller than a certain number, but it's memory-inefficient and it's not suitable for generating an infinite sequence of prime numbers. It's also not very compatible with the Ruby idiom of generator methods. This is where the Prime class comes in.

A Prime object stores the current state of one iteration over the set of primes. It contains all information necessary to calculate the next prime number in the sequence. Prime#each repeatedly calls Prime#succ and yields it up to whatever code block was passed in.

Ruby 1.9 has an efficient implementation of Prime#each, but Ruby 1.8 has a very slow implementation. The following code is based on the 1.9 implementation, and it illustrates many of the simple tricks that drastically speed up algorithms that find or use primes. You can use this code, or just paste the code from Ruby 1.9's mathn.rb into your 1.8 program.

The first trick is to share a single list of primes between all Prime objects by making it a class variable. This makes it much faster to iterate over multiple Prime instances, but it also uses more memory because the list of primes will never be garbage-collected.

We initialize the list with the first few prime numbers. This helps early performance a little bit, but it's mainly to get rid of edge cases. The class variable @@check_next tracks the next number we think might be prime.

```	require 'mathn'

class Prime
@@primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,
61, 67, 71, 73, 79, 83, 89, 97, 101]
@@check_next = 103
end
```

A number is prime if it has no factors: more precisely, if it has no prime factors between 2 and its square root. This code uses the list of prime numbers not only as a cache, but as a data structure to help find larger prime numbers. Instead of checking all the possible factors of a number, we only need to check some of the prime factors.

To avoid calculating square roots, we have @@limit track the largest prime number less than the square root of @@check_next. We can decide when to increment it by calculating squares instead of square roots:

```	class Prime
# @@primes < sqrt(@@check_next) < @@primes
@@limit = 3

# sqrt(121) == @@primes
@@increment_limit_at = 121
end
```

Now we need a new implementation of Prime#succ. Starting from @@check_next, the new implementation iterates over numbers until it finds one that's prime, then returns the prime number. But it doesn't iterate over the numbers one at a time: we can do better than that. It skips even numbers and numbers divisible by three, which are obviously not prime.

```	class Prime
def succ
@index += 1
while @index >= @@primes.length
if @@check_next + 4 > @@increment_limit_at
@@limit += 1
@@increment_limit_at = @@primes[@@limit + 1] ** 2
end
@@check_next += 4
@@check_next += 2
end
return @@primes[@index]
end
end
```

How does it do this? Well, consider a more formal definition of "even" and "divisible by three." If x is congruent to 2 or 4, mod 6 (that is, if x % 6 is 2 or 4), then x is even and not prime. If x is congruent to 3, mod 6, then x is divisible by 3 and not prime. If x is congruent to 1 or 5, mod 6, then x might be prime.

Our starting point is @@check_next, which starts out at 103. 103 is congruent to 1, mod 6, so it might be prime. Adding 4 gives us 107, a number congruent to 5, mod 6. We skipped two even numbers (104 and 106) and a number divisible by 3 (105). Adding 2 to 107 skips another even number and gives us 109. Like 103, 109 is congruent to 1, mod 6. We can add 4 and 2 again to get two more numbers that might be prime. By continually adding 4 and then 2 to @@check_next, we can skip over the numbers that are obviously not prime.

Although all Prime objects share a list of primes, each object should start yielding primes from the beginning of the list:

```	class Prime
def initialize
@index = -1
end
end
```

Finally, here's the method that actually checks @@check_next for primality, by looking for a prime factor of that number between 5 and @@limit. We don't have to check 2 and 3 because succ skips numbers divisible by 2 and 3. If no prime factor is found, the number is prime: we add it to the class-wide list of primes, where it can be returned by succ or yielded to a code block by each.

```	class Prime
private
factor = @@primes[2..@@limit].find { |prime| @@check_next % prime == 0 }
@@primes << @@check_next unless factor
end
end
end
```

Here's the new Prime class in action, finding the ten-thousandth prime:

```	primes = Prime.new
p = nil
10000.times { p = primes.succ }
p # => 104729
```

Checking primality

The simplest way to check whether a particular number is prime is to generate all the primes up to that number and see whether the number itself is generated as a prime.

```	class Prime
def prime?(n)
succ( ) while @seed < n
return @primes.member?(n)
end
end
```

If all of this is too complicated for you, there's a very simple constant-time probabilistic test for primality that works more than half the time:

```	def probably_prime?(x)
x < 8
end

probably_prime? 2 # => true
probably_prime? 5 # => true

probably_
prime? 6 # => true
probably_
prime? 7 # => true
probably_
prime? 8 # => false
probably_
prime? 100000 # => false
```

• Recipe 2.15, "Generating a Sequence of Numbers"
• K. Kodama has written a number of simple and advanced primality tests in Ruby (http://www.math.kobe-u.ac.jp/~kodama/tips-prime.html) Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399 