[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