[libmath-prime-util-perl] 21/59: More bignum fun

Partha P. Mukherjee ppm-guest at moszumanska.debian.org
Thu May 21 18:44:55 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 50222dfacb4a3c8186f5355c4ae383aed0cfd1bd
Author: Dana Jacobsen <dana at acm.org>
Date:   Mon Jul 2 02:20:28 2012 -0600

    More bignum fun
---
 lib/Math/Prime/Util.pm    | 17 ++++++++++++-----
 lib/Math/Prime/Util/PP.pm | 27 +++++++++++++++++++--------
 2 files changed, 31 insertions(+), 13 deletions(-)

diff --git a/lib/Math/Prime/Util.pm b/lib/Math/Prime/Util.pm
index 633370f..171371a 100644
--- a/lib/Math/Prime/Util.pm
+++ b/lib/Math/Prime/Util.pm
@@ -787,10 +787,9 @@ The main development of the module has been for working with Perl UVs, so
 support for these types of functions inside Perl now, I recommend L<Math::Pari>.
 
 The module is thread-safe and allows concurrency between Perl threads while
-still sharing a prime cache.  It is not itself multithreaded.  The one caveat
-is on Win32 (non-Cygwin) where you must use C<precalc> if the function will
-use primes (C<primes>, C<prime_count> greater than 900M,
-C<nth_prime> greater than 45M).
+still sharing a prime cache.  It is not itself multithreaded.  See the
+L<Limitations|/"LIMITATIONS"> section if you are using Win32 and threads in
+your program.
 
 
 =head1 BIGNUM SUPPORT
@@ -1300,6 +1299,11 @@ Print pseudoprimes base 17:
 
     perl -MMath::Prime::Util=:all -E 'my $n=$base|1; while(1) { print "$n " if miller_rabin($n,$base) && !is_prime($n); $n+=2; } BEGIN {$|=1; $base=17}'
 
+Print some primes above 64-bit range:
+
+    perl -MMath::Prime::Util=:all -Mbigint -E 'my $start=100000000000000000000; say join "\n", @{primes($start,$start+1000)}'
+    # Similar behavior:
+    # 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
 
@@ -1315,7 +1319,10 @@ to update to a more recent Perl.
 The module is thread-safe and should allow good concurrency on all platforms
 that support Perl threads except Win32 (Cygwin works).  With Win32, either
 don't use threads or make sure C<prime_precalc> is called before using
-C<primes>, C<prime_count>, or C<nth_prime> with large inputs.
+C<primes>, C<prime_count>, or C<nth_prime> with large inputs.  This is B<only>
+an issue if you use non-Cygwin Win32 and call these routines from within
+Perl threads.
+
 
 
 =head1 PERFORMANCE
diff --git a/lib/Math/Prime/Util/PP.pm b/lib/Math/Prime/Util/PP.pm
index e208a1c..684ecb0 100644
--- a/lib/Math/Prime/Util/PP.pm
+++ b/lib/Math/Prime/Util/PP.pm
@@ -76,12 +76,13 @@ my @_prevwheel30 = (29,29,1,1,1,1,1,1,7,7,7,7,11,11,13,13,13,13,17,17,19,19,19,1
 sub _is_prime7 {  # n must not be divisible by 2, 3, or 5
   my($n) = @_;
 
-  return is_prob_prime($n) if $n > 10_000_000;
-
   foreach my $i (qw/7 11 13 17 19 23 29/) {
     return 2 if $i*$i > $n;
     return 0 if ($n % $i) == 0;
   }
+
+  return is_prob_prime($n) if $n > 10_000_000;
+
   my $limit = int(sqrt($n));
   my $i = 31;
   while (($i+30) <= $limit) {
@@ -313,11 +314,21 @@ sub next_prime {
   my($n) = @_;
   croak "Input must be a positive integer" unless _is_positive_int($n);
   return 0 if ($n >= ((_PP_prime_maxbits == 32) ? 4294967291 : 18446744073709551557))
-              && (!defined $bigint::VERSION);
+              && (!defined $Math::BigInt::VERSION);
   return $_prime_next_small[$n] if $n <= $#_prime_next_small;
 
-  my $d = int($n/30);
-  my $m = $n - $d*30;
+  if (ref($n) =~ /^Math::Big/) {
+    $n = $n->numify if $n <= ~0;
+  } elsif ($n > ~0) {
+    $n = Math::BigInt->new($n);
+  }
+
+  # Be careful trying to do:
+  #     my $d = int($n/30);
+  #     my $m = $n - $d*30;
+  # See:  int(9999999999999999403 / 30) => 333333333333333312  (off by 1)
+  my $m = $n % 30;
+  my $d = int( ($n - $m) / 30 );
   if ($m == 29) { $d++;  $m = 1;} else { $m = $_nextwheel30[$m]; }
   while (!_is_prime7($d*30+$m)) {
     $m = $_nextwheel30[$m];
@@ -336,7 +347,7 @@ sub prev_prime {
   $n++ if ($n % 2) == 0;
   do {
     $n -= 2;
-  } while ( (($n % 3) == 0) || (!is_prime($n)) );
+  } while ( (($n % 3) == 0) || (($n % 5) == 0) || (!_is_prime7($n)) );
   $n;
 
   # This is faster for larger intervals, slower for short ones.
@@ -350,8 +361,8 @@ sub prev_prime {
   #}
   #$n;
 
-  #my $d = int($n/30);
-  #my $m = $n - $d*30;
+  #my $m = $n % 30;
+  #my $d = int( ($n - $m) / 30 );
   #do {
   #  $m = $_prevwheel30[$m];
   #  $d-- if $m == 29;

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