[libmath-prime-util-perl] 89/181: Next set of XS changes

Partha P. Mukherjee ppm-guest at moszumanska.debian.org
Thu May 21 18:51:10 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 4f5622221c247aba8c34806c119daaabe2a486ac
Author: Dana Jacobsen <dana at acm.org>
Date:   Tue Dec 31 21:52:29 2013 -0800

    Next set of XS changes
---
 XS.xs                     | 84 +++++++++++++++++++++++++++--------------------
 lib/Math/Prime/Util.pm    |  3 +-
 lib/Math/Prime/Util/PP.pm |  1 +
 3 files changed, 51 insertions(+), 37 deletions(-)

diff --git a/XS.xs b/XS.xs
index b908084..6a1c40c 100644
--- a/XS.xs
+++ b/XS.xs
@@ -245,7 +245,7 @@ sieve_primes(IN UV low, IN UV high)
     if ((low <= 5) && (high >= 5)) { av_push(av, newSVuv( 5 )); }
     if (low < 7)  low = 7;
     if (low <= high) {
-      if (ix == 0) {                          /* Sieve */
+      if (ix == 0) {                          /* Sieve with primary cache */
         START_DO_FOR_EACH_PRIME(low, high) {
           av_push(av,newSVuv(p));
         } END_DO_FOR_EACH_PRIME
@@ -255,7 +255,7 @@ sieve_primes(IN UV low, IN UV high)
              low = _XS_next_prime(low) ) {
           av_push(av,newSVuv(low));
         }
-      } else if (ix == 2) {                   /* Erat */
+      } else if (ix == 2) {                   /* Erat with private memory */
         unsigned char* sieve = sieve_erat30(high);
         START_DO_FOR_EACH_SIEVE_PRIME( sieve, low, high ) {
            av_push(av,newSVuv(p));
@@ -519,55 +519,53 @@ divisor_sum(IN SV* svn, ...)
 
 void
 znorder(IN SV* sva, IN SV* svn)
+  ALIAS:
+    legendre_phi = 1
   PPCODE:
     int astatus = _validate_int(aTHX_ sva, 0);
     int nstatus = _validate_int(aTHX_ svn, 0);
     if (astatus == 1 && nstatus == 1) {
       UV a = my_svuv(sva);
       UV n = my_svuv(svn);
-      UV order = znorder(a, n);
-      if (order == 0) XSRETURN_UNDEF;
-      XSRETURN_UV(order);
+      UV ret;
+      switch (ix) {
+        case 0:  ret = znorder(a,n);
+                 if (ret == 0) XSRETURN_UNDEF;  /* not defined */
+                 break;
+        default: ret = legendre_phi(a, n);
+                 break;
+      }
+      XSRETURN_UV(ret);
     }
-    _vcallsubn(aTHX_ G_SCALAR, "_generic_znorder", 2);
-    return; /* skip implicit PUTBACK */
-
-void
-znprimroot(IN SV* svn)
-  PPCODE:
-    int status = _validate_int(aTHX_ svn, 1);
-    if (status != 0) {
-      UV r, n = my_svuv(svn);
-      if (status == -1)
-        n = -(IV)n;
-      r = znprimroot(n);
-      if (r == 0 && n != 1) XSRETURN_EMPTY;
-      XSRETURN_UV(r);
+    switch (ix) {
+      case 0:  _vcallsubn(aTHX_ G_SCALAR, "_generic_znorder", 2);  break;
+      /* TODO: Fixup public PP legendre_phi */
+      default: _vcallsubn(aTHX_ G_SCALAR, "PP::_legendre_phi", 2); break;
     }
-    _vcallsub("_generic_znprimroot");
     return; /* skip implicit PUTBACK */
 
 void
 kronecker(IN SV* sva, IN SV* svb)
+  PREINIT:
+    int astatus, bstatus, abpositive, abnegative;
   PPCODE:
-    int astatus = _validate_int(aTHX_ sva, 2);
-    int bstatus = _validate_int(aTHX_ svb, 2);
-    if (astatus == 1 && bstatus == 1) {
+    astatus = _validate_int(aTHX_ sva, 2);
+    bstatus = _validate_int(aTHX_ svb, 2);
+    /* Are both a and b positive? */
+    abpositive = astatus == 1 && bstatus == 1;
+    /* Will both fit in IVs?  We should use a bitmask return. */
+    abnegative = !abpositive
+                 && (astatus != 0 && SvIOK(sva) && !SvIsUV(sva))
+                 && (bstatus != 0 && SvIOK(svb) && !SvIsUV(svb));
+    if (abpositive || abnegative) {
       UV a = my_svuv(sva);
       UV b = my_svuv(svb);
-      XSRETURN_IV( kronecker_uu(a, b) );
-    } else if (astatus != 0 && SvIOK(sva) && !SvIsUV(sva) &&
-               bstatus != 0 && SvIOK(svb) && !SvIsUV(svb) ) {
-      IV a = my_sviv(sva);
-      IV b = my_sviv(svb);
-      XSRETURN_IV( kronecker_ss(a, b) );
+      IV k = (abpositive) ? kronecker_uu(a,b) : kronecker_ss(a,b);
+      XSRETURN_IV( k );
     }
     _vcallsubn(aTHX_ G_SCALAR, "_generic_kronecker", 2);
     return; /* skip implicit PUTBACK */
 
-UV
-legendre_phi(IN UV n, IN UV a)
-
 double
 _XS_ExponentialIntegral(IN SV* x)
   ALIAS:
@@ -624,15 +622,14 @@ euler_phi(IN SV* svlo, ...)
       UV hi = my_svuv(ST(1));
       if (lo <= hi) {
         UV i;
+        EXTEND(SP, hi-lo+1);
         if (ix == 0) {
           UV* totients = _totient_range(lo, hi);
-          EXTEND(SP, hi-lo+1);
           for (i = lo; i <= hi; i++)
             PUSHs(sv_2mortal(newSVuv(totients[i-lo])));
           Safefree(totients);
         } else {
           signed char* mu = _moebius_range(lo, hi);
-          EXTEND(SP, hi-lo+1);
           for (i = lo; i <= hi; i++)
             PUSHs(sv_2mortal(newSViv(mu[i-lo])));
           Safefree(mu);
@@ -654,8 +651,11 @@ carmichael_lambda(IN SV* svn)
   ALIAS:
     mertens = 1
     exp_mangoldt = 2
+    znprimroot = 3
+  PREINIT:
+    int status;
   PPCODE:
-    int status = _validate_int(aTHX_ svn, (ix > 1) ? 1 : 0);
+    status = _validate_int(aTHX_ svn, (ix > 1) ? 1 : 0);
     switch (ix) {
       case 0: if (status == 1) XSRETURN_UV(carmichael_lambda(my_svuv(svn)));
               _vcallsub("_generic_carmichael_lambda");
@@ -663,10 +663,22 @@ carmichael_lambda(IN SV* svn)
       case 1: if (status == 1) XSRETURN_IV(mertens(my_svuv(svn)));
               _vcallsub("_generic_mertens");
               break;
-      default:if (status ==-1) XSRETURN_UV(1);
+      case 2: if (status ==-1) XSRETURN_UV(1);
               if (status == 1) XSRETURN_UV(exp_mangoldt(my_svuv(svn)));
               _vcallsub("_generic_exp_mangoldt");
               break;
+      case 3:
+      default:if (status != 0) {
+                UV r, n = my_svuv(svn);
+                if (status == -1) n = -(IV)n;
+                r = znprimroot(n);
+                if (r == 0 && n != 1)
+                  XSRETURN_UNDEF;   /* No root, return undef */
+                else
+                  XSRETURN_UV(r);
+              }
+              _vcallsub("_generic_znprimroot");
+              break;
     }
     return; /* skip implicit PUTBACK */
 
diff --git a/lib/Math/Prime/Util.pm b/lib/Math/Prime/Util.pm
index 8f8eb0d..9480b2d 100644
--- a/lib/Math/Prime/Util.pm
+++ b/lib/Math/Prime/Util.pm
@@ -42,7 +42,7 @@ our @EXPORT_OK =
       partitions
       chebyshev_theta chebyshev_psi
       divisor_sum
-      carmichael_lambda kronecker znorder znprimroot
+      carmichael_lambda kronecker znorder znprimroot legendre_phi
       ExponentialIntegral LogarithmicIntegral RiemannZeta RiemannR
   );
 our %EXPORT_TAGS = (all => [ @EXPORT_OK ]);
@@ -107,6 +107,7 @@ BEGIN {
     *divisor_sum   = \&Math::Prime::Util::_generic_divisor_sum;
     *znorder       = \&Math::Prime::Util::_generic_znorder;
     *znprimroot    = \&Math::Prime::Util::_generic_znprimroot;
+    *legendre_phi  = \&Math::Prime::Util::PP::_legendre_phi;
     *factor        = \&Math::Prime::Util::_generic_factor;
     *factor_exp    = \&Math::Prime::Util::_generic_factor_exp;
     *divisors      = \&Math::Prime::Util::_generic_divisors;
diff --git a/lib/Math/Prime/Util/PP.pm b/lib/Math/Prime/Util/PP.pm
index 031d6ab..987834e 100644
--- a/lib/Math/Prime/Util/PP.pm
+++ b/lib/Math/Prime/Util/PP.pm
@@ -633,6 +633,7 @@ sub _mapes {
 sub _legendre_phi {
   my ($x, $a, $primes) = @_;
   return _mapes($x,$a) if $a <= 6;
+  $primes = primes($a + 1) unless defined $primes;
   return ($x > 0 ? 1 : 0) if $x < $primes->[$a];
 
   my $sum = 0;

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