[libmath-prime-util-perl] 87/181: Merge euler_phi and moebius XS

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


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

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

commit 3cc157ed389359b98202d972735699251f355a49
Author: Dana Jacobsen <dana at acm.org>
Date:   Tue Dec 31 19:02:53 2013 -0800

    Merge euler_phi and moebius XS
---
 XS.xs                  | 89 ++++++++++++++++----------------------------------
 lib/Math/Prime/Util.pm | 37 ++++-----------------
 2 files changed, 35 insertions(+), 91 deletions(-)

diff --git a/XS.xs b/XS.xs
index 23a5fe2..d3233c3 100644
--- a/XS.xs
+++ b/XS.xs
@@ -602,84 +602,51 @@ _XS_ExponentialIntegral(IN SV* x)
 
 void
 euler_phi(IN SV* svlo, ...)
+  ALIAS:
+    moebius = 1
+  PREINIT:
+    int lostatus, histatus;
   PPCODE:
-    if (items == 1) {
-      int lostatus = _validate_int(aTHX_ svlo, 1);
-      if (lostatus == -1) {      /*  I like SAGE's decision that    */
-        XSRETURN_UV(0);          /*  totient(n) = 0 if n <= 0       */
-      } else if (lostatus == 1) {
-        UV lo = my_svuv(svlo);
-        XSRETURN_UV(totient(lo));
+    lostatus = _validate_int(aTHX_ svlo, 2);
+    histatus = (items == 1 || _validate_int(aTHX_ ST(1), 0));
+    if (items == 1 && lostatus != 0) {
+      /* input is a single value and in UV/IV range */
+      if (ix == 0) {
+        UV n = (lostatus == -1) ? 0 : my_svuv(svlo);
+        XSRETURN_UV(totient(n));
       } else {
-        _vcallsubn(aTHX_ G_SCALAR, "_generic_euler_phi", 1);
-        return; /* skip implicit PUTBACK */
+        IV n = (lostatus == -1) ? -(my_sviv(svlo)) : my_svuv(svlo);
+        XSRETURN_IV(moebius(n));
       }
-    } else if (items == 2) {
-      SV* svhi = ST(1);
-      int lostatus = _validate_int(aTHX_ svlo, 1);
-      int histatus = _validate_int(aTHX_ svhi, 1);
-      if (lostatus == 1 && histatus == 1) {
-        UV lo = my_svuv(svlo);
-        UV hi = my_svuv(svhi);
-        if (hi < lo) XSRETURN_EMPTY;
-        if (lo < 2) {
-          if (lo <= 0           ) XPUSHs(sv_2mortal(newSVuv(0)));
-          if (lo <= 1 && hi >= 1) XPUSHs(sv_2mortal(newSVuv(1)));
-          lo = 2;
-        }
-        if (hi >= lo) {
-          UV i;
+    } else if (items == 2 && lostatus == 1 && histatus == 1) {
+      /* input is a range and both lo and hi are non-negative */
+      UV lo = my_svuv(svlo);
+      UV hi = my_svuv(ST(1));
+      if (lo <= hi) {
+        UV i;
+        if (ix == 0) {
           UV* totients = _totient_range(lo, hi);
-          /* Extend the stack to handle how many items we'll return */
           EXTEND(SP, hi-lo+1);
           for (i = lo; i <= hi; i++)
             PUSHs(sv_2mortal(newSVuv(totients[i-lo])));
           Safefree(totients);
-        }
-      } else {
-        _vcallsubn(aTHX_ G_ARRAY,"_generic_euler_phi",items);
-        return; /* skip implicit PUTBACK */
-      }
-    } else {
-      croak("Usage: euler_phi(n) or euler_phi(1o,hi)");
-    }
-
-void
-moebius(IN SV* svlo, ...)
-  PPCODE:
-    if (items == 1) {
-      int nstatus = _validate_int(aTHX_ svlo, 0);
-      if (nstatus == 1) {
-        UV n = my_svuv(svlo);
-        XSRETURN_IV(moebius(n));
-      } else {
-        _vcallsubn(aTHX_ G_SCALAR, "_generic_moebius",1);
-        return; /* skip implicit PUTBACK */
-      }
-    } else if (items == 2) {
-      SV* svhi = ST(1);
-      int lostatus = _validate_int(aTHX_ svlo, 0);
-      int histatus = _validate_int(aTHX_ svhi, 0);
-      if (lostatus == 1 && histatus == 1) {
-        UV lo = my_svuv(svlo);
-        UV hi = my_svuv(svhi);
-        if (hi < lo) {
-          XSRETURN_EMPTY;
         } else {
-          UV i;
           signed char* mu = _moebius_range(lo, hi);
-          MPUassert( mu != 0, "_moebius_range returned 0" );
           EXTEND(SP, hi-lo+1);
           for (i = lo; i <= hi; i++)
             PUSHs(sv_2mortal(newSViv(mu[i-lo])));
           Safefree(mu);
         }
-      } else {
-        _vcallsubn(aTHX_ G_ARRAY, "_generic_moebius",items);
-        return; /* skip implicit PUTBACK */
       }
     } else {
-      croak("Usage: moebius(n) or moebius(1o,hi)");
+      /* Whatever we didn't handle above */
+      U32 gimme_v = GIMME_V;
+      switch (ix) {
+        case 0:  _vcallsubn(aTHX_ gimme_v, "_generic_euler_phi", items); break;
+        case 1:
+        default: _vcallsubn(aTHX_ gimme_v, "_generic_moebius", items);   break;
+      }
+      return;
     }
 
 void
diff --git a/lib/Math/Prime/Util.pm b/lib/Math/Prime/Util.pm
index de9155f..8f8eb0d 100644
--- a/lib/Math/Prime/Util.pm
+++ b/lib/Math/Prime/Util.pm
@@ -2575,35 +2575,13 @@ By default all functions support bignums.  For performance, you should
 install and use L<Math::BigInt::GMP> or L<Math::BigInt::Pari>, and
 L<Math::Prime::Util::GMP>.
 
-Some of the functions, including:
-
-  factor
-  factor_exp
-  is_pseudoprime
-  is_strong_pseudoprime
-  nth_prime
-  moebius
-  mertens
-  euler_phi
-  chebyshev_theta
-  chebyshev_psi
-  is_prime
-  is_prob_prime
-  next_prime
-  prev_prime
-
-work very fast (under 1 microsecond) on small inputs, but the wrappers for
-input validation and bigint support take more time than the function itself.
-Using the flag '-bigint', e.g.:
+Using the flag C<-bigint>, e.g.
 
   use Math::Prime::Util qw(-bigint);
 
-will turn off bigint support for those functions.  Those functions will then
-go directly to the XS versions, which will speed up very small inputs a B<lot>.
-This is useful if you're using the functions in a loop, but since the difference
-is less than a millisecond, it's really not important in general.  The last
-five functions have shortcuts by default so will only skip validation.
-
+will turn off bigint support for some functions.  This turns off input
+validation and some complicated conversions.  It is not recommended and
+will likely go away in future version.
 
 If you are using bigints, here are some performance suggestions:
 
@@ -3397,7 +3375,7 @@ C<$_> set to each divisor in sorted order.  Also see L</divisor_sum>.
   $sum += moebius($_) for (1..200); say "Mertens(200) = $sum";
 
 Returns μ(n), the Möbius function (also called the Moebius, Mobius, or
-MoebiusMu function) for a non-negative integer input.  This function is 1 if
+MoebiusMu function) for an integer input.  This function is 1 if
 C<n = 1>, 0 if C<n> is not square free (i.e. C<n> has a repeated factor),
 and C<-1^t> if C<n> is a product of C<t> distinct primes.  This is an
 important function in prime number theory.  Like SAGE, we define
@@ -3420,9 +3398,8 @@ for large inputs.  For example, computing Mertens(100M) takes:
 
    time    approx mem
      0.4s      0.1MB   mertens(100_000_000)
-    74.8s   7000MB     List::Util::sum(moebius(1,100_000_000))
-    88.5s      0MB     $sum += moebius($_) for 1..100_000_000   [-nobigint]
-   181.8s      0MB     $sum += moebius($_) for 1..100_000_000
+     5.5s   7000MB     List::Util::sum(moebius(1,100_000_000))
+    91.2s      0MB     $sum += moebius($_) for 1..100_000_000
 
 The summation of individual terms via factoring is quite expensive in time,
 though uses O(1) space.  This function will generate the equivalent output

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