[libmath-prime-util-perl] 23/50: Enhancements to primes.pl tests
Partha P. Mukherjee
ppm-guest at moszumanska.debian.org
Thu May 21 18:45:35 UTC 2015
This is an automated email from the git hooks/post-receive script.
ppm-guest pushed a commit to annotated tag v0.13
in repository libmath-prime-util-perl.
commit a892e8f4d90530832f4ae674d56dcba9055ff914
Author: Dana Jacobsen <dana at acm.org>
Date: Sat Oct 20 03:29:17 2012 -0600
Enhancements to primes.pl tests
---
examples/make-script-test-data.pl | 66 +++++++++++++++--------
examples/test-primes-script.pl | 110 ++++++++++++++++++++------------------
examples/test-primes-script2.pl | 84 +++++++++++++++++++++++++++++
3 files changed, 186 insertions(+), 74 deletions(-)
diff --git a/examples/make-script-test-data.pl b/examples/make-script-test-data.pl
index bfee664..760f4eb 100755
--- a/examples/make-script-test-data.pl
+++ b/examples/make-script-test-data.pl
@@ -6,28 +6,33 @@ use FindBin;
use bigint;
use Data::BitStream::XS;
use Math::Prime::Util qw/is_prime/;
-$|++; #flush the output buffer after every write() or print() function
+$|++;
+# Encode all the OEIS text files for our primes.pl testing into a bitstream.
+# This not only makes the test script run much faster, but it turns 18 text
+# files of 5MB into one ~300k file.
my @test_data = (
- [ 668, "Mersenne", "--mersenne", 10**100],
- [ 7529, "Triplet", "--triplet", 0],
- [ 7530, "Quadruplet", "--quadruplet", 0],
- [23200, "Cousin", "--cousin", 0],
- [23201, "Sexy", "--sexy", 0],
- [ 1359, "Twin", "--twin", 0],
- [ 5385, "Safe", "--safe", 0],
- [ 5384, "SG", "--sophie", 0],
- [ 2385, "Palindromic", "--palin", 32_965_656_923],
- [ 5479, "Lucas", "--lucas", 0],
- [ 5478, "Fibonacci", "--fibonacci", 0],
- [63980, "Pillai", "--pillai", 2000],
- [28388, "Good", "--good", 20000],
- [ 2407, "Cuban y+1", "--cuban1", 0],
- [ 2648, "Cuban y+2", "--cuban2", 100_000_000],
- [ 5234, "Primorial+1", "--pnp1", 2500],
- [ 6794, "Primorial-1", "--pnm1", 2500],
- [18239, "Euclid", "--euclid", 0],
+ # OEIS# TEXT NAME script-arg skip if > this
+ [ 7529, "Triplet", "triplet", 0],
+ [ 7530, "Quadruplet", "quadruplet", 0],
+ [23200, "Cousin", "cousin", 0],
+ [23201, "Sexy", "sexy", 0],
+ [ 1359, "Twin", "twin", 0],
+ [ 5385, "Safe", "safe", 0],
+ [ 5384, "SG", "sophie", 0],
+ [ 2407, "Cuban y+1", "cuban1", 0],
+ [ 2648, "Cuban y+2", "cuban2", 0],
+ [ 2385, "Palindromic", "palin", 32_965_656_923],
+ [ 668, "Mersenne", "mersenne", 10**100],
+ [ 5479, "Lucas", "lucas", 0],
+ [ 5478, "Fibonacci", "fibonacci", 0],
+ [63980, "Pillai", "pillai", 2000],
+ [28388, "Good", "good", 20000],
+ [31157, "Lucky", "lucky", 0],
+ [ 5234, "Primorial+1", "pnp1", 2500],
+ [ 6794, "Primorial-1", "pnm1", 2500],
+ [18239, "Euclid", "euclid", 0],
);
foreach my $test (@test_data) {
@@ -45,7 +50,7 @@ foreach my $test (@test_data) {
my $stream = Data::BitStream::XS->new( file => 'script-test-data.bs', mode => 'w' );
foreach my $test (@test_data) {
- test_oeis(@$test);
+ encode_oeis(@$test);
}
$stream->write_close();
@@ -102,12 +107,15 @@ sub read_oeis {
return \@ref;
}
-sub test_oeis {
+sub encode_oeis {
my($oeis_no, $name, $script_arg, $restrict, $ref_data) = @_;
my @ref = @$ref_data;
printf "%12s primes: stream..", $name;
+ put_text_string($stream, $script_arg);
+ put_text_string($stream, $name);
+
if ($ref[-1] > 18446744073709551615) {
print ",";
# Store the first two values, then a list of deltas
@@ -151,3 +159,19 @@ sub test_oeis {
print "done\n";
}
+
+sub put_text_string {
+ my ($stream, $str) = @_;
+ $stream->put_gamma(ord($_)) for (split "", $str);
+ $stream->put_gamma(0);
+ 1;
+}
+
+sub get_text_string {
+ my ($stream) = @_;
+ my $str = '';
+ while (my $c = $stream->get_gamma) {
+ $str .= chr($c);
+ }
+ $str;
+}
diff --git a/examples/test-primes-script.pl b/examples/test-primes-script.pl
index 7f3390f..052b6af 100755
--- a/examples/test-primes-script.pl
+++ b/examples/test-primes-script.pl
@@ -8,50 +8,29 @@ use bigint;
use Data::BitStream::XS;
$|++; #flush the output buffer after every write() or print() function
-# Should use a "put_test_string" sort of call on the test data, so we
-# wouldn't need this.
-my @test_data = (
- [ 668, "Mersenne", "--mersenne", 10**100],
- [ 7529, "Triplet", "--triplet", 0],
- [ 7530, "Quadruplet", "--quadruplet", 0],
- [23200, "Cousin", "--cousin", 0],
- [23201, "Sexy", "--sexy", 0],
- [ 1359, "Twin", "--twin", 0],
- [ 5385, "Safe", "--safe", 0],
- [ 5384, "SG", "--sophie", 0],
- [ 2385, "Palindromic", "--palin", 32_965_656_923],
- [ 5479, "Lucas", "--lucas", 0],
- [ 5478, "Fibonacci", "--fibonacci", 0],
- [63980, "Pillai", "--pillai", 2000],
- [28388, "Good", "--good", 20000],
- [ 2407, "Cuban y+1", "--cuban1", 0],
- [ 2648, "Cuban y+2", "--cuban2", 100_000_000],
- [ 5234, "Primorial+1", "--pnp1", 2500],
- [ 6794, "Primorial-1", "--pnm1", 2500],
- [18239, "Euclid", "--euclid", 0],
-);
-my %oeis_name = map { $_->[0] => $_->[1] } @test_data;
-my %oeis_number = map { my $n=$_->[2]; $n=~s/^--//; $n => $_->[0] } @test_data;
+# Maps between oeis name and number, filled in as we read sequences.
+my %oeis_number; # short-name -> no
+my %oeis_data; # no -> ref to info+data
+
+# returned array contains elements of:
+# [$oeis_no, $name, $script_arg, $num_entries, \@ref_data];
+my $test_data = read_script_data('script-test-data.bs');
# Verify additional filters
my @additional_filters;
foreach my $name (@ARGV) {
$name =~ s/^--//;
- die "Unknown filter: $name\n" unless defined $oeis_number{$name};
- push @additional_filters, $name;
+ my $oeis_no = $oeis_number{$name};
+ die "Unknown filter: $name\n" unless defined $oeis_no;
+ push @additional_filters, $oeis_no;
}
-
-my $test_data_hash = read_script_data('script-test-data.bs');
-
if (@additional_filters > 0) {
- print "Additional Filters: ", join(" ", @additional_filters), "\n";
+ print "Additional Filters: ",
+ join(" ", map { $oeis_data{$_}->[2] } @additional_filters), "\n";
}
-foreach my $test (@test_data) {
- my $oeis_no = $test->[0];
- if (!defined $test_data_hash->{$oeis_no}) {
- die "No test data found for OEIS $oeis_no : $test->[1] primes\n";
- }
- test_oeis(@$test, $test_data_hash);
+
+foreach my $test (@$test_data) {
+ test_oeis(@$test);
}
@@ -64,11 +43,13 @@ sub read_script_data {
unless -r $filename;
my $stream = Data::BitStream::XS->new( file => $filename, mode => 'ro' );
- my %hash;
+ my @data;
while (!$stream->exhausted) {
+ my $script_arg = get_text_string($stream);
+ my $name = get_text_string($stream);
my ($oeis_no, $is_bigint, $num_entries, @ref) = $stream->get_gamma(5);
- printf "%12s primes (OEIS A%06d): reading %7d entries..", $oeis_name{$oeis_no}, $oeis_no, $num_entries;
+ printf "%12s primes (OEIS A%06d): reading %7d entries..", $name, $oeis_no, $num_entries;
if ($is_bigint) {
print ",";
my $k = 2;
@@ -76,7 +57,7 @@ sub read_script_data {
print ".";
# Check to see if we have any giant deltas
foreach my $d (@deltas) {
- if ($d >= 18446744073709551614) {
+ if ( $d >= '18446744073709551614' ) {
my $len = $stream->get_gamma;
my $binstr = $stream->read_string($len);
$d = Math::BigInt->new('0b' . $binstr);
@@ -85,7 +66,6 @@ sub read_script_data {
print ".";
my $prev = $ref[1];
push @ref, map { $prev = $_*2+$prev+2; } @deltas;
- $hash{$oeis_no} = \@ref;
print ".\n";
} else {
no bigint;
@@ -95,25 +75,31 @@ sub read_script_data {
print ".";
my $prev = $ref[1];
push @ref, map { $prev = $_*2+$prev+2; } @deltas;
- $hash{$oeis_no} = \@ref;
print ".\n";
}
+ my $row = [$oeis_no, $name, $script_arg, $num_entries, \@ref];
+ push @data, $row;
+ $oeis_data{$oeis_no} = $row;
+ $oeis_number{$script_arg} = $oeis_no;
}
- \%hash;
+ \@data;
}
sub test_oeis {
- my($oeis_no, $name, $script_arg, $restrict, $test_data_hash) = @_;
+ my($oeis_no, $name, $script_arg, $num_entries, $ref_data) = @_;
- my @ref = @{ $test_data_hash->{$oeis_no} };
+ my @ref = @$ref_data;
my $end = $ref[-1];
-
- foreach my $filter_name (@additional_filters) {
- my $filter_no = $oeis_number{$filter_name};
- my %filter_data;
- undef @filter_data{ @{$test_data_hash->{$filter_no}} };
- my $filter_end = $test_data_hash->{$filter_no}->[-1];
- @ref = grep { exists $filter_data{$_} } @ref;
+ $script_arg = '--' . $script_arg;
+
+ foreach my $filter_no (@additional_filters) {
+ #my $row = [$oeis_no, $name, $script_arg, $num_entries, \@ref];
+ my $filter_name = $oeis_data{$filter_no}->[2];
+ my $filter_data_ref = $oeis_data{$filter_no}->[4];
+ my %filter_data_hash;
+ undef @filter_data_hash{ @$filter_data_ref };
+ my $filter_end = $filter_data_ref->[-1];
+ @ref = grep { exists $filter_data_hash{$_} } @ref;
$script_arg .= " --$filter_name";
$end = $filter_end if $end > $filter_end; # bring endpoint down
}
@@ -130,11 +116,29 @@ sub test_oeis {
printf " %7d. %7.2f ms/prime\n", $num_generated, $msperprime;
}
- die "Not equal numbers: ", scalar @ref, " - ", scalar @scr, "\n"
- unless @ref == @scr;
+ if (scalar @ref != scalar @scr) {
+ warn " $FindBin::Bin/../bin/primes.pl $script_arg 1 $end\n";
+ die "Not equal numbers: ", scalar @ref, " - ", scalar @scr, "\n";
+ }
foreach my $i (0 .. $#ref) {
die "$name prime $i not equal: $ref[$i] - $scr[$i]\n"
if $ref[$i] != $scr[$i];
}
}
+
+sub put_text_string {
+ my ($stream, $str) = @_;
+ $stream->put_gamma(ord($_)) for (split "", $str);
+ $stream->put_gamma(0);
+ 1;
+}
+
+sub get_text_string {
+ my ($stream) = @_;
+ my $str = '';
+ while (my $c = $stream->get_gamma) {
+ $str .= chr($c);
+ }
+ $str;
+}
diff --git a/examples/test-primes-script2.pl b/examples/test-primes-script2.pl
new file mode 100755
index 0000000..5de579d
--- /dev/null
+++ b/examples/test-primes-script2.pl
@@ -0,0 +1,84 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use File::Spec::Functions;
+use FindBin;
+use Time::HiRes qw(gettimeofday tv_interval);
+use bigint;
+use Math::NumSeq;
+$|++; #flush the output buffer after every write() or print() function
+
+compare('Primes',
+ 10000000,
+ "$FindBin::Bin/../bin/primes.pl 1 LASTNUM",
+ q/perl -MMath::NumSeq::Primes -e 'my $seq = Math::NumSeq::Primes->new; while (1) { my $v = ($seq->next)[1]; last if $v > LASTNUM; print "$v\n"; }'/);
+
+compare('Twin',
+ 10000000,
+ "$FindBin::Bin/../bin/primes.pl --twin 1 LASTNUM",
+ q/perl -MMath::NumSeq::TwinPrimes -e 'my $seq = Math::NumSeq::TwinPrimes->new; while (1) { my $v = ($seq->next)[1]; last if $v > LASTNUM; print "$v\n"; }'/);
+
+compare('Sophie Germain',
+ 10000000,
+ "$FindBin::Bin/../bin/primes.pl --sophie 1 LASTNUM",
+ q/perl -MMath::NumSeq::SophieGermainPrimes -e 'my $seq = Math::NumSeq::SophieGermainPrimes->new; while (1) { my $v = ($seq->next)[1]; last if $v > LASTNUM; print "$v\n"; }'/);
+
+# Why Math::Prime::Util::is_prime instead of Math::Prime::XS::is_prime?
+# 1) it's much faster for the palindrome tests
+# 2) it supports bignums, which is required for Fib, Euclid, Lucas, etc.
+
+compare('Palindromic',
+ '10**11',
+ "$FindBin::Bin/../bin/primes.pl --palin 1 LASTNUM",
+ q/perl -MMath::Prime::Util=is_prime -MMath::NumSeq::Palindromes -e 'my $seq = Math::NumSeq::Palindromes->new; while (1) { my $v = ($seq->next)[1]; last if $v > LASTNUM; print "$v\n" if is_prime($v); }'/);
+
+# Sadly Math::NumSeq::LucasNumbers uses OEIS 204 (1,3) instead of OEIS 32 (-1,2)
+# and neither package offers a way to adjust.
+#compare('Lucas',
+# '10**100',
+# "$FindBin::Bin/../bin/primes.pl --lucas 1 LASTNUM",
+# q/perl -MMath::Prime::Util=is_prime -MMath::NumSeq::LucasNumbers -e 'my $seq = Math::NumSeq::LucasNumbers->new; while (1) { my $v = ($seq->next)[1]; last if $v > LASTNUM; print "$v\n" if is_prime($v); }'/);
+
+compare('Fibonacci',
+ '10**100',
+ "$FindBin::Bin/../bin/primes.pl --fib 1 LASTNUM",
+ q/perl -MMath::Prime::Util=is_prime -MMath::NumSeq::Fibonacci -e 'my $seq = Math::NumSeq::Fibonacci->new; while (1) { my $v = ($seq->next)[1]; last if $v > LASTNUM; print "$v\n" if is_prime($v); }'/);
+
+compare('Euclid',
+ '10**200',
+ "$FindBin::Bin/../bin/primes.pl --euclid 1 LASTNUM",
+ q/perl -MMath::Prime::Util=is_prime -MMath::NumSeq::Primorials -e 'my $seq = Math::NumSeq::Primorials->new; while (1) { my $v = ($seq->next)[1] + 1; last if $v > LASTNUM; print "$v\n" if is_prime($v); }'/);
+
+compare('Lucky',
+ '100000',
+ "$FindBin::Bin/../bin/primes.pl --lucky 1 LASTNUM",
+ q/perl -MMath::Prime::Util=is_prime -MMath::NumSeq::LuckyNumbers -e 'my $seq = Math::NumSeq::LuckyNumbers->new; while (1) { my $v = ($seq->next)[1]; last if $v > LASTNUM; print "$v\n" if is_prime($v); }'/);
+
+
+sub compare {
+ my($name, $end, $command_scr, $command_mns) = @_;
+ no bigint;
+ $command_scr =~ s/LASTNUM/$end/;
+ $command_mns =~ s/LASTNUM/$end/;
+
+ printf "%15s to %8s", $name, $end;
+
+ my $start_scr = [gettimeofday];
+ my @scr = split /\s+/, qx/$command_scr/;
+ my $seconds_scr = tv_interval($start_scr);
+
+ printf " (%7d). primes.pl %6.2fs", scalar @scr, $seconds_scr;
+
+ my $start_mns = [gettimeofday];
+ my @mns = split /\s+/, qx/$command_mns/;
+ my $seconds_mns = tv_interval($start_mns);
+
+ printf " Math::NumSeq %6.2fs\n", $seconds_mns;
+
+ die "$name: primes.pl generated ", scalar @scr, " results. MNS generated ", scalar @mns, " results." if scalar @scr != scalar @mns;
+
+ foreach my $i (0 .. $#scr) {
+ die "$name prime $i not equal:\n primes.pl: $scr[$i]\n MNumSeq: $mns[$i]\n"
+ if $scr[$i] != $mns[$i];
+ }
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libmath-prime-util-perl.git
More information about the Pkg-perl-cvs-commits
mailing list