[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