[libmath-prime-util-perl] 27/29: Rewrite PP Lucas code. About same speed, but simpler.

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


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

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

commit 8c499eef738d4ba62e7408ea11ac978df59e1697
Author: Dana Jacobsen <dana at acm.org>
Date:   Sun May 19 04:10:53 2013 -0700

    Rewrite PP Lucas code.  About same speed, but simpler.
---
 lib/Math/Prime/Util/PP.pm | 53 ++++++++++++++++-------------------------------
 util.c                    |  7 ++++++-
 2 files changed, 24 insertions(+), 36 deletions(-)

diff --git a/lib/Math/Prime/Util/PP.pm b/lib/Math/Prime/Util/PP.pm
index 6d76fcd..a3df0c7 100644
--- a/lib/Math/Prime/Util/PP.pm
+++ b/lib/Math/Prime/Util/PP.pm
@@ -942,51 +942,34 @@ sub is_strong_lucas_pseudoprime {
   my $ZERO = $n->copy->bzero;
   my $U = $ZERO + 1;
   my $V = $ZERO + $P;
-  my $U_2m = $U->copy;
-  my $V_2m = $V->copy;
-  my $Q_m = $ZERO + $Q;
-  my $Q_m2 = $Q_m->copy->bmul(2);
-  my $Qkd = $Q_m->copy;
-  substr($dstr,-1) = '';   #$d->brsft(1);
-  #my $i = 1;
-  while ($dstr ne '') {    #while (!$d->is_zero) {
-    #warn "U=$U  V=$V  Qm=$Q_m  Qm2=$Q_m2\n";
-    $U_2m->bmul($V_2m);             $U_2m->bmod($n);
-    $V_2m->bmuladd($V_2m, -$Q_m2);  $V_2m->bmod($n);
-    #warn "  $i  U2m=$U_2m  V2m=$V_2m\n";  $i++;
-    $Q_m->bmul($Q_m);               $Q_m->bmod($n);
-    $Q_m2 = $Q_m->copy->bmul(2);    # no mod
-    if (substr($dstr,-1)) {   #if ($d->is_odd) {
-      my $T1 = $U_2m->copy->bmul($V);
-      my $T2 = $U_2m->copy->bmul($U)->bmul($D);
-      $U->bmuladd($V_2m, $T1);         # U = U*V_2m + V*U_2m
-      $U->badd($n) if $U->is_odd;      # U += n if U & 1
-      $U->brsft(1,2);                  # U = floor(U / 2)
-      $U->bmod($n);                    # U = U % n
-
-      $V->bmuladd($V_2m, $T2);
+  my $Qk = $ZERO + $Q;
+  my $bpos = 0;
+  while ($bpos++ < length($dstr)) {
+    $U = ($U * $V) % $n;
+    $V = ($V * $V - 2*$Qk) % $n;
+    $Qk = ($Qk * $Qk) % $n;
+    if (substr($dstr,$bpos,1)) {
+      my $T1 = $U->copy->bmul($D);
+      $U->badd($V);
+      $U->badd($n) if $U->is_odd;
+      $U->brsft(1);
+      $U->bmod($n);
+
+      $V->badd($T1);
       $V->badd($n) if $V->is_odd;
-      $V->brsft(1,2);
+      $V->brsft(1);
       $V->bmod($n);
 
-      $Qkd->bmul($Q_m);
-      $Qkd->bmod($n);
+      $Qk = ($Qk * $Q) % $n;
     }
-    substr($dstr,-1) = '';   #$d->brsft(1);
   }
-  #warn "l0 U=$U  V=$V\n";
   return 1 if $U->is_zero || $V->is_zero;
 
   # Compute powers of V
-  my $Qkd2 = $Qkd->copy->bmul(2);
   foreach my $r (1 .. $s-1) {
-    #warn "l$r U=$U  V=$V  Qkd2=$Qkd2\n";
-    $V->bmuladd($V, -$Qkd2);  $V->bmod($n);
+    $V = ($V * $V - 2*$Qk) % $n;
     return 1 if $V->is_zero;
-    if ($r < ($s-1)) {
-      $Qkd->bmul($Qkd);  $Qkd->bmod($n);
-      $Qkd2 = $Qkd->copy->bmul(2);
-    }
+    $Qk = ($Qk * $Qk) % $n if $r < ($s-1);
   }
   return 0;
 }
diff --git a/util.c b/util.c
index ffcf524..638c572 100644
--- a/util.c
+++ b/util.c
@@ -634,10 +634,15 @@ UV _XS_nth_prime(UV n)
   MPUassert(upper_limit > 0, "nth_prime got an upper limit of 0");
 
   /* For relatively small values, generate a sieve and count the results.
+   *
    * For larger values, compute a lower bound, use Lehmer's algorithm to get
    * a fast prime count, then start segment sieving from there.
+   *
+   * For very large values, binary search on Riemann's R function to get a
+   * good approximation, use Lehmer's algorithm to get the count, then walk
+   * backwards or sieve forwards.
    */
-  if (upper_limit <= 1*1024*1024*30) {
+  if (upper_limit <= 32*1024*30) {
     /* Generate a sieve and count. */
     segment_size = get_prime_cache(upper_limit, &cache_sieve) / 30;
     /* Count up everything in the cached sieve. */

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