[libmath-prime-util-perl] 46/72: Speedup lucas sequence => speedup BPSW test
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 6100612299d322c48fd54e44d4471b80e67ba4d7
Author: Dana Jacobsen <dana at acm.org>
Date: Wed Sep 25 17:54:01 2013 -0700
Speedup lucas sequence => speedup BPSW test
---
lib/Math/Prime/Util/PP.pm | 66 ++++++++++++++++++++++++++++-------------------
1 file changed, 40 insertions(+), 26 deletions(-)
diff --git a/lib/Math/Prime/Util/PP.pm b/lib/Math/Prime/Util/PP.pm
index 957d6f1..4fde2ab 100644
--- a/lib/Math/Prime/Util/PP.pm
+++ b/lib/Math/Prime/Util/PP.pm
@@ -799,13 +799,18 @@ sub miller_rabin {
if ( ref($n) eq 'Math::BigInt' ) {
- my $s = 0;
my $nminus1 = $n->copy->bdec();
+ my $s = 0;
my $d = $nminus1->copy;
while ($d->is_even) {
$s++;
$d->brsft(1);
}
+ # Different way of doing the above. Fewer function calls, slower on ave.
+ #my $dbin = $nminus1->as_bin;
+ #my $last1 = rindex($dbin, '1');
+ #my $s = length($dbin)-2-$last1+1;
+ #my $d = $nminus1->copy->brsft($s);
foreach my $a (@bases) {
my $x = $n->copy->bzero->badd($a)->bmodpow($d,$n);
@@ -959,9 +964,6 @@ sub lucas_sequence {
croak "lucas_sequence: P out of range" if $P < 0 || $P >= $n;
croak "lucas_sequence: Q out of range" if $Q >= $n;
- my $D = $P*$P - 4*$Q;
- croak "lucas_sequence: D is zero" if $D == 0;
-
if (ref($n) ne 'Math::BigInt') {
if (!defined $Math::BigInt::VERSION) {
eval { require Math::BigInt; Math::BigInt->import(try=>'GMP,Pari'); 1; }
@@ -971,9 +973,15 @@ sub lucas_sequence {
}
my $ZERO = $n->copy->bzero;
- my $U = $ZERO + 1;
- my $V = $ZERO + $P;
- my $Qk = $ZERO + $Q;
+ my $ONE = $ZERO + 1;
+ my $TWO = $ZERO + 2;
+ $P = $ZERO+$P unless ref($P) eq 'Math::BigInt';
+ $Q = $ZERO+$Q unless ref($Q) eq 'Math::BigInt';
+ my $D = $P*$P - 4*$Q;
+ croak "lucas_sequence: D is zero" if $D == 0;
+ my $U = $ONE->copy;
+ my $V = $P->copy;
+ my $Qk = $Q->copy;
return ($ZERO, $ZERO+2) if $k == 0;
$k = Math::BigInt->new("$k") unless ref($k) eq 'Math::BigInt';
@@ -981,53 +989,59 @@ sub lucas_sequence {
my $bpos = 0;
if ($Q == 1) {
- my $Dinverse = ($ZERO+$D)->bmodinv($n);
- if ($P > 2 && !$Dinverse->is_nan) {
+ my $Dinverse = $D->copy->bmodinv($n);
+ if ($P > $TWO && !$Dinverse->is_nan) {
# Calculate V_k with U=V_{k+1}
- $U = $ZERO + ($P*$P - 2);
+ $U = $P->copy->bmul($P)->bsub($TWO)->bmod($n);
while (++$bpos < length($kstr)) {
if (substr($kstr,$bpos,1)) {
- $V->bmul($U)->bsub($P)->bmod($n);
- $U->bmul($U)->bsub( 2)->bmod($n);
+ $V->bmul($U)->bsub($P )->bmod($n);
+ $U->bmul($U)->bsub($TWO)->bmod($n);
} else {
- $U->bmul($V)->bsub($P)->bmod($n);
- $V->bmul($V)->bsub( 2)->bmod($n);
+ $U->bmul($V)->bsub($P )->bmod($n);
+ $V->bmul($V)->bsub($TWO)->bmod($n);
}
}
# Crandall and Pomerance eq 3.13: U_n = D^-1 (2V_{n+1} - PV_n)
- $U = $Dinverse * (2*$U - $P*$V);
+ $U = $Dinverse * ($TWO*$U - $P*$V);
} else {
while (++$bpos < length($kstr)) {
- $U = ($U * $V) % $n;
- $V = ($V * $V - 2) % $n;
+ $U->bmul($V)->bmod($n);
+ $V->bmul($V)->bsub($TWO)->bmod($n);
if (substr($kstr,$bpos,1)) {
my $T1 = $U->copy->bmul($D);
- $U->bmul($P)->badd( $V)->badd( $U->is_odd ? $n : 0 )->brsft(1);
- $V->bmul($P)->badd($T1)->badd( $V->is_odd ? $n : 0 )->brsft(1);
+ $U->bmul($P)->badd( $V)->badd( $U->is_odd ? $n : $ZERO )->brsft(1);
+ $V->bmul($P)->badd($T1)->badd( $V->is_odd ? $n : $ZERO )->brsft(1);
}
}
}
} else {
+ my $qsign = ($Q == -1) ? -1 : 0;
while (++$bpos < length($kstr)) {
- $U = ($U * $V) % $n;
- $V = ($V * $V - 2*$Qk) % $n;
- $Qk->bmul($Qk);
+ $U->bmul($V)->bmod($n);
+ if ($qsign == 1) { $V->bmul($V)->bsub($TWO)->bmod($n); }
+ elsif ($qsign == -1) { $V->bmul($V)->badd($TWO)->bmod($n); }
+ else { $V->bmul($V)->bsub($Qk->copy->blsft($ONE))->bmod($n); }
if (substr($kstr,$bpos,1)) {
my $T1 = $U->copy->bmul($D);
$U->bmul($P);
$U->badd($V);
$U->badd($n) if $U->is_odd;
- $U->brsft(1);
+ $U->brsft($ONE);
$V->bmul($P);
$V->badd($T1);
$V->badd($n) if $V->is_odd;
- $V->brsft(1);
+ $V->brsft($ONE);
- $Qk->bmul($Q);
+ if ($qsign != 0) { $qsign = -1; }
+ else { $Qk->bmul($Qk)->bmul($Q)->bmod($n); }
+ } else {
+ if ($qsign != 0) { $qsign = 1; }
+ else { $Qk->bmul($Qk)->bmod($n); }
}
- $Qk->bmod($n);
}
+ $Qk->neg if $qsign == 1;
}
$U->bmod($n);
$V->bmod($n);
--
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