[libmath-prime-util-perl] 26/35: Tiny efficiency for Mertens
Partha P. Mukherjee
ppm-guest at moszumanska.debian.org
Thu May 21 18:50:04 UTC 2015
This is an automated email from the git hooks/post-receive script.
ppm-guest pushed a commit to annotated tag v0.33
in repository libmath-prime-util-perl.
commit 672bc12ec6ae0ef3aae7a0d715009f4ecc8b9447
Author: Dana Jacobsen <dana at acm.org>
Date: Mon Nov 11 18:45:54 2013 -0800
Tiny efficiency for Mertens
---
t/19-moebius.t | 2 +-
util.c | 24 +++++++++++++++---------
2 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/t/19-moebius.t b/t/19-moebius.t
index 54a529e..772ceb2 100644
--- a/t/19-moebius.t
+++ b/t/19-moebius.t
@@ -71,7 +71,7 @@ if ($extra && $use64) {
2**23 => -10,
10**8 => 1928,
- 10**9 => -222,
+# 10**9 => -222,
# 1*10**10 => -33722, # From Deleglise and Rivat
# 2*10**10 => -48723, # Too slow with current method
);
diff --git a/util.c b/util.c
index 10f3914..f31e951 100644
--- a/util.c
+++ b/util.c
@@ -837,7 +837,7 @@ signed char* _moebius_range(UV lo, UV hi)
UV* _totient_range(UV lo, UV hi) {
UV* totients;
- UV i, hidiv2;
+ UV i;
if (hi < lo) croak("_totient_range error hi %lu < lo %lu\n", hi, lo);
New(0, totients, hi-lo+1, UV);
if (totients == 0)
@@ -882,20 +882,24 @@ IV _XS_mertens(UV n) {
}
return -sum;
#else
- /* See Deléglise and Rivat (1996) for a segmented n^1/3 algorithm.
- * This implementation uses their lemma 2.1 directly, so is n^1/2.
+ /* See Deléglise and Rivat (1996) for O(n^2/3 log(log(n))^1/3) algorithm.
+ * This implementation uses their lemma 2.1 directly, so is ~ O(n).
+ * In serial it is quite a bit faster than segmented summation of mu
+ * ranges, though the latter seems to be a favored method for GPUs.
*/
- UV u, i, m, nmk;
+ UV u, i, m, nmk, maxmu;
signed char* mu;
IV* M;
IV sum;
if (n <= 1) return n;
u = isqrt(n);
- mu = _moebius_range(0, u);
- New(0, M, u+1, IV);
+ maxmu = (n/(u+1)); /* maxmu lets us handle u < sqrt(n) */
+ if (maxmu < u) maxmu = u;
+ mu = _moebius_range(0, maxmu);
+ New(0, M, maxmu+1, IV);
M[0] = 0;
- for (i = 1; i <= u; i++)
+ for (i = 1; i <= maxmu; i++)
M[i] = M[i-1] + mu[i];
sum = M[u];
for (m = 1; m <= u; m++) {
@@ -905,9 +909,11 @@ IV _XS_mertens(UV n) {
UV last_nmk = n/(m*lower);
UV this_k = 0;
UV next_k = n/(m*1);
- for (nmk = 1; nmk <= last_nmk; nmk++) {
+ UV nmkm = m * 2;
+ for (nmk = 1; nmk <= last_nmk; nmk++, nmkm += m) {
this_k = next_k;
- next_k = n/(m*(nmk+1));
+ next_k = n/nmkm;
+ /* if (nmk > maxmu) croak("n = %lu m = %lu u/m = %lu n/m = %lu nmk %lu\n", n, m, u/m, n/m, nmk); */
inner_sum += M[nmk] * (this_k - next_k);
}
sum -= mu[m] * inner_sum;
--
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