[libmath-prime-util-perl] 14/55: Improved code for mont_prod64
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 9733e53ae29ad9b43188e38781ae9750c42b6998
Author: Dana Jacobsen <dana at acm.org>
Date: Thu May 1 14:24:44 2014 -0700
Improved code for mont_prod64
---
Changes | 3 ++-
primality.c | 32 +++++++++++++++++++++++++++-----
2 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/Changes b/Changes
index b78ae51..b9285c0 100644
--- a/Changes
+++ b/Changes
@@ -9,7 +9,8 @@ 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.
+ substantial (20-40%) speedup for primality testing in range 2^32 to 2^64.
+ This affects functions like next_prime, prev_prime, etc.
- Small improvement to twin_prime_count_approx and nth_twin_prime_approx.
diff --git a/primality.c b/primality.c
index d6f3962..02b0d40 100644
--- a/primality.c
+++ b/primality.c
@@ -46,16 +46,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
static INLINE uint64_t mont_prod64(uint64_t a, uint64_t b, uint64_t n, uint64_t npi)
{
uint64_t t_hi, t_lo, m, mn_hi, mn_lo, u;
- int carry;
/* t_hi * 2^64 + t_lo = a*b */
asm("mulq %3" : "=a"(t_lo), "=d"(t_hi) : "a"(a), "rm"(b));
m = t_lo * npi;
/* mn_hi * 2^64 + mn_lo = m*n */
asm("mulq %3" : "=a"(mn_lo), "=d"(mn_hi) : "a"(m), "rm"(n));
- carry = t_lo + mn_lo < t_lo ? 1 : 0;
- u = t_hi + mn_hi + carry;
- if (u < t_hi) return u-n;
- return u >= n ? u-n : u;
+ u = t_hi + mn_hi;
+ if (t_lo + mn_lo < t_lo) u++;
+ return (u < t_hi || u >= n) ? u-n : u;
}
#define mont_square64(a, n, npi) mont_prod64(a, a, n, npi)
static INLINE UV mont_powmod64(uint64_t a, uint64_t k, uint64_t one, uint64_t n, uint64_t npi)
@@ -72,6 +70,7 @@ static INLINE UV mont_powmod64(uint64_t a, uint64_t k, uint64_t one, uint64_t n,
* Divisionless Operations", Computer Journal (1994) 37 (3): 219-222, Proc 5 */
static INLINE uint64_t modular_inverse64(const uint64_t a)
{
+#if 0
uint64_t S = 1, J = 0;
int i;
for (i = 0; i < 64; i++) {
@@ -81,6 +80,29 @@ static INLINE uint64_t modular_inverse64(const uint64_t a)
}
S >>= 1;
}
+#else
+ /* 2 at a time. */
+ uint64_t S = 1, J = 0;
+ const uint64_t a1p = (a>>1)+1, a2 = a>>2, a2p = a2+1;
+ int i;
+ if (a & 2) {
+ const uint64_t tab[4] = { 0, a2p, a1p, a1p+a2p };
+ for (i = 0; i < 32; i++) {
+ uint64_t S2 = S >> 2;
+ int index = S & 3;
+ J |= (uint64_t)index << (2 * i);
+ S = S2 + tab[index];
+ }
+ } else {
+ const uint64_t tab[4] = { 0, a1p+a2, a1p, a2p };
+ for (i = 0; i < 32; i++) {
+ uint64_t S2 = S >> 2;
+ int index = S & 3;
+ J |= (uint64_t)((4-index)&3) << (2 * i);
+ S = S2 + tab[index];
+ }
+ }
+#endif
return J;
}
static INLINE uint64_t compute_modn64(const uint64_t n)
--
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