[libmath-prime-util-perl] 01/13: Fix segmented euler_phi

Partha P. Mukherjee ppm-guest at moszumanska.debian.org
Thu May 21 18:47:41 UTC 2015


This is an automated email from the git hooks/post-receive script.

ppm-guest pushed a commit to annotated tag v0.24
in repository libmath-prime-util-perl.

commit 6390df317eea8be534707656939a4b335545d904
Author: Dana Jacobsen <dana at acm.org>
Date:   Tue Mar 5 16:00:30 2013 -0800

    Fix segmented euler_phi
---
 Changes             |  4 ++++
 MANIFEST            |  1 +
 t/13-primecount.t   |  3 +++
 t/19-moebius.t      |  3 ++-
 util.c              | 10 ++++++----
 xt/totient-range.pl | 31 +++++++++++++++++++++++++++++++
 6 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/Changes b/Changes
index db49369..8b20caf 100644
--- a/Changes
+++ b/Changes
@@ -1,5 +1,9 @@
 Revision history for Perl extension Math::Prime::Util.
 
+0.24  5 March 2013
+
+    - euler_phi on a range wasn't working right with some ranges.
+
 0.23  5 March 2013
 
     - Replace XS Zeta for x > 5 with series from Cephes.  It is 1 eps more
diff --git a/MANIFEST b/MANIFEST
index 8506ef8..8df46f1 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -86,6 +86,7 @@ t/90-release-perlcritic.t
 t/91-release-pod-syntax.t
 t/92-release-pod-coverage.t
 xt/moebius-mertens.pl
+xt/totient-range.pl
 xt/primality-small.pl
 xt/primality-aks.pl
 xt/factor-holf.pl
diff --git a/t/13-primecount.t b/t/13-primecount.t
index 9448451..09fe825 100644
--- a/t/13-primecount.t
+++ b/t/13-primecount.t
@@ -62,6 +62,9 @@ my %intervals = (
   "24689 to 7973249" => 535368,
   "1e10 +2**16" => 2821,
   "17 to 13"    => 0,
+  "0 to 1"      => 0,
+  "0 to 2"      => 1,
+  "1 to 3"      => 2,
   "3 to 17"     => 6,
   "4 to 17"     => 5,
   "4 to 16"     => 4,
diff --git a/t/19-moebius.t b/t/19-moebius.t
index 9b976cd..5353ed8 100644
--- a/t/19-moebius.t
+++ b/t/19-moebius.t
@@ -161,7 +161,7 @@ plan tests => 0 + 1
                 + 3*scalar(keys %mertens)
                 + 1*scalar(keys %big_mertens)
                 + 2 # Small Phi
-                + 6 + scalar(keys %totients)
+                + 7 + scalar(keys %totients)
                 + scalar(keys %jordan_totients)
                 + 2  # Dedekind psi calculated two ways
                 + 1  # Calculate J5 two different ways
@@ -210,6 +210,7 @@ is_deeply( [euler_phi(0,1)], [0,1],   "euler_phi 0-1" );
 is_deeply( [euler_phi(1,2)], [1,1],   "euler_phi 1-2" );
 is_deeply( [euler_phi(1,3)], [1,1,2], "euler_phi 1-3" );
 is_deeply( [euler_phi(2,3)], [1,2],   "euler_phi 2-3" );
+is_deeply( [euler_phi(10,20)], [4,10,4,12,6,8,8,16,6,18,8], "euler_phi 10-20" );
 
 ###### Jordan Totient
 while (my($k, $tref) = each (%jordan_totients)) {
diff --git a/util.c b/util.c
index 1da3426..368fc24 100644
--- a/util.c
+++ b/util.c
@@ -652,6 +652,8 @@ UV _XS_nth_prime(UV n)
 /* Return an IV array with lo-hi+1 elements.  mu[k-lo] = µ(k) for k = lo .. hi.
  * It is the callers responsibility to call Safefree on the result. */
 #define PGTLO(p,lo)  ((p) >= lo) ? (p) : ((p)*(lo/(p)) + ((lo%(p))?(p):0))
+#define P2GTLO(pinit, p, lo) \
+   ((pinit) >= lo) ? (pinit) : ((p)*(lo/(p)) + ((lo%(p))?(p):0))
 char* _moebius_range(UV lo, UV hi)
 {
   char* mu;
@@ -756,16 +758,16 @@ UV* _totient_range(UV lo, UV hi) {
     croak("Could not get memory for %"UVuf" totients\n", hi);
   for (i = lo; i <= hi; i++)
     totients[i-lo] = i;
-  for (i = PGTLO(2*2, lo); i <= hi; i += 2) totients[i-lo] -= totients[i-lo]/2;
-  for (i = PGTLO(2*3, lo); i <= hi; i += 3) totients[i-lo] -= totients[i-lo]/3;
-  for (i = PGTLO(2*5, lo); i <= hi; i += 5) totients[i-lo] -= totients[i-lo]/5;
   sievehi = hi/2;
+  for (i=P2GTLO(2*2,2,lo); i <= hi; i += 2) totients[i-lo] -= totients[i-lo]/2;
+  for (i=P2GTLO(2*3,3,lo); i <= hi; i += 3) totients[i-lo] -= totients[i-lo]/3;
+  for (i=P2GTLO(2*5,5,lo); i <= hi; i += 5) totients[i-lo] -= totients[i-lo]/5;
   if (get_prime_cache(sievehi, &sieve) < sievehi) {
     release_prime_cache(sieve);
     croak("Could not generate sieve for %"UVuf, sievehi);
   } else {
     START_DO_FOR_EACH_SIEVE_PRIME( sieve, 7, sievehi ) {
-      for (i = PGTLO(2*p, lo); i <= hi; i += p)
+      for (i = P2GTLO(2*p,p,lo); i <= hi; i += p)
         totients[i-lo] -= totients[i-lo]/p;
     } END_DO_FOR_EACH_SIEVE_PRIME
     release_prime_cache(sieve);
diff --git a/xt/totient-range.pl b/xt/totient-range.pl
new file mode 100755
index 0000000..6371a6c
--- /dev/null
+++ b/xt/totient-range.pl
@@ -0,0 +1,31 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+$| = 1;  # fast pipes
+
+use Math::Prime::Util qw/euler_phi/;
+use List::Util qw/sum/;
+
+my $limit = shift || 1_000_000;
+
+print "Calculating totients from 1 to $limit...";
+my @phi = map { euler_phi($_) } 1 .. $limit;
+print "...";
+unshift @phi, 0;
+print "...done\n";
+
+while (1) {
+  my $beg = 1 + int(rand($limit));
+  my $end = 1 + int(rand($limit));
+  ($beg,$end) = ($end,$beg) if $beg > $end;
+
+  # Does range return the same values?
+  my @phi_range = @phi[ $beg .. $end ];
+  my @totients = euler_phi($beg,$end);
+
+  my $sum1 = sum(@phi_range);
+  my $sum2 = sum(@totients);
+  warn "\nbeg $beg  end $end  sum $sum1  range sum $sum2\n"
+       unless $sum1 == $sum2;
+  print ".";
+}

-- 
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