[libmath-prime-util-perl] 125/181: Performance tweaks (small) for bigints

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


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

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

commit 2fea141a7a7a1f536fa018905250a61aeb01b3ba
Author: Dana Jacobsen <dana at acm.org>
Date:   Mon Jan 6 19:22:08 2014 -0800

    Performance tweaks (small) for bigints
---
 lib/Math/Prime/Util/ECAffinePoint.pm     | 49 ++++++++++++++++++++++++---
 lib/Math/Prime/Util/ECProjectivePoint.pm | 18 ++++++----
 lib/Math/Prime/Util/PrimalityProving.pm  | 57 ++++++++++++++++++--------------
 3 files changed, 88 insertions(+), 36 deletions(-)

diff --git a/lib/Math/Prime/Util/ECAffinePoint.pm b/lib/Math/Prime/Util/ECAffinePoint.pm
index d2d67d0..4041d17 100644
--- a/lib/Math/Prime/Util/ECAffinePoint.pm
+++ b/lib/Math/Prime/Util/ECAffinePoint.pm
@@ -72,12 +72,51 @@ sub _double {
   return ($x,$y);
 }
 
+sub _inplace_add {
+  my ($P1x, $P1y, $x, $y, $n) = @_;
+
+  if ($P1x == $x) {
+    my $t = ($P1y + $y) % $n;
+    if ($t == 0) {
+      ($_[2],$_[3]) = (Math::BigInt->bzero,Math::BigInt->bone);
+      return;
+    }
+  }
+  my $deltax = ($x - $P1x) % $n;
+  $deltax->bmodinv($n);
+  if ($deltax eq 'NaN') {
+    ($_[2],$_[3]) = (Math::BigInt->bzero,Math::BigInt->bone);
+    return;
+  }
+  my $deltay = ($y - $P1y) % $n;
+  my $m = ($deltay * $deltax) % $n;   # m = deltay / deltax
+
+  $_[2] = ($m*$m - $P1x - $x) % $n;
+  $_[3] = ($m*($P1x - $_[2]) - $P1y) % $n;
+}
+sub _inplace_double {
+  my($x, $y, $a, $n) = @_;
+  my $m = $y+$y;
+  $m->bmodinv($n);
+  if ($m eq 'NaN') {
+    ($_[0],$_[1]) = (Math::BigInt->bzero,Math::BigInt->bone);
+    return;
+  }
+  $m->bmul($x->copy->bmul($x)->bmul(3)->badd($a))->bmod($n);
+
+  my $xin = $x->copy;
+  $_[0] = ($m*$m - $x - $x) % $n;
+  $_[1] = ($m*($xin - $_[0]) - $y) % $n;
+}
+
 sub mul {
   my ($self, $k) = @_;
   my $x = $self->{'x'};
   my $y = $self->{'y'};
+  my $a = $self->{'a'};
   my $n = $self->{'n'};
   my $f = $self->{'f'};
+  $k = int($k->bstr) if ref($k) eq 'Math::BigInt' && $k < ''.~0;
 
   my $Bx = $n->copy->bzero;
   my $By = $n->copy->bone;
@@ -87,16 +126,16 @@ sub mul {
     if ( ($k % 2) != 0) {
       $k--;
       $f->bmul($Bx-$x)->bmod($n);
-      if    ($x == 0 && $y == 1)   { }
-      elsif ($Bx == 0 && $By == 1) { ($Bx,$By) = ($x,$y); }
-      else                         { ($Bx,$By) = $self->_add($x,$y,$Bx,$By); }
+      if    ($x->is_zero && $y->is_one)   { }
+      elsif ($Bx->is_zero && $By->is_one) { ($Bx,$By) = ($x,$y); }
+      else                                { _inplace_add($x,$y,$Bx,$By,$n); }
     } else {
       $k >>= 1;
       $f->bmul(2*$y)->bmod($n);
-      ($x,$y) = $self->_double($x,$y);
+      _inplace_double($x,$y,$a,$n);
     }
   }
-  $f = Math::BigInt::bgcd( $f, $n);
+  $f = Math::BigInt::bgcd($f, $n);
   $self->{'x'} = $Bx;
   $self->{'y'} = $By;
   $self->{'f'} = $f;
diff --git a/lib/Math/Prime/Util/ECProjectivePoint.pm b/lib/Math/Prime/Util/ECProjectivePoint.pm
index dd30eb8..f6343c0 100644
--- a/lib/Math/Prime/Util/ECProjectivePoint.pm
+++ b/lib/Math/Prime/Util/ECProjectivePoint.pm
@@ -53,20 +53,26 @@ sub _add3 {
   my $u = ($x2 - $z2) * ($x1 + $z1);
   my $v = ($x2 + $z2) * ($x1 - $z1);
 
-  my $upv2 = ($u + $v) ** 2;
-  my $umv2 = ($u - $v) ** 2;
+  my $upv2 = $u + $v;  $upv2->bmul($upv2);
+  my $umv2 = $u - $v;  $umv2->bmul($umv2);
 
-  return ( ($upv2*$zin) % $n, ($umv2*$xin) % $n );
+  $upv2->bmul($zin)->bmod($n);
+  $umv2->bmul($xin)->bmod($n);
+  return ($upv2, $umv2);
 }
 
 sub _double {
   my ($x, $z, $n, $d) = @_;
 
-  my $u = ($x + $z) ** 2;
-  my $v = ($x - $z) ** 2;
+  my $u = $x + $z;   $u->bmul($u);
+  my $v = $x - $z;   $v->bmul($v);
+
   my $w = $u - $v;
   my $t = $d * $w + $v;
-  return ( ($u * $v) % $n  ,  ($w * $t) % $n );
+
+  $u->bmul($v)->bmod($n);
+  $w->bmul($t)->bmod($n);
+  return ($u, $w);
 }
 
 sub mul {
diff --git a/lib/Math/Prime/Util/PrimalityProving.pm b/lib/Math/Prime/Util/PrimalityProving.pm
index 09ee681..69aebf4 100644
--- a/lib/Math/Prime/Util/PrimalityProving.pm
+++ b/lib/Math/Prime/Util/PrimalityProving.pm
@@ -114,17 +114,23 @@ sub primality_proof_bls75 {
   return @composite if is_strong_pseudoprime($n,2,15,325) == 0;
 
   $n = Math::BigInt->new("$n") unless ref($n) eq 'Math::BigInt';
-  my $nm1 = $n-1;
-  my $A = $nm1->copy->bone;   # factored part
+  my $nm1 = $n->copy->bdec;
+  my $ONE = $nm1->copy->bone;
+  my $TWO = $ONE->copy->binc;
+  my $A = $ONE->copy;         # factored part
   my $B = $nm1->copy;         # unfactored part
-  my @factors = (2);
+  my @factors = ($TWO);
   croak "BLS75 error: n-1 not even" unless $nm1->is_even();
-  my $trial_B = 20000;
-  $trial_B = 500 if ! prime_get_config->{'xs'};
   {
-    while ($B->is_even) { $B /= 2; $A *= 2; }
-    my @tf = Math::Prime::Util::PP::trial_factor($B, $trial_B);
-    pop @tf if $tf[-1] > $trial_B;
+    while ($B->is_even) { $B->bdiv($TWO); $A->bmul($TWO); }
+    my @tf;
+    if ($B <= ''.~0 && prime_get_config->{'xs'}) {
+      @tf = Math::Prime::Util::trial_factor($B, 20000);
+      pop @tf if $tf[-1] > 20000;
+    } else {
+      @tf = Math::Prime::Util::PP::trial_factor($B, 500);
+      pop @tf if $tf[-1] > 500;
+    }
     foreach my $f (@tf) {
       next if $f == $factors[-1];
       push @factors, $f;
@@ -133,7 +139,7 @@ sub primality_proof_bls75 {
   }
   my @nstack;
   # nstack should only hold composites
-  if ($B == 1) {
+  if ($B->is_one) {
     # Completely factored.  Nothing.
   } elsif (is_prob_prime($B)) {
     push @factors, $B;
@@ -142,8 +148,8 @@ sub primality_proof_bls75 {
     push @nstack, $B;
   }
   while (@nstack) {
-    my ($s,$r) = $B->copy->bdiv($A->copy->bmul(2));
-    my $fpart = ($A+1) * (2*$A*$A + ($r-1) * $A + 1);
+    my ($s,$r) = $B->copy->bdiv($A->copy->bmul($TWO));
+    my $fpart = ($A+$ONE) * ($TWO*$A*$A + ($r-$ONE) * $A + $ONE);
     last if $n < $fpart;
 
     my $m = pop @nstack;
@@ -159,33 +165,33 @@ sub primality_proof_bls75 {
     next unless scalar @ftry > 1;
     # Process each factor
     foreach my $f (@ftry) {
-      croak "Invalid factoring: B=$B m=$m f=$f" if $f == 1 || $f == $m || ($B%$f) != 0;
+      croak "Invalid factoring: B=$B m=$m f=$f" if $f == 1 || $f == $m || !$B->copy->bmod($f)->is_zero;
       if (is_prob_prime($f)) {
         push @factors, $f;
-        do { $B /= $f;  $A *= $f; } while (($B % $f) == 0);
+        do { $B /= $f;  $A *= $f; } while $B->copy->bmod($f)->is_zero;
       } else {
         push @nstack, $f;
       }
     }
   }
+  { # remove duplicate factors and make a sorted array of bigints
+    my %uf = map { $_ => 1 } @factors;
+    @factors = sort {$a<=>$b} map { Math::BigInt->new("$_") } keys %uf;
+  }
   # Just in case:
   foreach my $f (@factors) {
-    while (($B % $f) == 0) {
+    while ($B->copy->bmod($f)->is_zero) {
       $B /= $f;  $A *= $f;
     }
   }
-  { # remove duplicate factors and make a sorted array of bigints
-    my %uf = map { $_ => 1 } @factors;
-    @factors = sort {$a<=>$b} map { Math::BigInt->new("$_") } keys %uf;
-  }
   # Did we factor enough?
-  my ($s,$r) = $B->copy->bdiv($A->copy->bmul(2));
-  my $fpart = ($A+1) * (2*$A*$A + ($r-1) * $A + 1);
+  my ($s,$r) = $B->copy->bdiv($A->copy->bmul($TWO));
+  my $fpart = ($A+$ONE) * ($TWO*$A*$A + ($r-$ONE) * $A + $ONE);
   return (1,'') if $n >= $fpart;
   # Check we didn't mess up
   croak "BLS75 error: $A * $B != $nm1" unless $A*$B == $nm1;
   croak "BLS75 error: $A not even" unless $A->is_even();
-  croak "BLS75 error: A and B not coprime" unless Math::BigInt::bgcd($A, $B)==1;
+  croak "BLS75 error: A and B not coprime" unless Math::BigInt::bgcd($A, $B)->is_one;
 
   my $rtest = $r*$r - 8*$s;
   my $rtestroot = $rtest->copy->bsqrt;
@@ -203,10 +209,11 @@ sub primality_proof_bls75 {
     } else {
       $cert .= "Q[$qnum] $f\n";
     }
+    my $nm1_div_f = $nm1 / $f;
     foreach my $a (2 .. 10000) {
       my $ap = Math::BigInt->new($a);
-      next unless $ap->copy->bmodpow($nm1, $n) == 1;
-      next unless Math::BigInt::bgcd($ap->copy->bmodpow($nm1/$f, $n)->bsub(1), $n) == 1;
+      next unless $ap->copy->bmodpow($nm1, $n)->is_one;
+      next unless Math::BigInt::bgcd($ap->copy->bmodpow($nm1_div_f, $n)->bdec, $n)->is_one;
       $atext .= "A[$qnum] $a\n" unless $a == 2;
       $success = 1;
       last;
@@ -707,9 +714,9 @@ sub _verify_bls5 {
     my $a = $A[$i];
     my $q = $Q[$i];
     return _pfail "BLS5: $n failed A[i]^(N-1) mod N = 1"
-      unless $a->copy->bmodpow($nm1, $n) == 1;
+      unless $a->copy->bmodpow($nm1, $n)->is_one;
     return _pfail "BLS5: $n failed gcd(A[i]^((N-1)/Q[i])-1, N) = 1"
-      unless Math::BigInt::bgcd($a->copy->bmodpow($nm1/$q, $n)-1, $n) == 1;
+      unless Math::BigInt::bgcd($a->copy->bmodpow($nm1/$q, $n)->bdec, $n)->is_one;
   }
   ($n, @Q);
 }

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