[libmath-prime-util-perl] 41/59: more fun with bigints and random primes
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 330a0a1cfa4709859815bbf27bad650be1d1099a
Author: Dana Jacobsen <dana at acm.org>
Date: Sun Jul 8 18:00:36 2012 -0600
more fun with bigints and random primes
---
lib/Math/Prime/Util.pm | 42 +++++++++++++++++++++---------------------
t/81-bignum.t | 2 +-
2 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/lib/Math/Prime/Util.pm b/lib/Math/Prime/Util.pm
index 672931a..891a922 100644
--- a/lib/Math/Prime/Util.pm
+++ b/lib/Math/Prime/Util.pm
@@ -298,7 +298,7 @@ sub primes {
# ~80m for 4096-bit
#
# A lot of this is due to is_prime on bigints however.
-#
+#
# 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;'
# perl -Iblib/lib -Iblib/arch -MMath::Prime::Util=:all -E 'my %freq; $n=1000000; $freq{random_prime(1260437,1260733)}++ for (1..$n); printf("%4d %6.3f%%\n", $_, 100.0*$freq{$_}/$n) for sort {$a<=>$b} keys %freq;'
@@ -311,18 +311,6 @@ sub primes {
# TODO: Look at RANDBITS if using system rand
my $rand_max_bits = 31;
my $rand_max_val = 1 << $rand_max_bits;
- my $_rdata = 0;
- my $_rbits = 0;
- my $get_rand_bit = sub {
- if ($_rbits == 0) {
- $_rdata = $irandf->($rand_max_val);
- $_rbits = $rand_max_bits;
- }
- my $r = $_rdata & 1;
- $_rdata >>= 1;
- $_rbits--;
- $r;
- };
# Returns a uniform number between [0,$range] inclusive. The straightforward
# method of getting a number of rand bits equal to the number of bits in the
@@ -330,11 +318,12 @@ sub primes {
# falls within the desired range.
my $get_rand_range = sub {
my($range) = @_;
+ return 0 if $range <= 0;
my $rbits = 0;
if (ref($range) eq 'Math::BigInt') {
$rbits = length($range->as_bin) - 2;
} else {
- my $t = $range - 1;
+ my $t = $range;
while ($t) { $rbits++; $t >>= 1; }
}
while (1) {
@@ -349,7 +338,6 @@ sub primes {
}
};
-
# Sub to call with low and high already primes and verified range.
my $_random_prime = sub {
my($low,$high) = @_;
@@ -382,6 +370,7 @@ sub primes {
# not implementing it now because it seems like a rare case.
if ($oddrange <= $rand_max_val) {
+ $oddrange = int($oddrange->bstr) if ref($oddrange) eq 'Math::BigInt';
# Our range is small enough we can just call rand once and be happy.
# Generate random numbers in the interval until one is prime.
my $loop_limit = 2000 * 1000; # To protect against broken rand
@@ -409,12 +398,23 @@ sub primes {
# 2) randomly select one of the partitions.
# 3) iterate choosing random values within the partition.
- my $nbins = int( ($oddrange + $rand_max_val - 1) / $rand_max_val );
- my $binsize = int( ($oddrange + $nbins - 1) / $nbins );
- my $nparts = int( $oddrange / $binsize );
-
+ my($binsize, $nparts);
+ if (ref($oddrange) eq 'Math::BigInt') {
+ # Go to some trouble here because some systems are wonky, such as
+ # giving us +a/+b = -r.
+ my($nbins, $rem);
+ ($nbins, $rem) = $oddrange->copy->bdiv("$rand_max_val");
+ $nbins++ if $rem > 0;
+ ($binsize,$rem) = $oddrange->copy->bdiv($nbins);
+ $binsize++ if $rem > 0;
+ $nparts = $oddrange->copy->bdiv($binsize);
+ } else {
+ my $nbins = int( ($oddrange + $rand_max_val - 1) / $rand_max_val );
+ $binsize = int( ($oddrange + $nbins - 1) / $nbins );
+ $nparts = int( $oddrange / $binsize );
+ }
+
my $rpart = $get_rand_range->($nparts);
- #my $rpart = (($irandf->($rand_max_val) << 31) + $irandf->($rand_max_val)) % $nparts;
my $primelow = $low + 2 * $binsize * $rpart;
my $partsize = ($rpart < $nparts) ? $binsize
@@ -1650,7 +1650,7 @@ the configuration, so changing it has no effect. The settings include:
maxdigits the max digits in a number, without bigint
maxprime the largest representable prime, without bigint
maxprimeidx the index of maxprime, without bigint
-
+
=head1 FACTORING FUNCTIONS
diff --git a/t/81-bignum.t b/t/81-bignum.t
index 75d7f7e..59523cf 100644
--- a/t/81-bignum.t
+++ b/t/81-bignum.t
@@ -69,7 +69,7 @@ plan tests => 0 +
12 + # random primes
0;
-# Using GMP makes these tests run about 2x faster on my machine
+# Using GMP makes these tests run about 2x faster on some machines
use bigint try => 'GMP'; # <--------------- large numbers ahead! > 2^64
use Math::Prime::Util qw/
--
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