[libmath-prime-util-perl] 42/59: Use the MPU:GMP module if we can

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


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

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

commit 3d981b4c1696b8b5c8f0d69437fc114ee8d4d3dc
Author: Dana Jacobsen <dana at acm.org>
Date:   Sun Jul 8 22:48:13 2012 -0600

    Use the MPU:GMP module if we can
---
 lib/Math/Prime/Util.pm | 91 ++++++++++++++++++++++++++++----------------------
 1 file changed, 51 insertions(+), 40 deletions(-)

diff --git a/lib/Math/Prime/Util.pm b/lib/Math/Prime/Util.pm
index 891a922..e9de7d0 100644
--- a/lib/Math/Prime/Util.pm
+++ b/lib/Math/Prime/Util.pm
@@ -53,8 +53,6 @@ BEGIN {
 
   # Load PP code.  Nothing exported.
   require Math::Prime::Util::PP;
-  # There is no GMP module yet
-  $_Config{'gmp'} = 0;
 
   eval {
     require XSLoader;
@@ -80,7 +78,13 @@ BEGIN {
     *pbrent_factor  = \&Math::Prime::Util::PP::pbrent_factor;
     *prho_factor    = \&Math::Prime::Util::PP::prho_factor;
     *pminus1_factor = \&Math::Prime::Util::PP::pminus1_factor;
-  }
+  };
+
+  # See if they have the GMP module
+  $_Config{'gmp'} = 0;
+  $_Config{'gmp'} = 1 if eval { require Math::Prime::Util::GMP;
+                                Math::Prime::Util::GMP->import();
+                                1; };
 }
 END {
   _prime_memfreeall;
@@ -102,6 +106,7 @@ if ($_Config{'maxbits'} == 32) {
 #    return _XS_foo($n)  if $n <= $_XS_MAXVAL
 # which builds into one scalar whether XS is available and if we can call it.
 my $_XS_MAXVAL = $_Config{'xs'}  ?  $_Config{'maxparam'}  :  -1;
+my $_HAVE_GMP = $_Config{'gmp'};
 
 # Notes on how we're dealing with big integers:
 #
@@ -277,9 +282,9 @@ sub primes {
 #    1) Joye and Paillier have patents on their methods.  Never use them.
 #
 #    2) The easy-peasy method of next_prime(random number) is fast but gives
-#       gives a terribly distribution, and not only in the obvious positive
-#       bias.  The probability for a prime is proportional to its gap, which
-#       is really a bad distribution.
+#       a terribly distribution, and not only in the obvious positive bias.
+#       The probability for a prime is proportional to its gap, which is
+#       really a bad distribution.
 #
 # For standard random primes, the implementation is very similar to Fouque's
 # Algorithm 1.  For ranges of 32-bits or less, the distribution is uniform.
@@ -287,17 +292,17 @@ sub primes {
 #
 # The random_maurer_prime function uses Maurer's algorithm of course.
 #
-# The current code is reasonably fast for native, but very slow for bigints.
-#      70uS for   24-bit
-#     0.01s for   64-bit
-#     0.2s  for  128-bit
-#     1s    for  256-bit
-#    10s    for  512-bit
-#   1m      for 1024-bit
-#  ~4m      for 2048-bit
-# ~80m      for 4096-bit
-#
-# A lot of this is due to is_prime on bigints however.
+# The current code is reasonably fast for native, but slow for bigints.
+#    n-bits      no GMP      with MPU::GMP
+#    ----------  ----------  --------------
+#       24-bit         70uS
+#       64-bit       0.01s       0.01s
+#      128-bit       0.2s        0.02s
+#      256-bit       1s          0.04s
+#      512-bit      10s          0.1s
+#     1024-bit     1m            0.5s
+#     2048-bit    ~4m            5s
+#     4096-bit   ~80m           35s
 #
 # To verify distribution:
 #   perl -Iblib/lib -Iblib/arch -MMath::Prime::Util=:all -E 'my %freq; $n=1000000; $freq{random_nbit_prime(6)}++ for (1..$n); printf("%4d %6.3f%%\n", $_, 100.0*$freq{$_}/$n) for sort {$a<=>$b} keys %freq;'
@@ -430,11 +435,10 @@ sub primes {
       $prime = $primelow + ( 2 * $irandf->($partsize) );
       croak "random prime failure, $prime > $high" if $prime > $high;
       croak "Random function broken?" if $loop_limit-- < 0;
-      if (ref($prime) eq 'Math::BigInt') {
-        next if $prime > 53 && Math::BigInt::bgcd($prime, "16294579238595022365") != 1;
-      } else {
-        next if $prime > 13 && (!($prime % 3) || !($prime % 5) || !($prime % 7) || !($prime % 11) || !($prime % 13));
-      }
+      # If we are a small int, then some mods are good.
+      # If we're a bigint and have MPU:GMP installed then everything here is
+      # wasteful.  If we're a bigint without MPU:GMP, then a bgcd is faster.
+      next if $prime > 11 && (!($prime % 3) || !($prime % 5) || !($prime % 7) || !($prime % 11));
       do { $prime = 2; last; } if $prime == 1;   # special case for low = 2
       last if is_prime($prime);
     }
@@ -707,6 +711,7 @@ sub is_prime {
   _validate_positive_integer($n);
 
   return _XS_is_prime($n) if $n <= $_XS_MAXVAL;
+  return Math::Prime::Util::GMP::is_prime($n, @_) if $_HAVE_GMP;
   return is_prob_prime($n);
 }
 
@@ -762,11 +767,15 @@ sub is_strong_pseudoprime {
   _validate_positive_integer($n);
   # validate bases?
   return _XS_miller_rabin($n, @_) if $n <= $_XS_MAXVAL;
+  return Math::Prime::Util::GMP::is_strong_pseudoprime($n, @_) if $_HAVE_GMP;
   return Math::Prime::Util::PP::miller_rabin($n, @_);
 }
 
 sub is_strong_lucas_pseudoprime {
-  return Math::Prime::Util::PP::is_strong_lucas_pseudoprime(@_);
+  my($n) = shift;
+  _validate_positive_integer($n);
+  return Math::Prime::Util::GMP::is_strong_lucas_pseudoprime("$n") if $_HAVE_GMP;
+  return Math::Prime::Util::PP::is_strong_lucas_pseudoprime($n);
 }
 
 sub miller_rabin {
@@ -802,6 +811,7 @@ sub is_prob_prime {
   _validate_positive_integer($n);
 
   return _XS_is_prob_prime($n) if $n <= $_XS_MAXVAL;
+  return Math::Prime::Util::GMP::is_prob_prime($n, @_) if $_HAVE_GMP;
 
   return 2 if $n == 2 || $n == 3 || $n == 5 || $n == 7;
   return 0 if $n < 11;
@@ -1221,18 +1231,17 @@ and more.
 
 The default sieving and factoring are intended to be (and currently are)
 the fastest on CPAN, including L<Math::Prime::XS>, L<Math::Prime::FastSieve>,
-L<Math::Factor::XS>, and L<Math::Prime::TiedArray>.  For numbers in the 10-20
-digit range, it is often orders of magnitude faster.  Typically it is faster
-than L<Math::Pari> for 64-bit operations, with the exception of factoring
-certain 16-20 digit numbers.
+L<Math::Factor::XS>, L<Math::Prime::TiedArray>, and L<Math::Primality> (when
+the GMP module is available).  For numbers in the 10-20 digit range, it is
+often orders of magnitude faster.  Typically it is faster than L<Math::Pari>
+for 64-bit operations, with the exception of factoring certain 16-20 digit
+numbers.
 
 The main development of the module has been for working with Perl UVs, so
-32-bit or 64-bit.  Bignum support is limited.  On advantage is that it requires
-no external software (e.g. GMP or Pari).  If you need full bignum support for
-these types of functions inside Perl now, I recommend L<Math::Pari>.
-While this module contains all the functionality of L<Math::Primality> and is
-much faster on 64-bit input, L<Math::Primality> is much faster than we are
-for bigints.  This is being addressed.
+32-bit or 64-bit.  Bignum support is still experimental.  One advantage is
+that it requires no external software (e.g. GMP or Pari).  For much faster
+performance for bigints, install the L<Math::Prime::Util::GMP> module.  I
+also recommend L<Math::Pari> for these types of operations on big numbers.
 
 The module is thread-safe and allows concurrency between Perl threads while
 still sharing a prime cache.  It is not itself multithreaded.  See the
@@ -1243,9 +1252,8 @@ your program.
 =head1 BIGNUM SUPPORT
 
 By default all functions support bigints.  Performance on bigints is not very
-good however, as currently it is all using the core bigint / bignum routines.
-Some of these performance concerns will be addressed in later versions, and
-should all be hidden.
+good without the L<Math::Prime::Util::GMP> module, as all operations then
+use the bigint / bignum routines from Perl core.
 
 Some of the functions, notably:
 
@@ -1554,8 +1562,8 @@ set will be uniformly selected, with randomness supplied via calls to the
 L<rand> function as described above.
 
 This the trivial algorithm to select primes from a range.  This gives a uniform
-distribution, however it is quite slow for bigints, where the C<is_prime>
-function is a limiter.
+distribution and can be extremely fast.  When used with bigints, having the
+L<Math::Prime::Util::GMP> module installed will make it run much faster.
 
 
 =head2 random_maurer_prime
@@ -1809,6 +1817,7 @@ Print some primes above 64-bit range:
     # Similar but much faster:
     # perl -MMath::Pari=:int,PARI,nextprime -E 'my $start = PARI "100000000000000000000"; my $end = $start+1000; my $p=nextprime($start); while ($p <= $end) { say $p; $p = nextprime($p+1); }'
 
+
 =head1 LIMITATIONS
 
 I have not completed testing all the functions near the word size limit
@@ -1892,8 +1901,10 @@ The differences are in the implementations:
      MR tests, while above 4759123141 it performs a BPSW test.  This is is
      fantastic for bigints over 2^64, but it is significantly slower than
      native precision tests.  With 64-bit numbers it is generally an order of
-     magnitude or more slower than any of the others.  This reverses when
-     numbers get larger.
+     magnitude or more slower than any of the others.  Once bigints are being
+     used, its performance is quite good.  It is an order of magnitude or more
+     faster than this module by default, but installing the
+     L<Math::Prime::Util::GMP> module makes this code run slightly faster.
 
    - L<Math::Pari> has some very effective code, but it has some overhead to get
      to it from Perl.  That means for small numbers it is relatively slow: an

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