This is an automated email from the git hooks/post-receive script.

ppm-guest pushed a commit to annotated tag v0.27
in repository libmath-prime-util-perl.

commit 17559c6acaf9d010e87060b45374aa7a527eda95
Author: Dana Jacobsen <d...@acm.org>
Date:   Fri May 10 16:35:25 2013 -0700

    Allow BLS75 theorem 7 n-1 proofs
---
 examples/verify-gmp-ecpp-cert.pl |  5 ++-
 lib/Math/Prime/Util.pm           | 65 ++++++++++++++++++++++-----
 lib/Math/Prime/Util/PP.pm        | 94 +++++++++++++++++++++++++---------------
 xt/primality-proofs.pl           | 11 +++--
 4 files changed, 123 insertions(+), 52 deletions(-)

diff --git a/examples/verify-gmp-ecpp-cert.pl b/examples/verify-gmp-ecpp-cert.pl
index de3e616..7c629ce 100755
--- a/examples/verify-gmp-ecpp-cert.pl
+++ b/examples/verify-gmp-ecpp-cert.pl
@@ -4,6 +4,9 @@ use strict;
 use Math::BigInt try=>"GMP,Pari";
 use Math::Prime::Util qw/:all/;
 use Data::Dump qw/dump/;
+my $bifilter = sub { my($ctx, $n) = @_;
+                     return {dump=>"$n"} if ref($n) eq "Math::BigInt";
+                     undef; };
 
 # Takes the output of GMP-ECPP, creates a certificate in the format used
 # by MPU, and runs it through the verifier.
@@ -57,5 +60,5 @@ while (<>) {
   }
 }
 
-print dump(\@cert), "\n";
+print dump_filtered(\@cert, $bifilter), "\n";
 print verify_prime(@cert) ? "SUCCESS\n" : "FAILURE\n";
diff --git a/lib/Math/Prime/Util.pm b/lib/Math/Prime/Util.pm
index 0a7f465..bd59e50 100644
--- a/lib/Math/Prime/Util.pm
+++ b/lib/Math/Prime/Util.pm
@@ -234,9 +234,8 @@ sub _validate_positive_integer {
 
   if (ref($_[0])) {
     $_[0] = Math::BigInt->new("$_[0]") unless ref($_[0]) eq 'Math::BigInt';
-    $_bigint_small = Math::BigInt->new("$_Config{'maxparam'}")
-                   unless defined $_bigint_small;
-    if ($_[0]->bacmp($_bigint_small) <= 0) {
+    # Stupid workaround for Math::BigInt::GMP RT # 71548
+    if ($_[0]->bacmp(''.~0) <= 0) {
       $_[0] = int($_[0]->bstr);
     } else {
       $_[0]->upgrade(undef) if $_[0]->upgrade();  # Stop BigFloat upgrade
@@ -251,8 +250,8 @@ sub _validate_positive_integer {
     }
   }
   # One of these will be true:
-  #     1) $n <= max and $n is not a bigint
-  #     2) $n  > max and $n is a bigint
+  #     1) $n <= ~0 and $n is not a bigint
+  #     2) $n  > ~0 and $n is a bigint
   1;
 }
 
@@ -1802,6 +1801,13 @@ sub verify_prime {
   if ($method eq 'n-1') {
     # BLS75 or generalized Pocklington
     # 
http://www.ams.org/journals/mcom/1975-29-130/S0025-5718-1975-0384673-1/S0025-5718-1975-0384673-1.pdf
+    # Pull of optional theorem 7 data
+    my ($theorem, $t7_B1, $t7_B, $t7_a) = (5, undef, undef, undef);
+    if (scalar @pdata == 3 && ref($pdata[0]) eq 'ARRAY' && $pdata[0]->[0] =~ 
/^(B|T7|Theorem\s*7)$/i) {
+      $theorem = 7;
+      (undef, $t7_B1, $t7_B, $t7_a) = @{shift @pdata};
+      $t7_B  = Math::BigInt->new("$t7_B");
+    }
     if (scalar @pdata != 2 || (ref($pdata[0]) ne 'ARRAY') || (ref($pdata[1]) 
ne 'ARRAY')) {
       warn "verify_prime: incorrect n-1 format, must have factors and a 
values\n";
       return 0;
@@ -1858,10 +1864,42 @@ sub verify_prime {
       print "primality fail: A and B not coprime\n" if $verbose;
       return 0;
     }
-    # Theorem 5, m = 1, page 624
-    {
+    if ($theorem == 7) {
+      if ($B != $t7_B) {
+        print "primality fail: T7 unfactored != unfactored\n" if $verbose;
+        return 0;
+      }
+      if ($t7_B1 < 1) {
+        print "primality fail: T7 B value < 1\n" if $verbose;
+        return 0;
+      }
+      # 1. Check $B has no factors smaller than $t7_B1
+      my $no_small_factors = 0;
+      if ($_HAVE_GMP) {
+        my @trial = Math::Prime::Util::GMP::trial_factor($B, $t7_B1);
+        $no_small_factors = (scalar @trial == 1);
+      } elsif ($B <= ''.~0) {
+        my @trial = Math::Prime::Util::PP::trial_factor($B, $t7_B1);
+        $no_small_factors = (scalar @trial == 1);
+      } else {
+        # This is slow when B1 > 1M, but with a bigint B it's faster than
+        # doing trial divisions (but much slower with native B).
+        $no_small_factors =
+            (Math::BigInt::bgcd($B, primorial(Math::BigInt->new($t7_B1))) == 
1);
+      }
+      if (!$no_small_factors) {
+        print "primality fail: T7 B has a factor smaller than B1\n" if 
$verbose;
+        return 0;
+      }
+      # 2. Add $B and $t7_a to lists so they get checked as part of (I).
+      push @prime_factors, $B;
+      push @pfas, $t7_a;
+    }
+    { # Theorem 5, m = 1, page 624;  Theorem 7, page 626
       my ($s,$r) = $B->copy->bdiv($A->copy->bmul(2));
-      my $fpart = ($A+1) * (2*$A*$A + ($r-1) * $A + 1);
+      my $fpart = ($theorem == 7)
+                ? ($A*$t7_B1+1) * (2*$A*$A + ($r-$t7_B1) * $A + 1)
+                : ($A+1) * (2*$A*$A + ($r-1) * $A + 1);
       if ($n >= $fpart) {
         print "primality fail: not enough factors\n" if $verbose;
         return 0;
@@ -1883,7 +1921,7 @@ sub verify_prime {
         return 0;
       }
     }
-    print "primality success: $n by BLS75 theorem 5\n" if $verbose > 1;
+    print "primality success: $n by BLS75 theorem $theorem\n" if $verbose > 1;
     return 1;
   }
 
@@ -2873,9 +2911,9 @@ A certificate is an array holding an C<n-cert>.  An 
C<n-cert> is one of:
          4 a^(n-1) = 1 mod n
          5 a^((n-1)/f) != 1 mod n for each factor
 
-  n,"n-1",[n-cert, ...],[a,...]
+  n,"n-1",[optional B-block],[n-cert, ...],[a,...]
        An n-1 certificate suitable for the generalized Pocklington or the
-       BLS75 (Brillhart-Lehmer-Selfridge 1975, theorem 5) test.  The
+       BLS75 (Brillhart-Lehmer-Selfridge 1975, theorem 5) n-1 test.  The
        proof is performed using BLS75 theorem 5 which requires n-1 to be
        factored up to (n/2)^1/3.  If n-1 is factored to more than
        sqrt(n), then the conditions are identical to the generalized
@@ -2892,6 +2930,11 @@ A certificate is an array holding an C<n-cert>.  An 
C<n-cert> is one of:
          5 for each pair (f,a) representing a factor n-cert and its 'a':
              - a^(n-1) = 1 mod n
              - gcd( a^((n-1)/f)-1, n ) = 1
+       If the optional B block is present, then theorem 7 will be used.
+       The B-block consists of 4 items:  "B" as an identifier, the
+       factoring limit B indicating that the unfactored portion has no
+       factors smaller than B, the unfactored amount F, and an 'a' value
+       to be tested with F as in step 5.
 
   n,"AGKM",[ec-block],[ec-block],...
        An Elliptic Curve certificate.  We are given n, the method "AGKM"
diff --git a/lib/Math/Prime/Util/PP.pm b/lib/Math/Prime/Util/PP.pm
index de34252..5ed8e7b 100644
--- a/lib/Math/Prime/Util/PP.pm
+++ b/lib/Math/Prime/Util/PP.pm
@@ -69,19 +69,25 @@ sub _validate_positive_integer {
         if ref($n) ne 'Math::BigInt' && $n =~ tr/0123456789//c;
   croak "Parameter '$n' must be >= $min" if defined $min && $n < $min;
   croak "Parameter '$n' must be <= $max" if defined $max && $n > $max;
-  if ($n <= ~0) {
-    $_[0] = $_[0]->as_number() if ref($_[0]) eq 'Math::BigFloat';
-    $_[0] = int($_[0]->bstr) if ref($_[0]) eq 'Math::BigInt';
-  } elsif (ref($n) ne 'Math::BigInt') {
-    croak "Parameter '$n' outside of integer range" if !defined 
$bigint::VERSION;
-    $_[0] = Math::BigInt->new("$n"); # Make $n a proper bigint object
-    $_[0]->upgrade(undef) if $_[0]->upgrade();  # Stop BigFloat upgrade
+  if (ref($_[0])) {
+    $_[0] = Math::BigInt->new("$_[0]") unless ref($_[0]) eq 'Math::BigInt';
+    # Stupid workaround for Math::BigInt::GMP RT # 71548
+    if ($_[0]->bacmp(''.~0) <= 0) {
+      $_[0] = int($_[0]->bstr);
+      croak "Didn't convert!" if ref($_[0]);
+    } else {
+      $_[0]->upgrade(undef) if $_[0]->upgrade();  # Stop BigFloat upgrade
+    }
   } else {
-    $_[0]->upgrade(undef) if $_[0]->upgrade();  # Stop BigFloat upgrade
+    if ($n > ~0) {
+      croak "Parameter '$n' outside of integer range" if !defined 
$bigint::VERSION;
+      $_[0] = Math::BigInt->new("$n"); # Make $n a proper bigint object
+      $_[0]->upgrade(undef) if $_[0]->upgrade();  # Stop BigFloat upgrade
+    }
   }
   # One of these will be true:
-  #     1) $n <= max and $n is not a bigint
-  #     2) $n  > max and $n is a bigint
+  #     1) $n <= ~0 and $n is not a bigint
+  #     2) $n  > ~0 and $n is a bigint
   1;
 }
 
@@ -1115,21 +1121,32 @@ sub _basic_factor {
 }
 
 sub trial_factor {
-  my($n) = @_;
+  my($n, $maxlim) = @_;
   _validate_positive_integer($n);
+  $maxlim = $n unless defined $maxlim && _validate_positive_integer($maxlim);
 
-  my @factors = _basic_factor($n);
+  # Don't use _basic factor here -- they want a trial forced.
+  #my @factors = _basic_factor($n);
+  return ($n) if $n < 4;
+  my @factors;
+  while ( !($n % 2) ) { push @factors, 2;  $n = int($n / 2); }
+  while ( !($n % 3) ) { push @factors, 3;  $n = int($n / 3); }
+  while ( !($n % 5) ) { push @factors, 5;  $n = int($n / 5); }
+  $n = int($n->bstr) if ref($n) eq 'Math::BigInt' && $n <= ''.~0;
   return @factors if $n < 4;
 
   my $limit = int( sqrt($n) + 0.001);
+  $limit = $maxlim if $limit > $maxlim;
   my $f = 7;
   SEARCH: while ($f <= $limit) {
     foreach my $finc (4, 2, 4, 2, 4, 6, 2, 6) {
       if ( (($n % $f) == 0) && ($f <= $limit) ) {
         do { push @factors, $f; $n = int($n/$f); } while (($n % $f) == 0);
-        $n = int($n->bstr) if ref($n) eq 'Math::BigInt' && $n <= ~0;
-        last SEARCH if $n == 1 || Math::Prime::Util::is_prob_prime($n);
+        $n = int($n->bstr) if ref($n) eq 'Math::BigInt' && $n <= ''.~0;
+        #last SEARCH if $n == 1 || Math::Prime::Util::is_prob_prime($n);
+        last SEARCH if $n == 1;
         $limit = int( sqrt($n) + 0.001);
+        $limit = $maxlim if $limit > $maxlim;
       }
       $f += $finc;
     }
@@ -1875,22 +1892,15 @@ sub primality_proof_bls75 {
   my $B = $nm1->copy;         # unfactored part
   my @factors = (2);
   croak "BLS75 error: n-1 not even" unless $nm1->is_even();
+  my $trial_B = 20000;
   {
     while ($B->is_even) { $B /= 2; $A *= 2; }
-    my $tlim = $_primes_small[-1];
-    if ($B > $tlim*$tlim) {
-      my @small_primes = @_primes_small[2 .. $#_primes_small];
-      foreach my $f (@small_primes) {
-        if (($B % $f) == 0) {
-          push @factors, $f;
-          do { $B /= $f;  $A *= $f; } while (($B % $f) == 0);
-          last if $B <= $tlim*$tlim;
-        }
-      }
-    }
-    if ($B <= $tlim*$tlim) {
-      push @factors, factor($B);
-      $A *= $B;  $B /= $B;
+    my @tf = trial_factor($B, $trial_B);
+    pop @tf if $tf[-1] > $trial_B;
+    foreach my $f (@tf) {
+      next if $f == $factors[-1];
+      push @factors, $f;
+      do { $B /= $f;  $A *= $f; } while (($B % $f) == 0);
     }
   }
   my @nstack;
@@ -1903,15 +1913,14 @@ sub primality_proof_bls75 {
   } else {
     push @nstack, $B;
   }
-  my $using_theorem_7 = 0;
+  my $theorem = 5;
   while (@nstack) {
     my ($s,$r) = $B->copy->bdiv($A->copy->bmul(2));
     my $fpart = ($A+1) * (2*$A*$A + ($r-1) * $A + 1);
     last if $n < $fpart;
     # Theorem 7....
-    # my $tlim = $_primes_small[-1];
-    # $fpart = ($A*$tlim+1) * (2*$A*$A + ($r-$tlim) * $A + 1);
-    # if ($n < $fpart) { $using_theorem_7 = 1; last; }
+    $fpart = ($A*$trial_B+1) * (2*$A*$A + ($r-$trial_B) * $A + 1);
+    if ($n < $fpart) { $theorem = 7; last; }
 
     my $m = pop @nstack;
     # Don't use bignum if it has gotten small enough.
@@ -1948,7 +1957,9 @@ sub primality_proof_bls75 {
   }
   # Did we factor enough?
   my ($s,$r) = $B->copy->bdiv($A->copy->bmul(2));
-  my $fpart = ($A+1) * (2*$A*$A + ($r-1) * $A + 1);
+  my $fpart = ($theorem == 5)
+            ? ($A+1) * (2*$A*$A + ($r-1) * $A + 1)
+            : ($A*$trial_B+1) * (2*$A*$A + ($r-$trial_B) * $A + 1);
   return (1,[]) if $n >= $fpart;
   # Check we didn't mess up
   croak "BLS75 error: $A * $B != $nm1" unless $A*$B == $nm1;
@@ -1964,7 +1975,7 @@ sub primality_proof_bls75 {
   foreach my $f (@factors) {
     my $success = 0;
     foreach my $a (2 .. 10000) {
-      my $ap = Math::BigInt->new("$a");
+      my $ap = Math::BigInt->new($a);
       next unless $ap->copy->bmodpow($nm1, $n) == 1;
       next unless Math::BigInt::bgcd($ap->copy->bmodpow($nm1/$f, $n)->bsub(1), 
$n) == 1;
       push @as, $a;
@@ -1979,8 +1990,19 @@ sub primality_proof_bls75 {
     }
     push @fac_proofs, (scalar @$fproof == 1) ? $fproof->[0] : $fproof;
   }
-  my @proof = ($n, "n-1", [@fac_proofs], [@as]);
-  return (2, [@proof]);
+  if ($theorem == 5) {
+    return (2, [$n, "n-1", [@fac_proofs], [@as]]);
+  } else {
+    my $t7a = 0;
+    my $f = $B;
+    foreach my $a (2 .. 10000) {
+      my $ap = Math::BigInt->new($a);
+      next unless $ap->copy->bmodpow($nm1, $n) == 1;
+      next unless Math::BigInt::bgcd($ap->copy->bmodpow($nm1/$f, $n)->bsub(1), 
$n) == 1;
+      return (2, [$n, "n-1", ["B", $trial_B, $B, $a], [@fac_proofs], [@as]]);
+    }
+  }
+  return @composite;
 }
 
 
diff --git a/xt/primality-proofs.pl b/xt/primality-proofs.pl
index 580be8d..4c0cf7b 100644
--- a/xt/primality-proofs.pl
+++ b/xt/primality-proofs.pl
@@ -6,7 +6,10 @@ use Math::BigInt lib=>"GMP";
 #use Crypt::Primes 'maurer';
 use Math::Pari qw/isprime/;
 use Crypt::Random 'makerandom';
-use Data::Dump 'dump';
+use Data::Dump::Filtered 'dump_filtered';
+my $bifilter = sub { my($ctx, $n) = @_;
+                     return {dump=>"$n"} if ref($n) eq "Math::BigInt";
+                     undef; };
 
 $|++;
 my $num = 71;
@@ -56,7 +59,7 @@ foreach my $certn (@certs) {
   print proof_mark($certn->[1]);
   next if $v;
   print "\n\n$certn->[0] didn't verify!\n\n";
-  print dump($certn->[1]);
+  print dump_filtered($certn->[1], $bifilter);
   die;
 }
 print "\n";
@@ -64,8 +67,8 @@ print "\n";
 sub proof_mark {
   my $cert = shift;
   my $type = (scalar @$cert == 1) ? "bpsw" : $cert->[1];
-  if (!defined $type) { die "\nNo cert:\n\n", dump($cert); }
-  if    ($type =~ /n-1/i)       { return '1'; }
+  if (!defined $type) { die "\nNo cert:\n\n", dump_filtered($cert, $bifilter); 
}
+  if    ($type =~ /n-1/i)       { return ($cert->[2]->[0] eq 'B') ? '7' : '5'; 
}
   elsif ($type =~ /bpsw/i)      { return '.'; }
   elsif ($type =~ /ecpp|agkm/i) { return 'E'; }
   return '?';

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-perl/packages/libmath-prime-util-perl.git

_______________________________________________
Pkg-perl-cvs-commits mailing list
Pkg-perl-cvs-commits@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-perl-cvs-commits

Reply via email to