[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