Sieve of Eratosthenes: Difference between revisions

From Rosetta Code
Content added Content deleted
Line 484: Line 484:


As Melissa O'Neill demonstrates in [http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf The Genuine Sieve of Eratosthenes], this version is not better than trial division. She also presents an actual purely functional version that uses priority queues, and is much easier to combine with [http://http://en.wikipedia.org/wiki/Wheel_factorization wheels] (pre-calculated sieves for small primes) than the imperative version. Even combined with a simple wheel, the speed of this version is similar to the imperative version.
As Melissa O'Neill demonstrates in [http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf The Genuine Sieve of Eratosthenes], this version is not better than trial division. She also presents an actual purely functional version that uses priority queues, and is much easier to combine with [http://http://en.wikipedia.org/wiki/Wheel_factorization wheels] (pre-calculated sieves for small primes) than the imperative version. Even combined with a simple wheel, the speed of this version is similar to the imperative version.

=={{header|Icon}}==
[http://www.tools-of-computing.com/tc/CS/iconprog.pdf Icon HandBook]
procedure main()
sieve(100)
end
procedure sieve(n)
local p,i,j
p:=repl("1",n)
every i:=2 to sqrt(n) do
if p[i] == "1" then
every j:= i+i to n by i do p[j]:="0"
every i:=2 to n do if p[i]=="1" then write(i)
end


=={{header|J}}==
=={{header|J}}==

Revision as of 11:23, 9 December 2008

Task
Sieve of Eratosthenes
You are encouraged to solve this task according to the task description, using any language you may know.
This task has been clarified. Its programming examples are in need of review to ensure that they still fit the requirements of the task.

The Sieve of Eratosthenes is a simple algorithm that finds the prime numbers up to a given integer. Implement this algorithm, with the only allowed optimization that the outer loop can stop at the square root of the limit, and the inner loop may start at the square of the prime just found. That means especially that you shouldn't optimize by using pre-computed wheels, i.e. assume you need only to cross out odd numbers (wheel based on 2), numbers equal to 1 or 5 modulo 6 (wheel based on 2 and 3), or similar wheels based on low primes.

If there's an easy way to add such a wheel based optimization, implement this as an alternative version.

Ada

This example may be incorrect due to a recent change in the task requirements or a lack of testing. Please verify it and remove this message. If the example does not match the requirements or does not work, replace this message with Template:incorrect or fix the code yourself.

[[Category:{{{1}}} examples needing attention]]Property "Example requires attention" (as page type) with input value "{{{1}}}" contains invalid characters or is incomplete and therefore can cause unexpected results during a query or annotation process.

This solution uses an array of bits representing boolean values to identify the prime numbers. The limit on the outer loop is set to the square root of the number received from the command line. This limit minimizes the number of unneeded iterations in the algorithm.

The lowest index of the array of boolean is set to 2 so that all calculations begin at 2.

<ada>with Ada.Text_Io; use Ada.Text_Io; with Ada.Command_Line; use Ada.Command_Line; with Ada.Numerics.Elementary_Functions; use Ada.Numerics.Elementary_Functions;

procedure Sieve is

  package Nat_Io is new Ada.Text_Io.Integer_Io(Natural);
  use Nat_Io;
  type Bool_Array is array(Positive range <>) of Boolean;
  pragma pack (Bool_Array);
  procedure Get_Sieve (A : out Bool_Array) is     
     Test_Num : Positive;  
     Limit : Positive := Positive(sqrt(float(A'Last)));
  begin
     A := (Others => True); -- set all values to true 
     for Num in A'First..Limit loop
        if A(Num) then
           Test_Num := Num * Num;
           while Test_Num <= A'Last loop
              A(Test_Num) := False;
              Test_Num := Test_Num + Num;
           end loop;
        end if;
     end loop;
  end Get_Sieve;
  pragma Inline(Get_Sieve);
  
  N : Positive := 2;  

begin

  if Argument_Count > 0 then
     N := Positive'Value(Argument(1));
  end if;
  declare
     Vals : Bool_Array(2..N);
  begin
     Get_Sieve(Vals);
     for I in Vals'range loop
        if Vals(I) then
           Put_Line(Positive'Image(I));
        end if;
     end loop;
  end;

end Sieve;</ada>

This version uses tasking to try to improve the performance on multiprocessor systems which are becoming common. It is still an implementation of the Sieve of Eratosthenes: the list of numbers is in the main task, and the list of primes is in the list of Siever tasks.

<ada>with Ada.Command_Line; with Ada.Text_IO;

procedure Sieve is

  task type Siever is
     entry Check (Value : in Positive);
     entry Print;
  end Siever;
  subtype Siever_Task is Siever;
  type Sieve_Ptr is access Siever;
  task body Siever is
     Number    : Positive;
     Candidate : Positive;
     Next      : Sieve_Ptr;
  begin -- Siever
     accept Check (Value : in Positive) do
        Number := Value;
     end Check;
     All_Values : loop
        select
           accept Check (Value : in Positive) do
              Candidate := Value;
           end Check;
           if Candidate rem Number /= 0 then
              if Next = null then
                 Next := new Siever_Task;
              end if;
              Next.Check (Value => Candidate);
           end if;
        or
           accept Print do
              Ada.Text_IO.Put (Item => Integer'Image (Number) );
              if Next /= null then
                 Next.Print;
              end if;
           end Print;
           exit All_Values;
        end select;
     end loop All_Values;
  end Siever;
  Head : Sieve_Ptr := new Siever;
  Max  : Positive  := 20;

begin -- Sieve

  if Ada.Command_Line.Argument_Count > 0 then
     Max := Integer'Value (Ada.Command_Line.Argument (1) );
  end if;
  All_Values : for I in 2 .. Max loop
     Head.Check (Value => I);
  end loop All_Values;
  Head.Print;

end Sieve;</ada>

This version is the same as the previous version, but with a wheel of 2.

<ada>with Ada.Command_Line; with Ada.Text_IO;

procedure Sieve_With_Wheel is

  task type Siever is
     entry Check (Value : in Positive);
     entry Print;
  end Siever;
  subtype Siever_Task is Siever;
  type Sieve_Ptr is access Siever;
  task body Siever is
     Number    : Positive;
     Candidate : Positive;
     Next      : Sieve_Ptr;
  begin -- Siever
     accept Check (Value : in Positive) do
        Number := Value;
     end Check;
     All_Values : loop
        select
           accept Check (Value : in Positive) do
              Candidate := Value;
           end Check;
           if Candidate rem Number /= 0 then
              if Next = null then
                 Next := new Siever_Task;
              end if;
              Next.Check (Value => Candidate);
           end if;
        or
           accept Print do
              Ada.Text_IO.Put (Item => Integer'Image (Number) );
              if Next /= null then
                 Next.Print;
              end if;
           end Print;
           exit All_Values;
        end select;
     end loop All_Values;
  end Siever;
  Head  : Sieve_Ptr := new Siever;
  Max   : Positive  := 20;
  Value : Positive  := 3;

begin -- Sieve_With_Wheel

  if Ada.Command_Line.Argument_Count > 0 then
     Max := Integer'Value (Ada.Command_Line.Argument (1) );
  end if;
  All_Values : loop
     exit All_Values when Value > Max;
     Head.Check (Value => Value);
     Value := Value + 2;
  end loop All_Values;
  Ada.Text_IO.Put (Item => " 2");
  Head.Print;

end Sieve_With_Wheel;</ada>

ALGOL 68

BOOL prime = TRUE, non prime = FALSE;
PROC eratosthenes = (INT n)[]BOOL:
(
  [n]BOOL sieve;
  FOR i TO UPB sieve DO sieve[i] := prime OD;
  INT m = ENTIER sqrt(n);
  sieve[1] := non prime;
  FOR i FROM 2 TO m DO
    IF sieve[i] = prime THEN
      FOR j FROM i*i BY i TO n DO
        sieve[j] := non prime
      OD
    FI
  OD;
  sieve
);

print((eratosthenes(80),new line))

Output:

FTTFTFTFFFTFTFFFTFTFFFTFFFFFTFTFFFFFTFFFTFTFFFTFFFFFTFFFFFTFTFFFFFTFFFTFTFFFFFTF

BASIC

Works with: FreeBASIC
Works with: RapidQ

<freebasic> DIM n AS Integer, k AS Integer, limit AS Integer

INPUT "Enter number to search to: "; limit DIM flags(limit) AS Integer

FOR n = 2 TO SQR(limit)

   IF flags(n) = 0 THEN
       FOR k = n*n TO limit STEP n
           flags(k) = 1
       NEXT k
   END IF

NEXT n

' Display the primes FOR n = 2 TO limit

   IF flags(n) = 0 THEN PRINT n; ", ";

NEXT n </freebasic>

Befunge

2>:3g" "-!v\  g30          <
 |!`"O":+1_:.:03p>03g+:"O"`|
 @               ^  p3\" ":<
2 234567890123456789012345678901234567890123456789012345678901234567890123456789

C

Plain sieve, without any optimizations:

<c>#include <stdlib.h>

  1. include <math.h>

char* eratosthenes (int n) {

 char* sieve;
 int i, j, m;
 /* calloc initializes to zero */
 sieve = calloc (n+1, sizeof(char));
 m = (int) sqrt ((double) n);
 sieve[0] = 1;
 sieve[1] = 1;
 for (i = 2; i <= m; i++) {
   if (sieve[i] == 0) {
     for (j = i*i; j <= n; j += i) {
       sieve[j] = 1;
     }
   }
 }
 return sieve;

}</c>

Possible optimizations include sieving only odd numbers (or more complex wheels), packing the sieve into bits to improve locality (and allow larger sieves), etc.

C++

Works with: Boost

<cpp>// yield all prime numbers less then limit. template<class UnaryFunction> void primesupto(int limit, UnaryFunction yield) {

 std::vector<bool> is_prime(limit, true);
 
 const int sqrt_limit = static_cast<int>(std::sqrt(limit));
 for (int n = 2; n <= sqrt_limit; ++n)
   if (is_prime[n]) {

yield(n);

for (unsigned k = n*n, ulim = static_cast<unsigned>(limit); k < ulim; k += n)

     //NOTE: "unsigned" is used to avoid an overflow in `k+=n` for `limit` near INT_MAX

is_prime[k] = false;

   }
 for (int n = sqrt_limit + 1; n < limit; ++n)
   if (is_prime[n])

yield(n); }</cpp>

Full program:

<cpp>/**

  $ g++ -I/path/to/boost sieve.cpp -o sieve && sieve 10000000
*/
  1. include <inttypes.h> // uintmax_t
  2. include <limits>
  3. include <cmath>
  4. include <iostream>
  5. include <sstream>
  6. include <vector>
  1. include <boost/lambda/lambda.hpp>


int main(int argc, char *argv[]) {

 using namespace std;
 using namespace boost::lambda;
 int limit = 10000;
 if (argc == 2) {
   stringstream ss(argv[--argc]);
   ss >> limit;
   if (limit < 1 or ss.fail()) {
     cerr << "USAGE:\n  sieve LIMIT\n\nwhere LIMIT in the range [1, " 

<< numeric_limits<int>::max() << ")" << endl;

     return 2;
   }
 }
 // print primes less then 100
 primesupto(100, cout << _1 << " ");
 cout << endl;  
 // find number of primes less then limit and their sum
 int count = 0;
 uintmax_t sum = 0;
 primesupto(limit, (var(sum) += _1, var(count) += 1));
 cout << "limit sum pi(n)\n" 
      << limit << " " << sum << " " << count << endl;

}</cpp>

Common Lisp

<lisp>(defun primer ()

((lambda (&rest q)
 (lambda ()
 ((lambda (u n) (funcall u u n))
  (lambda (u n) (if (some (lambda (x y) (and (/= 1 y) (= (mod x y) 0)))
                          ((lambda (x &aux (y (list x))) (setf (cdr y) y)) n) q)
                    (funcall u u (1+ n)) (setf q (cons n q) n n))) (1+ (car q))))) 1))
Example use

(defparameter *png* (primer)) (loop repeat 50 collect (funcall *png*))</lisp>

E

E's standard library doesn't have a step-by-N numeric range, so we'll define one, implementing the standard iteration protocol.

def rangeFromBelowBy(start, limit, step) {
  return def stepper {
    to iterate(f) {
      var i := start
      while (i < limit) {
        f(null, i)
        i += step
      }
    }
  }
}

The sieve itself:

def eratosthenes(limit :(int > 2), output) {
  def composite := [].asSet().diverge()
  for i ? (!composite.contains(i)) in 2..!limit {
    output(i)
    composite.addAll(rangeFromBelowBy(i ** 2, limit, i))
  }
}

Example usage:

? eratosthenes(12, println)
# stdout: 2
#         3
#         5
#         7
#         11

Forth

: sieve ( n -- )
  here over erase
  2
  begin
    2dup dup * >
  while
    here over + c@ 0= if
      2dup dup * do
        1 here i + c!
      dup +loop
    then
    1+
  repeat
  drop
  ." Primes: " 2 do here i + c@ 0= if i . then loop ;

100 sieve

Fortran

Fortran 90 and later

PROGRAM SIEVE
  IMPLICIT NONE
  INTEGER :: i, j, number
  LOGICAL, ALLOCATABLE :: pflags(:)

  WRITE(*,*) "Enter number to search to"
  READ (*,*) number

  ALLOCATE (pflags(2:number))
  pflags = .TRUE.    

  DO i = 2, SQRT(REAL(number))
    IF (pflags(i)) THEN
      DO j = i+i, number, i
        pflags(j) = .FALSE.
      END DO
    END IF
  END DO

  DO i = 2, number
    IF (pflags(i)) WRITE(*,*) i
  END DO

  DEALLOCATE (pflags)

END PROGRAM SIEVE

Since 2 is trivially the only even prime number this version just sieves odd numbers

ALLOCATE (pflags((number-1)/2))
pflags = .TRUE.    
 
DO i = 1, SQRT(REAL(number-1)/2)
  IF (pflags(i)) THEN
    DO j = 3*i+1, (number-1)/2, 2*i+1
      pflags(j) = .FALSE.
    END DO
  END IF
END DO

DO i = 1, (number-1)/2
  IF (pflags(i)) WRITE(*,*) 2*i + 1
END DO  

Haskell

This example may be incorrect due to a recent change in the task requirements or a lack of testing. Please verify it and remove this message. If the example does not match the requirements or does not work, replace this message with Template:incorrect or fix the code yourself.

[[Category:{{{1}}} examples needing attention]]Property "Example requires attention" (as page type) with input value "{{{1}}}" contains invalid characters or is incomplete and therefore can cause unexpected results during a query or annotation process.

Imperative version, with unboxed arrays:

import Control.Monad
import Control.Monad.ST

import Data.Array.ST
import Data.Array.Unboxed

primeSieve n = runST sieve where
  newSieve :: ST s (STUArray s Integer Bool)
  newSieve = newArray (2,n) True
  sieve :: ST s (UArray Integer Bool)
  sieve = do
    s <- newSieve
    let m = ceiling $ sqrt $ fromInteger n
    forM_ [2..m] $ \i -> do
      si <- readArray s i
      when si $ do
        forM_ [i*i,i*i+i..n] $ \j -> do
        writeArray s j False
    unsafeFreeze s

Return primes from sieve as list:

primesTo n = [p | p <- [2..n], s ! p] where s = primeSieve n

One often sees a purely functional version similar to

primes :: [Integer]
primes = sieve [2..] where
  sieve (p:xs) = p : sieve [x | x <- xs, x `mod` p > 0]

As Melissa O'Neill demonstrates in The Genuine Sieve of Eratosthenes, this version is not better than trial division. She also presents an actual purely functional version that uses priority queues, and is much easier to combine with wheels (pre-calculated sieves for small primes) than the imperative version. Even combined with a simple wheel, the speed of this version is similar to the imperative version.

Icon

Icon HandBook

procedure main()
   sieve(100)
end
procedure sieve(n)
   local p,i,j
   p:=repl("1",n)
   every i:=2 to sqrt(n) do
       if p[i] == "1" then
           every j:= i+i to n by i do p[j]:="0"
   every i:=2 to n do if p[i]=="1" then write(i)
end

J

This example may be incorrect due to a recent change in the task requirements or a lack of testing. Please verify it and remove this message. If the example does not match the requirements or does not work, replace this message with Template:incorrect or fix the code yourself.

[[Category:{{{1}}} examples needing attention]]Property "Example requires attention" (as page type) with input value "{{{1}}}" contains invalid characters or is incomplete and therefore can cause unexpected results during a query or annotation process.

sieve=: 3 : 0
 m=. <.%:y
 z=. $0
 b=. y{.1
 while. m>j=. 1+b i. 0 do.
  b=. b+.y$(-j){.1
  z=. z,j
 end.
 z,1+I.-.b
)

"Wheels" are readily implemented as follows:

sieve1=: 3 : 0
 m=. <.%:y
 z=. y (>:#]) 2 3 5 7
 b=. 1,}.y$+./(*/z)$&>(-z){.&.>1
 while. m>j=. 1+b i. 0 do.
  b=. b+.y$(-j){.1
  z=. z,j
 end.
 z,1+I.-.b
)

The use of 2 3 5 7 as wheels provides a 20% time improvement for n=1000 and 2% for n=1e6 .

Java

Works with: Java version 1.5+

<java>import java.util.LinkedList;

public class Sieve{

      public static LinkedList<Integer> sieve(int n){
              if(n < 2) return new LinkedList<Integer>();
              LinkedList<Integer> primes = new LinkedList<Integer>();
              LinkedList<Integer> nums = new LinkedList<Integer>();
              for(int i = 2;i <= n;i++){ //unoptimized
                      nums.add(i);
              }
              while(nums.size() > 0){
                      int nextPrime = nums.remove();
                      for(int i = nextPrime * nextPrime;i <= n;i += nextPrime){
                              nums.removeFirstOccurrence(i);
                      }
                      primes.add(nextPrime);
              }
              return primes;
      }

}</java>

To optimize by testing only odd numbers, replace the loop marked "unoptimized" with these lines: <java>nums.add(2); for(int i = 3;i <= n;i += 2){

      nums.add(i);

}</java>

to sieve :limit
  make "a (array :limit 2)     ; initialized to empty lists
  make "p []
  for [i 2 :limit] [
    if empty? item :i :a [
      queue "p :i
      for [j [:i * :i] :limit :i] [setitem :j :a :i]
    ]
  ]
  output :p
end
print sieve 100   ; 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

Lucid

prime
 where
    prime = 2 fby (n whenever isprime(n));
    n = 3 fby n+2;
    isprime(n) = not(divs) asa divs or prime*prime > N
                    where
                      N is current n;
                      divs = N mod prime eq 0;
                    end;
 end

recursive

sieve( N )
   where
    N = 2 fby N + 1;
    sieve( i ) =
      i fby sieve ( i whenever i mod first i ne 0 ) ;
   end

MAXScript

fn eratosthenes n =
(
    multiples = #()
    print 2
    for i in 3 to n do
    (
        if (findItem multiples i) == 0 then
        (
            print i
            for j in (i * i) to n by i do
            (
                append multiples j
            )
        )
    )
)

eratosthenes 100

Nial

primes is sublist [ each (2 = sum eachright (0 = mod) [pass,count]), pass ] rest count

Using it

|primes 10
=2 3 5 7

Oberon-2

MODULE Primes;

   IMPORT Out, Math;

   CONST N = 1000;

   VAR a: ARRAY N OF BOOLEAN;
      i, j, m: INTEGER;

BEGIN
   (* Set all elements of a to TRUE. *)
   FOR i := 1 TO N - 1 DO
      a[i] := TRUE;
   END;

   (* Compute square root of N and convert back to INTEGER. *)
   m := ENTIER(Math.Sqrt(N));

   FOR i := 2 TO m DO
      IF a[i] THEN
         FOR j := 2 TO (N - 1) DIV i DO 
            a[i*j] := FALSE;
         END;
      END;
   END;

   (* Print all the elements of a that are TRUE. *)
   FOR i := 2 TO N - 1 DO
      IF a[i] THEN
         Out.Int(i, 4);
      END;
   END;
   Out.Ln;
END Primes.

OCaml

Imperative

<ocaml>let sieve n =

 let is_prime = Array.create n true in
 let limit = truncate(sqrt (float n)) in
 for i = 2 to pred limit do
   if is_prime.(i) then
     let j = ref (i*i) in
     try while true do
       is_prime.(!j) <- false;
       j := !j + i;
     done with _ -> ()
 done;
 (is_prime)</ocaml>

<ocaml>let primes n =

 let _, primes =
   Array.fold_left (fun (i,acc) -> function
       | true -> (i+1, i::acc)
       | false -> (i+1, acc))
     (0, [])
     (sieve n)
 in
 List.tl(List.tl(List.rev primes))</ocaml>

in the top-level:

# primes 100 ;;
- : int list =
[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]

Functional

<ocaml>(* first define some iterators *)

  1. let fold_iter f init a b =
   let rec aux acc i =
     if i > b
     then (acc)
     else aux (f acc i) (succ i)
   in
   aux init a ;;

val fold_iter : ('a -> int -> 'a) -> 'a -> int -> int -> 'a = <fun>

  1. let fold_step f init a b step =
   let rec aux acc i =
     if i > b
     then (acc)
     else aux (f acc i) (i + step)
   in
   aux init a ;;

val fold_step : ('a -> int -> 'a) -> 'a -> int -> int -> int -> 'a = <fun>

(* remove a given value from a list *)

  1. let remove li v =
   let rec aux acc = function
     | hd::tl when hd = v -> (List.rev_append acc tl)
     | hd::tl -> aux (hd::acc) tl
     | [] -> li
   in
   aux [] li ;;

val remove : 'a list -> 'a -> 'a list = <fun>

(* the main function *)

  1. let primes n =
   let li =
     (* create a list [from 2; ... until n] *)
     List.rev(fold_iter (fun acc i -> (i::acc)) [] 2 n)
   in
   let limit = truncate(sqrt(float n)) in
   fold_iter (fun li i ->
       if List.mem i li  (* test if (i) is prime *)
       then (fold_step (fun acc j -> remove acc j) li (i*i) n i)
       else li)
     li 2 (pred limit)
 ;;

val primes : int -> int list = <fun>

  1. primes 200 ;;

- : int list = [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; 103; 107; 109; 113; 127; 131; 137; 139; 149; 151;
157; 163; 167; 173; 179; 181; 191; 193; 197; 199]</ocaml>

Pascal

Note: Some Pascal implementations put quite low limits on the size of a set (e.g. Turbo Pascal doesn't allow more than 256 members). To compile on such an implementation, reduce the constant PrimeLimit accordingly. <pascal> program primes(output)

const

PrimeLimit = 1000;

var

primes: set of 1 .. PrimeLimit;
n, k: integer;
needcomma: boolean;

begin

{ calculate the primes }
primes := [2 .. PrimeLimit];
for n := 1 to trunc(sqrt(PrimeLimit)) do
 begin
  if n in primes
   then
    begin
     k := n*n;
     while k < PrimeLimit do
      begin
       primes := primes - [k];
       k := k + n
      end
    end
 end;
 { output the primes }
 needcomma := false;
 for n := 1 to PrimeLimit do
  if n in primes
   then
    begin
     if needcomma
      then
       write(', ');
     write(n);
     needcomma := true
    end

end. </pascal>

Perl

<perl>sub findprimes {

my $prime_limit=shift;
my @possible_primes;
my @primes;
my $prime;
if ($prime_limit < 2) {
 return \@primes;
}
@possible_primes=(2..$prime_limit);
do {
 $prime=shift(@possible_primes);
 push @primes, $prime;
 @possible_primes = grep {$_%$prime!=0} @possible_primes;
} while ($possible_primes[0] < sqrt($prime_limit));	
return [@primes,@possible_primes];	

}

my $prime_limit; print "Input the number that you wish to test :"; chomp($prime_limit=<STDIN>); my $primes=&findprimes($prime_limit); print "The primes are: @{$primes}!!!\n";</perl>

Pop11

define eratostenes(n);
lvars bits = inits(n), i, j;
for i from 2 to n do
   if bits(i) = 0 then
      printf('' >< i, '%s\n');
      for j from 2*i by i to n do
         1 -> bits(j);
      endfor;
   endif;
endfor;
enddefine;

Python

Testing on list of primes up to that number

<python>for x in range(1,100000)

   z=0
   for y in p:
       if x%y==0:
           z=1
   if z==0:
       p.append(x)</python>

Using list lookup

<python>def eratosthenes(n):

   multiples = []
   print 2
   for i in xrange(3, n+1):
       if not i in multiples:
           print i
           for j in xrange(i*i, n+1, i):
               multiples.append(j)

eratosthenes(100)</python>

Using set lookup

The version below uses a set to store the multiples. set objects are much faster (usually O(log n)) than lists (O(n)) for checking if a given object is a member. Using the set.update method avoids explicit iteration in the interpreter, giving a further speed improvement.

<python>def eratosthenes2(n):

   multiples = set()
   print 2
   for i in xrange(3, n+1):
       if not i in multiples:
           print i
           multiples.update(xrange(i*i, n+1, i))

eratosthenes2(100)</python>

Using array lookup

The version below uses array lookup to test for primality. The function primes_upto() is a straightforward implementation of Sieve of Eratosthenesalgorithm. It returns prime numbers less than or equal to limit. <python>def primes_upto(limit):

   is_prime = [False] * 2 + [True] * (limit - 1) 
   for n in xrange(int(limit**0.5 + 1.5)): # stop at ``sqrt(limit)``
       if is_prime[n]:
           for i in xrange(n*n, limit+1, n):
               is_prime[i] = False
   return [i for i, prime in enumerate(is_prime) if prime]</python>

Using generator

<python> def iprimes_upto(limit):

   is_prime = [False] * 2 + [True] * (limit - 1)
   for n in range(limit + 1):
       if is_prime[n]:
           yield n
           for i in range(n*n, limit+1, n): # start at ``n`` squared
               is_prime[i] = False

</python> Example: <python> >>> list(iprimes_upto(15)) [2, 3, 5, 7, 11, 13]</python>

Using numpy

Library: numpy

Belowed code adapted from literateprograms.org using numpy <python>import numpy def primes_upto2(limit):

   is_prime = numpy.ones(limit + 1, dtype=numpy.bool)
   for n in xrange(2, int(limit**0.5 + 1.5)): 
       if is_prime[n]:
           is_prime[n*n::n] = 0
   return numpy.nonzero(is_prime)[0][2:]</python>

Performance note: there is no point to add wheels here, due to execution of p[n*n::n] = 0 and nonzero() takes us almost all time.

Using wheels

Version with wheel based optimization: <python>from numpy import array, bool_, multiply, nonzero, ones, put, resize

def makepattern(smallprimes):

   pattern = ones(multiply.reduce(smallprimes), dtype=bool_)
   pattern[0] = 0
   for p in smallprimes:
       pattern[p::p] = 0
   return pattern

def primes_upto3(limit, smallprimes=(2,3,5,7,11)):

   sp = array(smallprimes)
   if limit <= sp.max(): return sp[sp <= limit]
   #
   isprime = resize(makepattern(sp), limit + 1) 
   isprime[:2] = 0; put(isprime, sp, 1) 
   #
   for n in range(sp.max() + 2, int(limit**0.5 + 1.5), 2): 
       if isprime[n]:
           isprime[n*n::n] = 0 
   return nonzero(isprime)[0]</python>

Examples: <python>>>> primes_upto3(10**6, smallprimes=(2,3)) # Wall time: 0.17 array([ 2, 3, 5, ..., 999961, 999979, 999983]) >>> primes_upto3(10**7, smallprimes=(2,3)) # Wall time: 2.13 array([ 2, 3, 5, ..., 9999971, 9999973, 9999991]) >>> primes_upto3(15) array([ 2, 3, 5, 7, 11, 13]) >>> primes_upto3(10**7, smallprimes=primes_upto3(15)) # Wall time: 1.31 array([ 2, 3, 5, ..., 9999971, 9999973, 9999991]) >>> primes_upto2(10**7) # Wall time: 1.39 <-- version without wheels array([ 2, 3, 5, ..., 9999971, 9999973, 9999991]) >>> primes_upto3(10**7) # Wall time: 1.30 array([ 2, 3, 5, ..., 9999971, 9999973, 9999991])</python> The above-mentioned examples demonstrate that the given wheel based optimization does not show significant performance gain.

Infinite generator

A generator that will generate primes indefinitely (until it runs out of memory). <python>import heapq

  1. generates p*p, p*(p+1), p*(p+2), ...
  2. i.e. generates a sequence of non-primes that are multiples of p
  3. not a Python generator though
  4. it supports "peeking"

class MultiplesGen:

   def __init__(self, p):
       self.p = p
       self.q = p * p
   
   def get(self):
       return self.q
   
   def step(self):
       self.q += self.p
   
   def __cmp__(self, other):
       # order these sequences by their first not-yet-used element
       return cmp(self.q, other.q)
  1. generates all prime numbers

def sieve():

   # priority queue of above generators for all primes generated so far
   # i.e. priority queue of sequences of non-primes
   # the priority queue allows us to get the "next" non-prime quickly
   nonprimes = []
   
   i = 2
   while True:
       if nonprimes and i == nonprimes[0].get(): # non-prime
           while nonprimes[0].get() == i:
               # for each generator that generates this number
               # have it go to the next number
               # and re-position it in the priority queue
               x = heapq.heappop(nonprimes)
               x.step()
               heapq.heappush(nonprimes, x)
       
       else: # prime
           heapq.heappush(nonprimes, MultiplesGen(i))
           yield i
       
       i += 1</python>

Example:

>>> foo = sieve()
>>> for i in range(20):
...     print foo.next()
... 
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71

UnixPipes

# Uses file a as a buffer for sequences.
echo > a && yes \  | cat -n | tail +2|
 while read x ; do
     ( (echo 1 ; cat -s a) | xargs -n 1 expr $x % | grep "^0$" | wc -l | grep "^ *1 *$" > /dev/null && echo $x |tee -a a )
 done

Vedit macro language

This implementation uses an edit buffer as an array for flags. After the macro has been run, you can see how the primes are located in the array. Primes are marked with 'P' and non-primes with '-'. The first character position represents number 0.

#10 = Get_Num("Enter number to search to: ", STATLINE)
Buf_Switch(Buf_Free)                    // Use edit buffer as flags array
Ins_Text("--")                          // 0 and 1 are not primes
Ins_Char('P', COUNT, #10-1)             // init rest of the flags to "prime"
for (#1 = 2; #1*#1 < #10; #1++) {
    Goto_Pos(#1)
    if (Cur_Char=='P') {                // this is a prime number
        for (#2 = #1*#1; #2 <= #10; #2 += #1) {
            Goto_Pos(#2)
            Ins_Char('-', OVERWRITE)
        }
    }
}

Sample output showing numbers in range 0 to 599.

--PP-P-P---P-P---P-P---P-----P-P-----P---P-P---P-----P-----P
-P-----P---P-P-----P---P-----P-------P---P-P---P-P---P------
-------P---P-----P-P---------P-P-----P-----P---P-----P-----P
-P---------P-P---P-P-----------P-----------P---P-P---P-----P
-P---------P-----P-----P-----P-P-----P---P-P---------P------
-------P---P-P---P-------------P-----P---------P-P---P-----P
-------P-----P-----P---P-----P-------P---P-------P---------P
-P---------P-P-----P---P-----P-------P---P-P---P-----------P
-------P---P-------P---P-----P-----------P-P----------------
-P-----P---------P-----P-----P-P-----P---------P-----P-----P