my @primes = (2, 3, 5, 7, 11); # None have been tested sub more_primes { # This adds to the list of primes until it reaches $max # or the square of the largest current prime (assumed odd) my $base = shift || $primes[-1]+1; my $max = shift || $base + 10_000; my $square = $primes[-1] * $primes[-1]; $max = $square if $square < $max; # Determine what to find primes to $base++ unless $base % 2; # Make the base odd $max-- if $max %2; # Make the max odd $max = ($max - $base)/2; # Make $max into a count of odds return if $max < 0; # Sanity check my $more = ""; # Initialize vector of 0's for the # odd numbers in our range shift @primes; # Remove 2 foreach my $p (@primes) { my $start; if ($base < $p * $p) { $start = ($p * $p - $base)/2; # Start at the square if ($max < $start) { # Rest of primes don't matter! last; } } else { # Start at first odd it divides $start = $base % $p; # Find remainder $start = $p - $start if $start; # Distance to first thing it divides $start += $p if $start %2; # Distance to first odd it divides $start = $start/2; # Reindex for counting over odd! } for (my $i = $start; $i <= $max; $i += $p) { vec($more, $i, 1) = 1; } } unshift @primes, 2; # Replace 2 # Read off list of primes push @primes, map {$_ + $_ + $base} grep {vec($more, $_, 1) == 0} 0..$max; } sub ith_prime { my $i = shift; while ($i > $#primes) { more_primes(); } return $primes[$i]; } sub prime_iterator { my $i = -1; return sub { $i++; if ($i > $#primes) { more_primes(); } return $primes[$i]; }; }