[libmath-prime-util-perl] 38/43: Add slightly faster ranged totient for start = 0
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 6e9b8a26a2afc03bfc880846288cd5543b5c62e2
Author: Dana Jacobsen <dana at acm.org>
Date: Fri Apr 18 15:16:29 2014 -0700
Add slightly faster ranged totient for start = 0
---
Changes | 2 ++
util.c | 37 ++++++++++++++++++++++++++++++++++++-
xt/totient-range.pl | 5 +++--
3 files changed, 41 insertions(+), 3 deletions(-)
diff --git a/Changes b/Changes
index 45c1912..96765af 100644
--- a/Changes
+++ b/Changes
@@ -26,6 +26,8 @@ Revision history for Perl module Math::Prime::Util
- Fix legendre_phi when given tiny x and large a (odd test case).
Some speedups for huge a, from R. Andrew Ohana.
+ - Ranged totient is slightly faster with start of 0.
+
0.39 2014-03-01
diff --git a/util.c b/util.c
index f246c34..f9e8879 100644
--- a/util.c
+++ b/util.c
@@ -583,6 +583,7 @@ UV twin_prime_count_approx(UV n)
/* Best would be another estimate for n < ~ 5000 */
if (n < 2000) return twin_prime_count(3,n);
{
+ /* Sebah and Gourdon 2002 */
const long double two_C2 = 1.32032363169373914785562422L;
const long double two_over_log_two = 2.8853900817779268147198494L;
long double ln = (long double) n;
@@ -1064,12 +1065,46 @@ UV* _totient_range(UV lo, UV hi) {
New(0, totients, hi-lo+1, UV);
/* Do via factoring if very small or if we have a small range */
- if (hi < 100 || hi/(hi-lo+1) > 1000) {
+ if (hi < 100 || (hi-lo) < 10 || hi/(hi-lo+1) > 1000) {
for (i = lo; i <= hi; i++)
totients[i-lo] = totient(i);
return totients;
}
+ /* If doing a full sieve, do it monolithic. More aux memory, but 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))
+ : (hi/loghi) * (1.0+1.0/loghi+2.51/(loghi*loghi));
+ 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);
+ }
+ }
+ }
+ Safefree(setb);
+ Safefree(prime);
+ totients[1] = 1;
+ totients[0] = 0;
+ return totients;
+ }
+
for (i = lo; i <= hi; i++) {
UV v = i;
if (i % 2 == 0) v -= v/2;
diff --git a/xt/totient-range.pl b/xt/totient-range.pl
index 6371a6c..035973b 100755
--- a/xt/totient-range.pl
+++ b/xt/totient-range.pl
@@ -14,9 +14,10 @@ print "...";
unshift @phi, 0;
print "...done\n";
+print "Running non-stop random tests. Break when desired.\n";
while (1) {
- my $beg = 1 + int(rand($limit));
- my $end = 1 + int(rand($limit));
+ my $beg = 0 + int(rand($limit));
+ my $end = 0 + int(rand($limit));
($beg,$end) = ($end,$beg) if $beg > $end;
# Does range return the same values?
--
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