[libmath-prime-util-perl] 40/43: More optimizations for euler_phi(0, n)
Partha P. Mukherjee
ppm-guest at moszumanska.debian.org
Thu May 21 18:53:09 UTC 2015
This is an automated email from the git hooks/post-receive script.
ppm-guest pushed a commit to annotated tag v0.40
in repository libmath-prime-util-perl.
commit 7f6602eed22e6366958ebb4dfd094422fc826cec
Author: Dana Jacobsen <dana at acm.org>
Date: Mon Apr 21 11:58:02 2014 -0700
More optimizations for euler_phi(0,n)
---
Changes | 2 +-
TODO | 3 ++-
util.c | 39 +++++++++++++++++++++++----------------
3 files changed, 26 insertions(+), 18 deletions(-)
diff --git a/Changes b/Changes
index 3b12038..09ee7da 100644
--- a/Changes
+++ b/Changes
@@ -1,6 +1,6 @@
Revision history for Perl module Math::Prime::Util
-0.40 2014-03
+0.40 2014-04-21
[ADDED]
diff --git a/TODO b/TODO
index ae9e8e2..f8132c7 100644
--- a/TODO
+++ b/TODO
@@ -70,4 +70,5 @@
- znlog better implementation
- We don't use legendre_phi for other functions any more, but it'd be nice
- to speed it up using some ideas from the Ohana 2011 SAGE code.
+ to speed it up using some ideas from the Ohana 2011 SAGE branch. For example
+ (10**13,10**5) takes 2.5x longer, albeit with 6x less memory.
diff --git a/util.c b/util.c
index f9e8879..446e2fa 100644
--- a/util.c
+++ b/util.c
@@ -1071,10 +1071,9 @@ UV* _totient_range(UV lo, UV hi) {
return totients;
}
- /* If doing a full sieve, do it monolithic. More aux memory, but faster. */
+ /* If doing a full sieve, do it monolithic. Faster. */
if (lo == 0) {
UV* prime;
- char* setb;
double loghi = log(hi);
UV max_index = (hi < 67) ? 18
: (hi < 355991) ? 15+(hi/(loghi-1.09))
@@ -1082,24 +1081,32 @@ UV* _totient_range(UV lo, UV hi) {
UV j, index, nprimes = 0;
New(0, prime, max_index, UV); /* could use prime_count_upper(hi) */
- Newz(0, setb, (hi+1+7)/8, char);
- for (i = 2; i <= hi; i++) {
- if ( (setb[i/8] & (1 << i%8)) == 0 ) {
- totients[i] = i-1;
- prime[nprimes++] = i;
- }
- for (j=0, index=2*i; j < nprimes && index <= hi; index = i*prime[++j]) {
- setb[index/8] |= 1 << (index%8);
- if (i % prime[j] == 0) {
- totients[index] = totients[i]*prime[j];
- break;
- } else {
- totients[index] = totients[i]*(prime[j]-1);
+ memset(totients, 0, (hi-lo+1) * sizeof(UV));
+ for (i = 2; i <= hi/2; i++) {
+ index = 2*i;
+ if ( !(i&1) ) {
+ if (i == 2) { totients[2] = 1; prime[nprimes++] = 2; }
+ totients[index] = totients[i]*2;
+ } else {
+ if (totients[i] == 0) {
+ totients[i] = i-1;
+ prime[nprimes++] = i;
+ }
+ for (j=0; j < nprimes && index <= hi; index = i*prime[++j]) {
+ if (i % prime[j] == 0) {
+ totients[index] = totients[i]*prime[j];
+ break;
+ } else {
+ totients[index] = totients[i]*(prime[j]-1);
+ }
}
}
}
- Safefree(setb);
Safefree(prime);
+ /* All totient values have been filled in except the primes. Mark them. */
+ for (i = ((hi/2) + 1) | 1; i <= hi; i += 2)
+ if (totients[i] == 0)
+ totients[i] = i-1;
totients[1] = 1;
totients[0] = 0;
return totients;
--
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