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

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

commit 718c44d785f1557512e786e4c235957a9f9203cb
Author: Dana Jacobsen <d...@acm.org>
Date:   Mon Mar 11 18:31:36 2013 -0700

    New internal macro to loop a..b using primary sieve
---
 Changes  |  3 +++
 TODO     |  7 -------
 XS.xs    | 16 +++-------------
 factor.c | 41 +++++++++++++++++++----------------------
 lehmer.c | 15 ++++-----------
 sieve.h  | 35 +++++++++++++++++++++++++++++++++++
 util.c   | 61 ++++++++++++++-----------------------------------------------
 7 files changed, 78 insertions(+), 100 deletions(-)

diff --git a/Changes b/Changes
index 71c04c9..fdc9b74 100644
--- a/Changes
+++ b/Changes
@@ -5,6 +5,9 @@ Revision history for Perl extension Math::Prime::Util.
     - Speed up p-1 stage 2 factoring.  This makes factor() about 20% faster
       for 19 digit semiprimes.
 
+    - New internal macro to loop over primary sieve starting at 2.  Simplifies
+      code in quite a few places.
+
 0.24 10 March 2013
 
     - Fix compilation with old pre-C99 strict compilers (decl after statement).
diff --git a/TODO b/TODO
index dc0ddd7..a75cc17 100644
--- a/TODO
+++ b/TODO
@@ -41,11 +41,4 @@
 
 - More efficient totient segment.  Do we really need primes to n/2?
 
-- Add a more complex system for allowing something like:
-      FOREACH_PRIME(low, high) {
-        ....
-      } END_FOREACH_PRIME
-  that (1) handles any low / high, and (2) segments.  Take segment_primes
-  from XS.xs to do this.
-
 - Implement S2 calculation for LMO prime count.
diff --git a/XS.xs b/XS.xs
index 5f2f42d..ff46ecc 100644
--- a/XS.xs
+++ b/XS.xs
@@ -102,19 +102,9 @@ sieve_primes(IN UV low, IN UV high)
     AV* av = newAV();
   CODE:
     if (low <= high) {
-      if (get_prime_cache(high, &sieve) < high) {
-        release_prime_cache(sieve);
-        croak("Could not generate sieve for %"UVuf, high);
-      } else {
-        if ((low <= 2) && (high >= 2)) { av_push(av, newSVuv( 2 )); }
-        if ((low <= 3) && (high >= 3)) { av_push(av, newSVuv( 3 )); }
-        if ((low <= 5) && (high >= 5)) { av_push(av, newSVuv( 5 )); }
-        if (low < 7) { low = 7; }
-        START_DO_FOR_EACH_SIEVE_PRIME( sieve, low, high ) {
-           av_push(av,newSVuv(p));
-        } END_DO_FOR_EACH_SIEVE_PRIME
-        release_prime_cache(sieve);
-      }
+      START_DO_FOR_EACH_PRIME(low, high) {
+        av_push(av,newSVuv(p));
+      } END_DO_FOR_EACH_PRIME
     }
     RETVAL = newRV_noinc( (SV*) av );
   OUTPUT:
diff --git a/factor.c b/factor.c
index 75e496b..26622cf 100644
--- a/factor.c
+++ b/factor.c
@@ -66,7 +66,7 @@ int factor(UV n, UV *factors)
       }
       /* This p-1 gets about 2/3 of what makes it through the above */
       if (!split_success) {
-        split_success = pminus1_factor(n, tofac_stack+ntofac, 4000, 80000)-1;
+        split_success = pminus1_factor(n, tofac_stack+ntofac, 5000, 80000)-1;
         if (verbose) printf("pminus1 %d\n", split_success);
       }
       /* Some rounds of HOLF, good for close to perfect squares */
@@ -632,19 +632,21 @@ int pminus1_factor(UV n, UV *factors, UV B1, UV B2)
   UV sqrtB1 = isqrt(B1);
   MPUassert( (n >= 3) && ((n%2) != 0) , "bad n in pminus1_factor");
 
-  for (q = 2; q <= sqrtB1; q = _XS_next_prime(q)) {
-    UV k = q*q;
-    UV kmin = B1/q;
+  START_DO_FOR_EACH_PRIME(2, sqrtB1) {
+    UV k = p*p;
+    UV kmin = B1/p;
     while (k <= kmin)
-      k *= q;
+      k *= p;
     a = powmod(a, k, n);
-  }
+    q = p;
+  } END_DO_FOR_EACH_PRIME
   if (a == 0) { factors[0] = n; return 1; }
   f = gcd_ui(a-1, n);
   if (f == 1) {
     savea = a;
     saveq = q;
-    for (; q <= B1; q = _XS_next_prime(q)) {
+    START_DO_FOR_EACH_PRIME(q+1, B1) {
+      q = p;
       a = powmod(a, q, n);
       if ( (j++ % 32) == 0) {
         if (a == 0 || gcd_ui(a-1, n) != 1)
@@ -652,23 +654,24 @@ int pminus1_factor(UV n, UV *factors, UV B1, UV B2)
         savea = a;
         saveq = q;
       }
-    }
+    } END_DO_FOR_EACH_PRIME
     if (a == 0) { factors[0] = n; return 1; }
     f = gcd_ui(a-1, n);
   }
   /* If we found more than one factor in stage 1, backup and single step */
   if (f == n) {
     a = savea;
-    for (q = saveq; q <= B1; q = _XS_next_prime(q)) {
-      UV k = q;
-      UV kmin = B1/q;
+    START_DO_FOR_EACH_PRIME(saveq, B1) {
+      UV k = p;
+      UV kmin = B1/p;
       while (k <= kmin)
-        k *= q;
+        k *= p;
       a = powmod(a, k, n);
       f = gcd_ui(a-1, n);
+      q = p;
       if (f != 1)
         break;
-    }
+    } END_DO_FOR_EACH_PRIME
     /* If f == n again, we could do:
      * for (savea = 3; f == n && savea < 100; savea = _XS_next_prime(savea)) {
      *   a = savea;
@@ -681,8 +684,7 @@ int pminus1_factor(UV n, UV *factors, UV B1, UV B2)
   }
 
   /* STAGE 2 */
-  if (f == 1 && B2 > B1 && q >= 5) {
-    const unsigned char* sieve;
+  if (f == 1 && B2 > B1) {
     UV bm = a;
     UV b = 1;
     UV bmdiff;
@@ -699,11 +701,7 @@ int pminus1_factor(UV n, UV *factors, UV B1, UV B2)
 
     a = powmod(a, q, n);
     j = 1;
-    if (get_prime_cache(B2, &sieve) < B2) {
-      release_prime_cache(sieve);
-      croak("Could not generate sieve for %"UVuf, B2);
-    }
-    START_DO_FOR_EACH_SIEVE_PRIME( sieve, q+1, B2 ) {
+    START_DO_FOR_EACH_PRIME( q+1, B2 ) {
       UV lastq = q;
       UV qdiff;
       q = p;
@@ -729,8 +727,7 @@ int pminus1_factor(UV n, UV *factors, UV B1, UV B2)
         if (f != 1)
           break;
       }
-    } END_DO_FOR_EACH_SIEVE_PRIME
-    release_prime_cache(sieve);
+    } END_DO_FOR_EACH_PRIME
     f = gcd_ui(b, n);
   }
   if ( (f != 1) && (f != n) ) {
diff --git a/lehmer.c b/lehmer.c
index 267787b..1417e2e 100644
--- a/lehmer.c
+++ b/lehmer.c
@@ -183,9 +183,8 @@ static UV* generate_small_primes(UV n)
  * Remember to free when done. */
 static UV* generate_small_primes(UV n)
 {
-  const unsigned char* sieve;
   UV* primes;
-  UV  i;
+  UV  i = 0;
   double fn = (double)n;
   double flogn  = log(fn);
   double flog2n  = log(flogn);
@@ -195,20 +194,14 @@ static UV* generate_small_primes(UV n)
      (n >= 18)     ? (UV) ceil(fn*(flogn+flog2n-1.0+((flog2n+0.30)/flogn)))
                    : 59;
 
-  if (get_prime_cache(nth_prime, &sieve) < nth_prime) {
-    release_prime_cache(sieve);
-    croak("Could not generate sieve for %"UVuf, nth_prime);
-  }
   New(0, primes, n+1, UV);
   if (primes == 0)
     croak("Can not allocate small primes\n");
-  primes[0] = 0; primes[1] = 2; primes[2] = 3; primes[3] = 5;
-  i = 3;
-  START_DO_FOR_EACH_SIEVE_PRIME( sieve, 7, nth_prime ) {
+  primes[0] = 0;
+  START_DO_FOR_EACH_PRIME(2, nth_prime) {
     if (i >= n) break;
     primes[++i] = p;
-  } END_DO_FOR_EACH_SIEVE_PRIME
-  release_prime_cache(sieve);
+  } END_DO_FOR_EACH_PRIME
   if (i < n)
     croak("Did not generate enough small primes.\n");
   if (verbose > 1) printf("generated %lu small primes, from 2 to %lu\n", i, 
primes[i]);
diff --git a/sieve.h b/sieve.h
index 8e1f3f9..6dca024 100644
--- a/sieve.h
+++ b/sieve.h
@@ -81,5 +81,40 @@ static UV prev_prime_in_sieve(const unsigned char* sieve, UV 
p) {
     } \
   }
 
+#define START_DO_FOR_EACH_PRIME(a, b) \
+  { \
+    const unsigned char* sieve_; \
+    UV d_ = 0; \
+    UV m_ = 7; \
+    UV p  = a; \
+    UV l_ = b; \
+    if (get_prime_cache(l_, &sieve_) < l_) { \
+      release_prime_cache(sieve_); \
+      croak("Could not generate sieve for %"UVuf, l_); \
+    } \
+    if (p <= 5) { \
+      p = (p <= 2) ? 2 : (p <= 3) ? 3 : 5; \
+    } else { \
+      d_ = p/30; \
+      m_ = p-d_*30; \
+      m_ += distancewheel30[m_]; \
+      p = d_*30 + m_; \
+    } \
+    while ( p <= l_ ) { \
+      if (p < 7 || !(sieve_[d_] & masktab30[m_]))
+
+#define RETURN_FROM_EACH_PRIME(x) \
+    do { release_prime_cache(sieve_); return(x); } while (0)
+
+#define END_DO_FOR_EACH_PRIME \
+      if (p < 7) { \
+        p += 1 + (p > 2); \
+      } else { \
+        m_ = nextwheel30[m_];  if (m_ == 1) { d_++; } \
+        p = d_*30+m_; \
+      } \
+    } \
+    release_prime_cache(sieve_); \
+  }
 
 #endif
diff --git a/util.c b/util.c
index 3eb4929..c7c3505 100644
--- a/util.c
+++ b/util.c
@@ -769,7 +769,7 @@ UV _XS_nth_prime(UV n)
 char* _moebius_range(UV lo, UV hi)
 {
   char* mu;
-  UV i, p;
+  UV i;
   UV sqrtn = isqrt(hi);
 #if 1
   IV* A;
@@ -786,14 +786,13 @@ char* _moebius_range(UV lo, UV hi)
     croak("Could not get memory for %"UVuf" moebius results\n", hi-lo+1);
   for (i = lo; i <= hi; i++)
     A[i-lo] = 1;
-  prime_precalc(sqrtn);
-  for (p = 2; p <= sqrtn; p = _XS_next_prime(p)) {
+  START_DO_FOR_EACH_PRIME(2, sqrtn) {
     UV p2 = p*p;
     for (i = PGTLO(p2, lo); i <= hi; i += p2)
       A[i-lo] = 0;
     for (i = PGTLO(p, lo); i <= hi; i += p)
       A[i-lo] *= -(IV)p;
-  }
+  } END_DO_FOR_EACH_PRIME
   New(0, mu, hi-lo+1, char);
   if (mu == 0)
     croak("Could not get memory for %"UVuf" moebius results\n", hi-lo+1);
@@ -807,6 +806,7 @@ char* _moebius_range(UV lo, UV hi)
   Safefree(A);
 #endif
 #if 0
+  UV p;
   /* Simple char method, Needs way too many primes */
   New(0, mu, hi-lo+1, char);
   if (mu == 0)
@@ -827,6 +827,7 @@ char* _moebius_range(UV lo, UV hi)
    * (1) I'm using the log function, which should be fixed (easy).
    * (2) it doesn't work.  try 64-101 vs. 64 vs. 100.
    */
+  UV p;
   unsigned char* A;
   New(0, A, hi-lo+1, unsigned char);
   if (A == 0)
@@ -862,7 +863,6 @@ char* _moebius_range(UV lo, UV hi)
 
 UV* _totient_range(UV lo, UV hi) {
   UV* totients;
-  const unsigned char* sieve;
   UV i, sievehi;
   if (hi < lo) croak("_totient_range error hi %lu < lo %lu\n", hi, lo);
   New(0, totients, hi-lo+1, UV);
@@ -872,18 +872,10 @@ UV* _totient_range(UV lo, UV hi) {
     totients[i-lo] = i;
   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 = 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);
-  }
+  START_DO_FOR_EACH_PRIME(3, sievehi) {
+    for (i = P2GTLO(2*p,p,lo); i <= hi; i += p)
+      totients[i-lo] -= totients[i-lo]/p;
+  } END_DO_FOR_EACH_PRIME
   for (i = lo; i <= hi; i++)
     if (totients[i-lo] == i)
       totients[i-lo] = i-1;
@@ -951,49 +943,24 @@ IV _XS_mertens(UV n) {
 
 double _XS_chebyshev_theta(UV n)
 {
-  const unsigned char* sieve;
   KAHAN_INIT(sum);
-
-  if (n >= 2) KAHAN_SUM(sum, 0.6931471805599453094172321214581765680755L);
-  if (n >= 3) KAHAN_SUM(sum, 1.0986122886681096913952452369225257046475L);
-  if (n >= 5) KAHAN_SUM(sum, 1.6094379124341003746007593332261876395256L);
-  if (n < 7) return (double) sum;
-
-  if (get_prime_cache(n, &sieve) < n) {
-    release_prime_cache(sieve);
-    croak("Could not generate sieve for %"UVuf, n);
-  }
-  START_DO_FOR_EACH_SIEVE_PRIME(sieve, 7, n) {
+  START_DO_FOR_EACH_PRIME(2, n) {
     KAHAN_SUM(sum, logl(p));
-  } END_DO_FOR_EACH_SIEVE_PRIME
-  release_prime_cache(sieve);
+  } END_DO_FOR_EACH_PRIME
   return (double) sum;
 }
 double _XS_chebyshev_psi(UV n)
 {
-  const unsigned char* sieve;
-  UV prime, mults_are_one;
+  UV mults_are_one = 0;
   long double logn, logp;
   KAHAN_INIT(sum);
 
   logn = logl(n);
-  for (prime = 2; prime <= 5 && prime <= n; prime += prime-1) {
-    logp = logl(prime);
-    KAHAN_SUM(sum, logp * floorl(logn/logp + 1e-15));
-  }
-  if (n < 7) return (double) sum;
-
-  if (get_prime_cache(n, &sieve) < n) {
-    release_prime_cache(sieve);
-    croak("Could not generate sieve for %"UVuf, n);
-  }
-  mults_are_one = 0;
-  START_DO_FOR_EACH_SIEVE_PRIME(sieve, 7, n) {
+  START_DO_FOR_EACH_PRIME(2, n) {
     logp = logl(p);
     if (!mults_are_one && p > (n/p))   mults_are_one = 1;
     KAHAN_SUM(sum, (mults_are_one) ? logp : logp * floorl(logn/logp + 1e-15));
-  } END_DO_FOR_EACH_SIEVE_PRIME
-  release_prime_cache(sieve);
+  } END_DO_FOR_EACH_PRIME
   return (double) sum;
 }
 

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-perl/packages/libmath-prime-util-perl.git

_______________________________________________
Pkg-perl-cvs-commits mailing list
Pkg-perl-cvs-commits@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-perl-cvs-commits

Reply via email to