[libmath-prime-util-perl] 50/181: Updated validate_int; znprimroot, carmichael_lambda, kronecker

Partha P. Mukherjee ppm-guest at moszumanska.debian.org
Thu May 21 18:51:05 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 0371266e7ffa8f95312a42a62cf5cdcf1c028101
Author: Dana Jacobsen <dana at acm.org>
Date:   Fri Dec 27 18:23:21 2013 -0800

    Updated validate_int; znprimroot, carmichael_lambda, kronecker
---
 XS.xs  | 159 ++++++++++++++++++++++++++++++++++++++++++++++-------------------
 util.h |   1 -
 2 files changed, 112 insertions(+), 48 deletions(-)

diff --git a/XS.xs b/XS.xs
index bcc417b..21903a5 100644
--- a/XS.xs
+++ b/XS.xs
@@ -20,22 +20,30 @@
 #include "lmo.h"
 #include "aks.h"
 
-#if BITS_PER_WORD == 64 && defined(_MSC_VER)
-  #include <stdlib.h>
-  #define PSTRTOULL(str, end, base) _strtoui64 (str, end, base)
-#elif BITS_PER_WORD == 64 && (defined(__GNUC__) || QUADKIND==QUAD_IS_LONG_LONG)
+#if BITS_PER_WORD == 64
+  #if defined(_MSC_VER)
+    #include <stdlib.h>
+    #define strtoull _strtoui64
+    #define strtoll  _strtoi64
+  #endif
   #define PSTRTOULL(str, end, base) strtoull (str, end, base)
+  #define PSTRTOLL(str, end, base)  strtoll (str, end, base)
 #else
   #define PSTRTOULL(str, end, base) strtoul (str, end, base)
+  #define PSTRTOLL(str, end, base)  strtol (str, end, base)
 #endif
 
 /* Workaround perl 5.6 UVs and bigints in later */
 #if PERL_REVISION <= 5 && PERL_VERSION <= 6 && BITS_PER_WORD == 64
  #define set_val_from_sv(val, sv) \
-   val = PSTRTOULL(SvPV_nolen(sv), NULL, 10);
+   do { val = PSTRTOULL(SvPV_nolen(sv), NULL, 10); } while(0)
+ #define set_sval_from_sv(val, sv) \
+   do { val = PSTRTOLL(SvPV_nolen(sv), NULL, 10); } while(0)
 #else
  #define set_val_from_sv(val, sv) \
-   val = (!SvROK(sv)) ? SvUV(sv) : PSTRTOULL(SvPV_nolen(sv), NULL, 10);
+   do { val = (!SvROK(sv)) ? SvUV(sv) : PSTRTOULL(SvPV_nolen(sv), NULL, 10); } while(0)
+ #define set_sval_from_sv(val, sv) \
+   do { val = (!SvROK(sv)) ? SvIV(sv) : PSTRTOLL(SvPV_nolen(sv), NULL, 10); } while(0)
 #endif
 
 /* multicall compatibility stuff */
@@ -66,10 +74,14 @@ static int pbrent_factor_a1(UV n, UV *factors, UV maxrounds) {
 
 #if BITS_PER_WORD == 32
   static const unsigned int uvmax_maxlen = 10;
+  static const unsigned int ivmax_maxlen = 10;
   static const char uvmax_str[] = "4294967295";
+  static const char ivmax_str[] = "2147483648";
 #else
   static const unsigned int uvmax_maxlen = 20;
+  static const unsigned int ivmax_maxlen = 19;
   static const char uvmax_str[] = "18446744073709551615";
+  static const char ivmax_str[] =  "9223372036854775808";
 #endif
 
 /* Is this a pedantically valid integer?
@@ -80,13 +92,19 @@ static int pbrent_factor_a1(UV n, UV *factors, UV maxrounds) {
 static int _validate_int(SV* n, int negok)
 {
   dTHX;
+  const char* maxstr;
   char* ptr;
-  STRLEN i, len;
-  int isneg = 0;
+  STRLEN i, len, maxlen;
+  int ret, isneg = 0;
 
   if (!SvOK(n))  croak("Parameter must be defined");
+  if (SvIOK(n)) {                      /* If defined as number, use that */
+    if (SvIsUV(n) || SvIV(n) >= 0)  return 1;
+    if (negok)  return -1;
+    else      croak("Parameter '%s' must be a positive integer", SvPV_nolen(n));
+  }
   if (SvROK(n) && !sv_isa(n, "Math::BigInt"))  return 0;
-  ptr = SvPV(n, len);  /* This will stringify bigints for us, yay */
+  ptr = SvPV(n, len);                  /* Includes stringifying bigints */
   if (len == 0 || ptr == 0)  croak("Parameter '' must be a positive integer");
   if (ptr[0] == '-') {                 /* Read negative sign */
     if (negok) { isneg = 1; ptr++; len--; }
@@ -100,15 +118,18 @@ static int _validate_int(SV* n, int negok)
   for (i = 0; i < len; i++)            /* Ensure all characters are digits */
     if (!isDIGIT(ptr[i]))
       croak("Parameter '%s' must be a positive integer", ptr);
-  if (isneg)                           /* Negative number (ignore overflow) */
+  if (isneg == 1)                      /* Negative number (ignore overflow) */
     return -1;
-  if (len < uvmax_maxlen)              /* Valid small integer */
-    return 1;
-  for (i = 0; i < uvmax_maxlen; i++) { /* Check if in range */
-    if (ptr[i] < uvmax_str[i]) return 1;
-    if (ptr[i] > uvmax_str[i]) return 0;
+  ret    = isneg ? -1           : 1;
+  maxlen = isneg ? ivmax_maxlen : uvmax_maxlen;
+  maxstr = isneg ? ivmax_str    : uvmax_str;
+  if (len < maxlen)                    /* Valid small integer */
+    return ret;
+  for (i = 0; i < maxlen; i++) {       /* Check if in range */
+    if (ptr[i] < maxstr[i]) return ret;
+    if (ptr[i] > maxstr[i]) return 0;
   }
-  return 1;                            /* value = UV_MAX.  That's ok */
+  return ret;                          /* value = UV_MAX/UV_MIN.  That's ok */
 }
 
 /* Call a Perl sub to handle work for us.
@@ -386,29 +407,14 @@ _XS_factor_exp(IN UV n)
   PREINIT:
     UV factors[MPU_MAX_FACTORS+1];
     UV exponents[MPU_MAX_FACTORS+1];
-    int i, j, nfactors;
+    int i, nfactors;
   PPCODE:
-    nfactors = factor(n, factors);
+    nfactors = factor_exp(n, factors, exponents);
     if (GIMME_V == G_SCALAR) {
-      /* Count unique prime factors and return the scalar */
-      if (n == 1)  XSRETURN_UV(0);
-      for (i = 1, j = 1; i < nfactors; i++)
-        if (factors[i] != factors[i-1])
-          j++;
-      PUSHs(sv_2mortal(newSVuv(j)));
+      PUSHs(sv_2mortal(newSVuv(nfactors)));
     } else {
       /* Return ( [p1,e1], [p2,e2], [p3,e3], ... ) */
       if (n == 1)  XSRETURN_EMPTY;
-      exponents[0] = 1;
-      for (i = 1, j = 1; i < nfactors; i++) {
-        if (factors[i] != factors[i-1]) {
-          exponents[j] = 1;
-          factors[j++] = factors[i];
-        } else {
-          exponents[j-1]++;
-        }
-      }
-      nfactors = j;
       for (i = 0; i < nfactors; i++) {
         AV* av = newAV();
         av_push(av, newSVuv(factors[i]));
@@ -601,6 +607,63 @@ next_prime(IN SV* n)
                            "Math::Prime::Util::_generic_prev_prime" );
     XSRETURN(1);
 
+void
+znprimroot(IN SV* svn)
+  PREINIT:
+    int status;
+  PPCODE:
+    status = _validate_int(svn, 1);
+    if (status != 0) {
+      UV n, r;
+      set_val_from_sv(n, svn);
+      if (status == -1)
+        n = -(IV)n;
+      r = znprimroot(n);
+      if (r == 0 && n != 1) XSRETURN_EMPTY;
+      XSRETURN_UV(r);
+    }
+    _vcallsub("Math::Prime::Util::_generic_znprimroot");
+    XSRETURN(1);
+
+int
+kronecker(IN SV* sva, IN SV* svb)
+  PREINIT:
+    int astatus, bstatus;
+  CODE:
+    astatus = _validate_int(sva, 2);
+    bstatus = _validate_int(svb, 2);
+    if (astatus == 1 && bstatus == 1) {
+      UV a, b;
+      set_val_from_sv(a, sva);
+      set_val_from_sv(b, svb);
+      RETVAL = kronecker_uu(a, b);
+    } else if (astatus != 0 && SvIOK(sva) && !SvIsUV(sva) &&
+               bstatus != 0 && SvIOK(svb) && !SvIsUV(svb) ) {
+      IV a, b;
+      set_sval_from_sv(a, sva);
+      set_sval_from_sv(b, svb);
+      RETVAL = kronecker_ss(a, b);
+    } else {
+      dTHX;
+      dSP;
+      int count;
+      ENTER;
+      SAVETMPS;
+      PUSHMARK(SP);
+      XPUSHs(sva);
+      XPUSHs(svb);
+      PUTBACK;
+      count = call_pv("Math::Prime::Util::_generic_kronecker", G_SCALAR);
+      SPAGAIN;
+      if (count != 1) croak("callback sub should return one value");
+      RETVAL = POPi;
+      PUTBACK;
+      FREETMPS;
+      LEAVE;
+    }
+  OUTPUT:
+    RETVAL
+
 double
 _XS_ExponentialIntegral(IN double x)
   ALIAS:
@@ -659,20 +722,22 @@ _XS_totient(IN UV lo, IN UV hi = 0)
         Safefree(totients);
       }
     } else {
-      UV facs[MPU_MAX_FACTORS+1];  /* maximum number of factors is log2n */
-      UV nfacs, totient, lastf;
-      UV n = lo;
-      if (n <= 1) XSRETURN_UV(n);
-      nfacs = factor(n, facs);
-      totient = 1;
-      lastf = 0;
-      for (i = 0; i < nfacs; i++) {
-        UV f = facs[i];
-        if (f == lastf) { totient *= f;               }
-        else            { totient *= f-1;  lastf = f; }
-      }
-      PUSHs(sv_2mortal(newSVuv(totient)));
+      XSRETURN_UV(totient(lo));
+    }
+
+void
+carmichael_lambda(IN SV* svn)
+  PREINIT:
+    int status;
+  PPCODE:
+    status = _validate_int(svn, 0);
+    if (status == 1) {
+      UV n;
+      set_val_from_sv(n, svn);
+      XSRETURN_UV(carmichael_lambda(n));
     }
+    _vcallsub("Math::Prime::Util::_generic_carmichael_lambda");
+    XSRETURN(1);
 
 void
 _XS_moebius(IN UV lo, IN UV hi = 0)
diff --git a/util.h b/util.h
index b420c20..520ea76 100644
--- a/util.h
+++ b/util.h
@@ -34,7 +34,6 @@ extern int kronecker_ss(IV a, IV b);
 extern UV totient(UV n);
 extern UV carmichael_lambda(UV n);
 extern UV znprimroot(UV n);
-extern UV znorder(UV n);
 
 /* Above this value, is_prime will do deterministic Miller-Rabin */
 /* With 64-bit math, we can do much faster mulmods from 2^16-2^32 */

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