The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/env perl
use strict;
use warnings;

use Math::Prime::Util qw/-nobigint next_prime is_prime prime_iterator/;

my $count = shift || 20;

# Find Sophie Germain primes (numbers where p and 2p+1 are both prime).

# In this method, we add a filter in front of our iterator, to create a
# Sophie-Germain-prime iterator.  This isn't the fastest way, but it's still
# 20x faster than Math::NumSeq::SophieGermainPrimes at 300k.  If we add the
# two-line precalc shown below, we can get another 4x or so more.

sub get_sophie_germain_iterator {
  my $p = shift || 2;
  my $it = prime_iterator($p);
  return sub {
    do { $p = $it->() } while !is_prime(2*$p+1);
    $p;
  };
}
my $sgit = get_sophie_germain_iterator();
for (1..$count) {
  print $sgit->(), "\n";
}


# Method 2.  At 300k this is 70x faster than Math::NumSeq::SophieGermainPrimes.
#
# my $estimate = 100 + int( nth_prime_upper($count) * 1.6 * log($count) );
# prime_precalc(2 * $estimate);
# 
# my $prime = 2;
# for (1..$count) {
#   $prime = next_prime($prime) while (!is_prime(2*$prime+1));
#   print "$prime\n";
#   $prime = next_prime($prime);
# }

# Alternate method, 10-20% faster, would benefit from a tighter estimate.
#
# my $numfound = 0;
# forprimes {
#   if ($numfound < $count && is_prime(2*$_+1)) {
#     print "$_\n";
#     $numfound++;
#   }
# } $estimate;
# die "Estimate too low" unless $numfound >= $count;