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/next_prime urandomm/;
use File::Temp qw/tempfile/;
use autodie;
my $maxdigits = (~0 <= 4294967295) ? 10 : 20;
$| = 1;  # fast pipes
my $num = shift || 10000;
my $yafu_fname = "yafu_batchfile_$$.txt";
$SIG{'INT'} = \&gotsig;

foreach my $digits (4 .. $maxdigits) {
  printf "%2d-digit numbers", $digits;
  my @narray = gendigits($digits, $num);
  print ".";
  my @mpuarray = mpu_next_primes(@narray);
  print ".";
  die "mpu_next_primes didn't get enough numbers" unless $#mpuarray == $#narray;
  my @yafuarray = yafu_next_primes(@narray);
  die "yafunext_primes didn't get enough numbers" unless $#yafuarray == $#narray;
  print ".";
  foreach my $n (@narray) {
    my $mpu = shift @mpuarray;
    my $yafu = shift @yafuarray;
    die "next_prime($n):  MPU: $mpu  YAFU: $yafu\n" unless $mpu == $yafu;
  }
  print ".";
  print "OK\n";
}

sub gendigits {
  my $digits = shift;
  die "Digits must be > 0" unless $digits > 0;
  my $howmany = shift;

  my $base = ($digits == 1) ? 0 : int(10 ** ($digits-1));
  my $max = int(10 ** $digits);
  $max = ~0 if $max > ~0;
  my @nums = map { $base + urandomm($max-$base) } (1 .. $howmany);
  return @nums;
}

sub mpu_next_primes {
  my @nparray;
  push @nparray, next_prime($_) for @_;
  @nparray;
}

sub yafu_next_primes {
  my @nparray;
  # Yafu 1.31 seems to go out of its way to make it hard to process more than
  # one number at a time.  The batchfile system will infinite loop if the data
  # file isn't in the current directory.
  # It does its darndest to see if you're on a terminal or not, and if not it
  # just cuts you off after one number.  So any sort of tempfile or pipe stuff
  # just plain doesn't work.  Faking it using IO::*tty* would probably work.

  #my $fh = File::Temp->new;   # .... autodie
  #print $fh, "$_\n" for @_;
  #$fh->flush;

  # Shudder.  Read comments above about why I have to do this.
  open(my $fh, '>', $yafu_fname);
  print $fh "$_\n" for @_;
  close $fh;

  open my $yafu, "yafu \"nextprime(\@)\" -batchfile $yafu_fname |";
  while (<$yafu>) {
    if (/^(ans = )?(\d+)\s*$/) {
      push @nparray, $2;
    }
  }
  close($yafu);
  @nparray;
}
sub gotsig { my $sig = shift; die "Die because SIG$sig\n"; }
END {
  unlink $yafu_fname if -e $yafu_fname;
  # YAFU leaves stuff around
  unlink "__tmpbatchfile" if -e "__tmpbatchfile";
  unlink "session.log" if -e "session.log";
}