[libmath-prime-util-perl] 47/72: Dynamically load BRS; PP random_nbit_prime speedup
Partha P. Mukherjee
ppm-guest at moszumanska.debian.org
Thu May 21 18:49:40 UTC 2015
This is an automated email from the git hooks/post-receive script.
ppm-guest pushed a commit to annotated tag v0.32
in repository libmath-prime-util-perl.
commit 92831b636ddb417a9d07ba988c92f43eb8ce829e
Author: Dana Jacobsen <dana at acm.org>
Date: Wed Sep 25 17:55:47 2013 -0700
Dynamically load BRS; PP random_nbit_prime speedup
---
Changes | 2 ++
lib/Math/Prime/Util.pm | 87 ++++++++++++++++++++++----------------------------
2 files changed, 40 insertions(+), 49 deletions(-)
diff --git a/Changes b/Changes
index 3657197..810e5c4 100644
--- a/Changes
+++ b/Changes
@@ -46,6 +46,8 @@ Revision history for Perl module Math::Prime::Util
- Bytes::Random::Secure is loaded only when random prime functionality
is used. Shaves a few milliseconds and bytes off of startup.
+ - Speedup for Perl (no GMP) primality and random nbit primes.
+
0.31 2013-08-07
- Change proof certificate documentation to reflect the new text format.
diff --git a/lib/Math/Prime/Util.pm b/lib/Math/Prime/Util.pm
index 260bd2f..a26a375 100644
--- a/lib/Math/Prime/Util.pm
+++ b/lib/Math/Prime/Util.pm
@@ -2,7 +2,6 @@ package Math::Prime::Util;
use strict;
use warnings;
use Carp qw/croak confess carp/;
-use Bytes::Random::Secure;
BEGIN {
$Math::Prime::Util::AUTHORITY = 'cpan:DANAJ';
@@ -128,16 +127,6 @@ BEGIN {
1; };
}
- # Try to figure out a system rand configuration that works for us.
- # Using something other than the craptastic system rand would be best.
- use Config;
- $_Config{'system_randbits'} = $Config{'randbits'};
- # Keep things in integer range.
- $_Config{'system_randbits'} = $_Config{'maxbits'}-1 if $_Config{'system_randbits'} >= $_Config{'maxbits'};
- # drand48 has an alternating last bit on almost every system.
- $_Config{'system_randbits'}-- if $_Config{'system_randbits'} == 48;
- no Config;
-
}
END {
_prime_memfreeall;
@@ -398,8 +387,8 @@ sub primes {
# For random primes, there are two good papers that should be examined:
#
-# "Fast Generation of Prime Numbers and Secure Public-Key Cryptographic Parameters"
-# by Ueli M. Maurer, 1995
+# "Fast Generation of Prime Numbers and Secure Public-Key
+# Cryptographic Parameters" by Ueli M. Maurer, 1995
# http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.26.2151
# related discussions:
# http://www.daimi.au.dk/~ivan/provableprimesproject.pdf
@@ -409,42 +398,42 @@ sub primes {
# by Pierre-Alain Fouque and Mehdi Tibouchi, 2011
# http://eprint.iacr.org/2011/481
#
-#
# Some things to note:
#
# 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
-# 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.
+# 2) The easy method of next_prime(random number), known as PRIMEINC, is
+# fast but gives a terrible distribution. It has a positive bias and
+# most importantly the probability for a prime is proportional to its
+# gap, which makes a terrible distribution (some numbers in the range
+# will be thousands of times more likely than others).
#
-# In this code, for ranges within randbits (typically 48 on UNIX system rand,
-# 31 for user-provided rand, and 16 for most Win32 systems), the results
-# are completely uniform. For larger ranges it is close.
+# We use:
+# TRIVIAL range within native integer size (2^32 or 2^64)
+# FTA1 random_nbit_prime with 65+ bits
+# INVA1 other ranges with 65+ bit range
+# where
+# TRIVIAL = monte-carlo method or equivalent, perfect uniformity.
+# FTA1 = Fouque/Tibouchi A1, very close to uniform
+# INVA1 = inverted FTA1, less uniform but works with arbitrary ranges
#
# The random_maurer_prime function uses Maurer's FastPrime algorithm.
#
-# These functions are quite fast for native size inputs, and reasonably fast
-# for bigints. Some factors that make a significant difference:
-# - Is Math::Prime::Util::GMP installed?
-# - Using Math::BigInt::GMP or Math::BigInt::Pari? Very important.
-# - Which platform? Typically x86_64 is best optimized.
-# - If using system rand, is RANDBITS large?
-# - What RNG?
+# If Math::Prime::Util::GMP is installed, these functions will be many times
+# faster than other methods (e.g. Math::Pari monte-carlo or Crypt::Primes).
#
-# Timings using Math::BigInt::GMP, x86_64, system rand with 32+ randbits.
+# Timings on x86_64, with Math::BigInt::GMP and Math::Random::ISAAC::XS.
#
# random_nbit_prime random_maurer_prime
# n-bits no GMP w/ MPU::GMP no GMP w/ MPU::GMP
# ---------- -------- ----------- -------- -----------
-# 24-bit 25uS same same same
-# 64-bit 87uS same same same
-# 128-bit 0.032s 0.0049s 0.098s 0.056s
-# 256-bit 0.062s 0.0097s 0.25s 0.15s
-# 512-bit 0.13s 0.019s 0.65s 0.30s
-# 1024-bit 0.28s 0.058s 1.3s 0.94s
-# 2048-bit 0.91s 0.4s 3.2s 3.1s
+# 24-bit 27uS same same same
+# 64-bit 97uS same same same
+# 128-bit 0.017s 0.0020s 0.098s 0.056s
+# 256-bit 0.033s 0.0033s 0.25s 0.15s
+# 512-bit 0.066s 0.0093s 0.65s 0.30s
+# 1024-bit 0.16s 0.060s 1.3s 0.94s
+# 2048-bit 0.83s 0.5s 3.2s 3.1s
# 4096-bit 6.6s 4.0s 23s 12.0s
#
# Writing these entirely in GMP has a problem, which is that we want to use
@@ -452,14 +441,11 @@ sub primes {
# possibility is to, if they do not supply a rand function, use the GMP MT
# function with an appropriate seed.
#
-# It will generate primes with more bits, but it slows down a lot. The
-# time variation becomes quite extreme once bit sizes get over 6000 or so.
-#
# Random timings for 10M calls:
# 1.92 system rand
# 2.62 Math::Random::MT::Auto
# 12.0 Math::Random::Secure w/ISAAC::XS
-# 12.6 Bytes::Random::Secure OO w/ISAAC::XS
+# 12.6 Bytes::Random::Secure OO w/ISAAC::XS <==== our default
# 31.1 Bytes::Random::Secure OO
# 44.5 Bytes::Random::Secure function w/ISAAC::XS
# 44.8 Math::Random::Secure
@@ -529,6 +515,7 @@ sub primes {
# with bad system rand functions.
my $irandf = $_Config{'irand'};
if (!defined $irandf) {
+ require Bytes::Random::Secure;
$_BRS = Bytes::Random::Secure->new(NonBlocking=>1) unless defined $_BRS;
$irandf = sub { return $_BRS->irand(); };
}
@@ -569,6 +556,7 @@ sub primes {
sub _get_nbit_rand_func {
my $irandf = $_Config{'irand'};
if (!defined $irandf) {
+ require Bytes::Random::Secure;
$_BRS = Bytes::Random::Secure->new(NonBlocking=>1) unless defined $_BRS;
return sub {
my($bits) = @_;
@@ -940,10 +928,13 @@ sub primes {
next unless Math::BigInt::bgcd($p, $_big_gcd[2]) == 1;
next unless Math::BigInt::bgcd($p, $_big_gcd[3]) == 1;
}
- next unless is_prob_prime($p);
+ # We know we don't have GMP and are > 2^64, so skip all the middle.
+ #next unless is_prob_prime($p);
+ next unless Math::Prime::Util::PP::miller_rabin($p, 2);
+ next unless Math::Prime::Util::PP::is_extra_strong_lucas_pseudoprime($p);
}
return $p;
- }
+ }
croak "Random function broken?";
}
@@ -1650,7 +1641,7 @@ sub carmichael_lambda {
my @factors = grep { !$factor_mult{$_}++ }
($n <= $_XS_MAXVAL) ? _XS_factor($n) : factor($n);
$factor_mult{2}-- if defined $factor_mult{2} && $factor_mult{2} > 2;
-
+
if (!defined $Math::BigInt::VERSION) {
eval { require Math::BigInt; Math::BigInt->import(try=>'GMP,Pari'); 1; }
or do { croak "Cannot load Math::BigInt"; };
@@ -1751,8 +1742,7 @@ sub _generic_is_prime {
if ref($_[0]) ne 'Math::BigInt' && $n <= $_XS_MAXVAL;
return Math::Prime::Util::GMP::is_prime($n) if $_HAVE_GMP;
- return 2 if ($n == 2) || ($n == 3) || ($n == 5); # 2, 3, 5 are prime
- return 0 if $n < 7; # everything else below 7 is composite
+ if ($n < 7) { return ($n == 2) || ($n == 3) || ($n == 5) ? 2 : 0; }
return 0 if !($n % 2) || !($n % 3) || !($n % 5);
return Math::Prime::Util::PP::_is_prime7($n);
}
@@ -1770,8 +1760,7 @@ sub _generic_is_prob_prime {
if ref($_[0]) ne 'Math::BigInt' && $n <= $_XS_MAXVAL;
return Math::Prime::Util::GMP::is_prob_prime($n) if $_HAVE_GMP;
- return 2 if ($n == 2) || ($n == 3) || ($n == 5); # 2, 3, 5 are prime
- return 0 if $n < 7; # everything else below 7 is composite
+ if ($n < 7) { return ($n == 2) || ($n == 3) || ($n == 5) ? 2 : 0; }
return 0 if !($n % 2) || !($n % 3) || !($n % 5);
return Math::Prime::Util::PP::_is_prime7($n);
}
@@ -3688,7 +3677,7 @@ will be seen. This is removes from consideration such algorithms as
C<PRIMEINC>, which although efficient, gives very non-random output. This
also implies that the numbers will not be evenly distributed, since the
primes are not evenly distributed. Stated again, the random prime functions
-return a uniformly selected prime from the set of primes within the range.
+return a uniformly selected prime from the set of primes within the range.
Hence given C<random_prime(1000)>, the numbers 2, 3, 487, 631, and 997 all
have the same probability of being returned.
@@ -3774,7 +3763,7 @@ on the values within the partition, which very slightly skews the results
towards smaller numbers).
The C<irand> function is used for randomness, so all the discussion in
-L</random_prime> about that applies here.
+L</random_prime> about that applies here.
The result will be a BigInt if the number of bits is greater than the native
bit size. For better performance with large bit sizes, install
L<Math::Prime::Util::GMP>.
--
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