[libmath-prime-util-perl] 15/55: Use 64-bit Montgomery math in primality tests even for 32-bit inputs

Partha P. Mukherjee ppm-guest at moszumanska.debian.org
Thu May 21 18:53:40 UTC 2015


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

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

commit 63471f6b339b55d05784d0a65c738352cf6530d5
Author: Dana Jacobsen <dana at acm.org>
Date:   Thu May 1 15:02:55 2014 -0700

    Use 64-bit Montgomery math in primality tests even for 32-bit inputs
---
 Changes     |  7 ++++---
 primality.c | 36 ++++++++++++++++++------------------
 2 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/Changes b/Changes
index b9285c0..d0017d3 100644
--- a/Changes
+++ b/Changes
@@ -8,9 +8,10 @@ Revision history for Perl module Math::Prime::Util
 
     [FUNCTIONALITY AND PERFORMANCE]
 
-    - New modular inverse from W. Izykowski, from Arazi (1994).  This is a
-      substantial (20-40%) speedup for primality testing in range 2^32 to 2^64.
-      This affects functions like next_prime, prev_prime, etc.
+    - Big speedup for primality testing in range ~2^25 to 2^64, which also
+      affects functions like next_prime, prev_prime, etc.  This is due to two
+      changes in the Montgomery math section -- an improvement to mont_prod64
+      and using a new modular inverse from W. Izykowski based on Arazi (1994).
 
     - Small improvement to twin_prime_count_approx and nth_twin_prime_approx.
 
diff --git a/primality.c b/primality.c
index 02b0d40..5f4a633 100644
--- a/primality.c
+++ b/primality.c
@@ -212,10 +212,8 @@ int _XS_miller_rabin(UV const n, const UV *bases, int nbases)
   if ((n & 1) == 0) return 0;
 
 #if USE_MONT_PRIMALITY
-  if (n >= UVCONST(4294967295))
-    return monty_mr64((uint64_t)n, bases, nbases);
-#endif
-
+  return monty_mr64((uint64_t)n, bases, nbases);
+#else
   while (!(d&1)) {  s++;  d >>= 1;  }
 
   for (b = 0; b < nbases; b++) {
@@ -238,6 +236,7 @@ int _XS_miller_rabin(UV const n, const UV *bases, int nbases)
     if (r >= s)  return 0;
   }
   return 1;
+#endif
 }
 
 int _XS_BPSW(UV const n)
@@ -249,10 +248,7 @@ int _XS_BPSW(UV const n)
   return    _XS_miller_rabin(n, mr_bases_const2, 1)
          && _XS_is_almost_extra_strong_lucas_pseudoprime(n,1);
 #else
-  if (n < UVCONST(4294967295)) {
-    return    _XS_miller_rabin(n, mr_bases_const2, 1)
-           && _XS_is_almost_extra_strong_lucas_pseudoprime(n,1);
-  } else {
+  {
     const uint64_t npi = modular_inverse64(n);
     const uint64_t montr = compute_modn64(n);
     const uint64_t mont2 = compute_2_65_mod_n(n, montr);
@@ -458,7 +454,7 @@ int _XS_is_lucas_pseudoprime(UV n, int strength)
     while ( (d & 1) == 0 ) {  s++;  d >>= 1; }
 
 #if USE_MONT_PRIMALITY
-  if (n > UVCONST(4294967295)) {
+  {
     const uint64_t npi = modular_inverse64(n);
     const uint64_t mont1 = compute_modn64(n);
     const uint64_t mont2 = compute_2_65_mod_n(n, mont1);
@@ -541,8 +537,7 @@ int _XS_is_lucas_pseudoprime(UV n, int strength)
     }
     return 0;
   }
-#endif
-
+#else
   lucas_seq(&U, &V, &Qk, n, P, Q, d);
 
   if (strength == 0) {
@@ -573,14 +568,17 @@ int _XS_is_lucas_pseudoprime(UV n, int strength)
     }
   }
   return 0;
+#endif
 }
 
 /* A generalization of Pari's shortcut to the extra-strong Lucas test.
+ *
+ * This only calculates and tests V, which means less work, but it does result
+ * in a few more pseudoprimes than the full extra-strong test.
+ *
  * I've added a gcd check at the top, which needs to be done and also results
  * in fewer pseudoprimes.  Pari always does trial division to 100 first so
- * is unlikely to come up there.  This only calculate V, which can be done
- * faster, but that means we have more pseudoprimes than the standard
- * extra-strong test.
+ * is unlikely to come up there.
  *
  * increment:  1 for Baillie OEIS, 2 for Pari.
  *
@@ -617,7 +615,7 @@ int _XS_is_almost_extra_strong_lucas_pseudoprime(UV n, UV increment)
   { UV v = d; b = 0; while (v >>= 1) b++; }
 
 #if USE_MONT_PRIMALITY
-  if (n > UVCONST(4294967295)) {
+  {
     const uint64_t npi = modular_inverse64(n);
     const uint64_t montr = compute_modn64(n);
     const uint64_t mont2 = compute_2_65_mod_n(n, montr);
@@ -646,7 +644,7 @@ int _XS_is_almost_extra_strong_lucas_pseudoprime(UV n, UV increment)
     }
     return 0;
   }
-#endif
+#else
   W = mulsubmod(P, P, 2, n);
   V = P;
   while (b--) {
@@ -669,6 +667,7 @@ int _XS_is_almost_extra_strong_lucas_pseudoprime(UV n, UV increment)
       return 0;
   }
   return 0;
+#endif
 }
 
 /*
@@ -702,7 +701,7 @@ int _XS_is_frobenius_underwood_pseudoprime(UV n)
   { UV v = np1; len = 1;  while (v >>= 1) len++; }
 
 #if USE_MONT_PRIMALITY
-  if (n > UVCONST(4294967295)) {
+  {
     const uint64_t npi = modular_inverse64(n);
     const uint64_t mont1 = compute_modn64(n);
     const uint64_t mont2 = compute_2_65_mod_n(n, mont1);
@@ -740,7 +739,7 @@ int _XS_is_frobenius_underwood_pseudoprime(UV n)
     }
     return (a == 0 && b == result);
   }
-#endif
+#else
   a = 1;
   b = 2;
 
@@ -775,6 +774,7 @@ int _XS_is_frobenius_underwood_pseudoprime(UV n)
   if (a == 0 && b == result)
     return 1;
   return 0;
+#endif
 }
 
 

-- 
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