[libmath-prime-util-perl] 12/13: Racing SQUFOF & other UV factoring changes

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


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

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

commit e885753e7fe1ebaea79ec0312bd1eba560726265
Author: Dana Jacobsen <dana at acm.org>
Date:   Mon Jul 23 00:53:58 2012 -0600

    Racing SQUFOF & other UV factoring changes
---
 Changes                        |  3 ++-
 XS.xs                          | 38 +++++++++++++++++++++++++++++++++++---
 examples/bench-factor-extra.pl |  2 ++
 examples/bench-miller-rabin.pl | 14 ++++++++++++--
 examples/bench-pp-count.pl     |  0
 examples/bench-pp-isprime.pl   |  0
 examples/bench-pp-sieve.pl     |  0
 lib/Math/Prime/Util.pm         |  3 +++
 8 files changed, 54 insertions(+), 6 deletions(-)

diff --git a/Changes b/Changes
index ee18187..617ed05 100644
--- a/Changes
+++ b/Changes
@@ -1,12 +1,13 @@
 Revision history for Perl extension Math::Prime::Util.
 
-0.11  19 July 2012
+0.11  23 July 2012
     - Turn of threading tests on Cygwin, as threads on some Cygwin platforms
       give random panics (my Win7 64-bit works fine, XP 32-bit does not).
     - Use pow instead of exp2 -- some systems don't have exp2.
     - Fix compile issues on MSC, thanks to Sisyphus.
     - some bigint/bignum changes (next_prime and math functions).
     - speed up and enhance some tests.
+    - Add racing SQUFOF for UVs, also add a little more trial division.
 
 
 0.10  16 July 2012
diff --git a/XS.xs b/XS.xs
index 22292f8..7236fa6 100644
--- a/XS.xs
+++ b/XS.xs
@@ -200,7 +200,7 @@ _XS_factor(IN UV n)
       XPUSHs(sv_2mortal(newSVuv( n ))); /* If n is 0-3, we're done. */
     } else {
       int const verbose = 0;
-      UV tlim = 53;  /* Below this we've checked with trial division */
+      UV tlim = 101;  /* Below this we've checked with trial division */
       UV tofac_stack[MPU_MAX_FACTORS+1];
       UV factored_stack[MPU_MAX_FACTORS+1];
       int ntofac = 0;
@@ -225,6 +225,21 @@ _XS_factor(IN UV n)
         while ( (n%43) == 0 ) {  n /= 43;  XPUSHs(sv_2mortal(newSVuv( 43 ))); }
         while ( (n%47) == 0 ) {  n /= 47;  XPUSHs(sv_2mortal(newSVuv( 47 ))); }
       }
+      if ( (n >= UVCONST(53*53)) && (gcd_ui(n, UVCONST(907383479) != 1)) ) {
+        while ( (n%53) == 0 ) {  n /= 53;  XPUSHs(sv_2mortal(newSVuv( 53 ))); }
+        while ( (n%59) == 0 ) {  n /= 59;  XPUSHs(sv_2mortal(newSVuv( 59 ))); }
+        while ( (n%61) == 0 ) {  n /= 61;  XPUSHs(sv_2mortal(newSVuv( 61 ))); }
+        while ( (n%67) == 0 ) {  n /= 67;  XPUSHs(sv_2mortal(newSVuv( 67 ))); }
+        while ( (n%71) == 0 ) {  n /= 71;  XPUSHs(sv_2mortal(newSVuv( 71 ))); }
+      }
+      if ( (n >= UVCONST(73*73)) && (gcd_ui(n, UVCONST(4132280413) != 1)) ) {
+        while ( (n%73) == 0 ) {  n /= 73;  XPUSHs(sv_2mortal(newSVuv( 73 ))); }
+        while ( (n%79) == 0 ) {  n /= 79;  XPUSHs(sv_2mortal(newSVuv( 79 ))); }
+        while ( (n%83) == 0 ) {  n /= 83;  XPUSHs(sv_2mortal(newSVuv( 83 ))); }
+        while ( (n%89) == 0 ) {  n /= 89;  XPUSHs(sv_2mortal(newSVuv( 89 ))); }
+        while ( (n%97) == 0 ) {  n /= 97;  XPUSHs(sv_2mortal(newSVuv( 97 ))); }
+      }
+
       do { /* loop over each remaining factor */
         /* In theory we can try to minimize work using is_definitely_prime(n)
          * but in practice it seems slower. */
@@ -235,15 +250,27 @@ _XS_factor(IN UV n)
                          ((n>>29) < 100000) ? 250000 :
                                               600000;
 
+ #if 0
+          if (!split_success && n < 1000000) {
+            nfactored += trial_factor(n, factored_stack+nfactored, 0);
+            n = 1;
+            break;
+          }
+ #endif
+
           /* Small factors will be found quite rapidly with this */
           if (!split_success) {
             split_success = pbrent_factor(n, tofac_stack+ntofac, 1500)-1;
             if (verbose) { if (split_success) printf("pbrent 1:  %"UVuf" %"UVuf"\n", tofac_stack[ntofac], tofac_stack[ntofac+1]); else printf("pbrent 0\n"); }
           }
 
-          /* SQUFOF does great with big numbers */
           if (!split_success) {
-            split_success = squfof_factor(n, tofac_stack+ntofac, sq_rounds)-1;
+            /* SQUFOF does very well with what's left after TD and Rho.
+             * On such input, racing SQUFOF is ~40% faster and has better
+             * success, but has input size restrictions. */
+            split_success = (n > (UV_MAX >> 3))
+                  ? squfof_factor(n, tofac_stack+ntofac, sq_rounds)-1
+                  : racing_squfof_factor(n, tofac_stack+ntofac, 0)-1;
             if (verbose) printf("squfof %d\n", split_success);
           }
 
@@ -354,6 +381,11 @@ squfof_factor(IN UV n, IN UV maxrounds = 4*1024*1024)
     SIMPLE_FACTOR(squfof_factor, n, maxrounds);
 
 void
+rsqufof_factor(IN UV n)
+  PPCODE:
+    SIMPLE_FACTOR(racing_squfof_factor, n, 0);
+
+void
 pbrent_factor(IN UV n, IN UV maxrounds = 4*1024*1024)
   PPCODE:
     SIMPLE_FACTOR(pbrent_factor, n, maxrounds);
diff --git a/examples/bench-factor-extra.pl b/examples/bench-factor-extra.pl
index 160f759..8a280da 100755
--- a/examples/bench-factor-extra.pl
+++ b/examples/bench-factor-extra.pl
@@ -36,6 +36,7 @@ sub test_at_digits {
     $nfactored{'pbrent'} += $calc_nfacs->(Math::Prime::Util::pbrent_factor($_, $rounds));
     $nfactored{'pminus1'} += $calc_nfacs->(Math::Prime::Util::pminus1_factor($_, $rounds));
     $nfactored{'squfof'} += $calc_nfacs->(Math::Prime::Util::squfof_factor($_, $sqrounds));
+    $nfactored{'rsqufof'} += $calc_nfacs->(Math::Prime::Util::rsqufof_factor($_));
     #$nfactored{'trial'} += $calc_nfacs->(Math::Prime::Util::trial_factor($_));
     #$nfactored{'fermat'} += $calc_nfacs->(Math::Prime::Util::fermat_factor($_, $rounds));
     $nfactored{'holf'} += $calc_nfacs->(Math::Prime::Util::holf_factor($_, $hrounds));
@@ -55,6 +56,7 @@ sub test_at_digits {
     "fermat"  => sub { Math::Prime::Util::fermat_factor($_, $rounds) for @nums },
     "holf"    => sub { Math::Prime::Util::holf_factor($_, $hrounds) for @nums },
     "squfof"  => sub { Math::Prime::Util::squfof_factor($_, $sqrounds) for @nums },
+    "rsqufof" => sub { Math::Prime::Util::rsqufof_factor($_) for @nums },
     "trial"   => sub { Math::Prime::Util::trial_factor($_) for @nums },
   };
   delete $lref->{'fermat'} if $digits >= 9;
diff --git a/examples/bench-miller-rabin.pl b/examples/bench-miller-rabin.pl
index 02c4478..ec11aab 100755
--- a/examples/bench-miller-rabin.pl
+++ b/examples/bench-miller-rabin.pl
@@ -1,9 +1,10 @@
 #!/usr/bin/env perl
 use strict;
 use warnings;
-#use Math::Primality;
+use Math::Primality;
 use Math::Prime::XS;
 use Math::Prime::Util '-nobigint';
+use Math::Prime::Util::GMP;
 #use Math::Prime::FastSieve;
 use Benchmark qw/:all/;
 use List::Util qw/min max/;
@@ -30,7 +31,16 @@ sub test_at_digits {
   print "miller_rabin for 1000 random $digits-digit numbers ($min_num - $max_num)\n";
 
   cmpthese($count,{
-    'M::P::U' => sub { Math::Prime::Util::miller_rabin($_,2,3,5,7,11,13,17) for @nums },
+    'MPU' => sub { Math::Prime::Util::is_strong_pseudoprime($_,2,3,5,7,11,13,17) for @nums },
+    'MPU GMP' => sub { Math::Prime::Util::GMP::is_strong_pseudoprime($_,2,3,5,7,11,13,17) for @nums },
+    'M:Primality' => sub { for (@nums) {
+                       Math::Primality::is_strong_pseudoprime($_,2) &&
+                       Math::Primality::is_strong_pseudoprime($_,3) &&
+                       Math::Primality::is_strong_pseudoprime($_,5) &&
+                       Math::Primality::is_strong_pseudoprime($_,7) &&
+                       Math::Primality::is_strong_pseudoprime($_,11) &&
+                       Math::Primality::is_strong_pseudoprime($_,13) &&
+                       Math::Primality::is_strong_pseudoprime($_,17); } },
   });
   print "\n";
 }
diff --git a/examples/bench-pp-count.pl b/examples/bench-pp-count.pl
old mode 100644
new mode 100755
diff --git a/examples/bench-pp-isprime.pl b/examples/bench-pp-isprime.pl
old mode 100644
new mode 100755
diff --git a/examples/bench-pp-sieve.pl b/examples/bench-pp-sieve.pl
old mode 100644
new mode 100755
diff --git a/lib/Math/Prime/Util.pm b/lib/Math/Prime/Util.pm
index e92c858..85bb493 100644
--- a/lib/Math/Prime/Util.pm
+++ b/lib/Math/Prime/Util.pm
@@ -1870,7 +1870,10 @@ same advantages and disadvantages as Fermat's method.
 
 =head2 squfof_factor
 
+=head2 rsqufof_factor
+
   my @factors = squfof_factor($n);
+  my @factors = rsqufof_factor($n);  # racing multiplier version
 
 Produces factors, not necessarily prime, of the positive number input.  An
 optional number of rounds can be given as a second parameter.  It is possible

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