#!/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";
}