[libmath-prime-util-perl] 12/55: New monty modinverse, nice primality speedup
Partha P. Mukherjee
ppm-guest at moszumanska.debian.org
Thu May 21 18:53:39 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 59d0b4ff22884dc918f9099860496815f3bde669
Author: Dana Jacobsen <dana at acm.org>
Date: Wed Apr 30 11:37:02 2014 -0700
New monty modinverse, nice primality speedup
---
Changes | 3 +++
primality.c | 40 ++++++++++++++++------------------------
2 files changed, 19 insertions(+), 24 deletions(-)
diff --git a/Changes b/Changes
index 57a5773..b78ae51 100644
--- a/Changes
+++ b/Changes
@@ -8,6 +8,9 @@ Revision history for Perl module Math::Prime::Util
[FUNCTIONALITY AND PERFORMANCE]
+ - New modular inverse from W. Izykowski, from Arazi (1994). This is a
+ substantial (10-20%) speedup for 64-bit primality testing.
+
- Small improvement to twin_prime_count_approx and nth_twin_prime_approx.
- Better AKS testing in xt/primality-aks.pl.
diff --git a/primality.c b/primality.c
index 38d3e7f..d6f3962 100644
--- a/primality.c
+++ b/primality.c
@@ -18,7 +18,7 @@ static const UV mr_bases_const2[1] = {2};
Code inside USE_MONT_PRIMALITY is Montgomery math and efficient M-R from
Wojciech Izykowski. See: https://github.com/wizykowski/miller-rabin
-Copyright (c) 2013, Wojciech Izykowski
+Copyright (c) 2013-2014, Wojciech Izykowski
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -68,28 +68,20 @@ static INLINE UV mont_powmod64(uint64_t a, uint64_t k, uint64_t one, uint64_t n,
}
return t;
}
+/* Returns -a^-1 mod 2^64. From B. Arazi "On Primality Testing Using Purely
+ * Divisionless Operations", Computer Journal (1994) 37 (3): 219-222, Proc 5 */
static INLINE uint64_t modular_inverse64(const uint64_t a)
{
- uint64_t u,x,w,z,q;
-
- x = 1; z = a;
-
- q = (-z)/z + 1; /* = 2^64 / z */
- u = - q; /* = -q * x */
- w = - q * z; /* = b - q * z = 2^64 - q * z */
-
- /* after first iteration all variables are 64-bit */
-
- while (w) {
- if (w < z) {
- q = u; u = x; x = q; /* swap(u, x) */
- q = w; w = z; z = q; /* swap(w, z) */
+ uint64_t S = 1, J = 0;
+ int i;
+ for (i = 0; i < 64; i++) {
+ if (S & 1) {
+ J |= (1ULL << i);
+ S += a;
}
- q = w / z;
- u -= q * x;
- w -= q * z;
+ S >>= 1;
}
- return x;
+ return J;
}
static INLINE uint64_t compute_modn64(const uint64_t n)
{
@@ -118,7 +110,7 @@ static INLINE uint64_t compute_2_65_mod_n(const uint64_t n, const uint64_t modn)
static int monty_mr64(const uint64_t n, const UV* bases, int cnt)
{
int i, j, t;
- const uint64_t npi = modular_inverse64(-((int64_t)n));
+ const uint64_t npi = modular_inverse64(n);
const uint64_t r = compute_modn64(n);
uint64_t u = n - 1;
const uint64_t nr = n - r;
@@ -239,7 +231,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 {
- const uint64_t npi = modular_inverse64(-((int64_t)n));
+ 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);
uint64_t u = n-1;
@@ -445,7 +437,7 @@ int _XS_is_lucas_pseudoprime(UV n, int strength)
#if USE_MONT_PRIMALITY
if (n > UVCONST(4294967295)) {
- const uint64_t npi = modular_inverse64(-((int64_t)n));
+ 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);
const uint64_t montP = (P == 1) ? mont1
@@ -604,7 +596,7 @@ int _XS_is_almost_extra_strong_lucas_pseudoprime(UV n, UV increment)
#if USE_MONT_PRIMALITY
if (n > UVCONST(4294967295)) {
- const uint64_t npi = modular_inverse64(-((int64_t)n));
+ 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);
const uint64_t montP = compute_a_times_2_64_mod_n(P, n, montr);
@@ -689,7 +681,7 @@ int _XS_is_frobenius_underwood_pseudoprime(UV n)
#if USE_MONT_PRIMALITY
if (n > UVCONST(4294967295)) {
- const uint64_t npi = modular_inverse64(-((int64_t)n));
+ 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);
const uint64_t mont5 = compute_a_times_2_64_mod_n(5, n, mont1);
--
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