Imported Upstream version 0.26
Salvatore Bonaccorso
11 years ago
0 | 0 | Revision history for Perl extension Math::Prime::Util. |
1 | ||
2 | 0.26 21 April 2013 | |
3 | ||
4 | - Pure Perl factoring: | |
5 | - real p-1 -- much faster and more effective | |
6 | - Fermat (no better than HOLF) | |
7 | - speedup for pbrent | |
8 | - simple ECM | |
9 | - redo factoring mix | |
10 | ||
11 | - New functions: | |
12 | prime_certificate produces a certificate of primality. | |
13 | verify_prime checks a primality certificate. | |
14 | ||
15 | - Pure perl primality proof now uses BLS75 instead of Lucas, so some | |
16 | numbers will be much faster [n-1 only needs factoring to (n/2)^1/3]. | |
17 | ||
18 | - Math::Prime::Util::ECAffinePoint and ECProjectivePoint modules for | |
19 | dealing with elliptic curves. | |
1 | 20 | |
2 | 21 | 0.25 19 March 2013 |
3 | 22 |
3 | 3 | lib/Math/Prime/Util/PrimeArray.pm |
4 | 4 | lib/Math/Prime/Util/PP.pm |
5 | 5 | lib/Math/Prime/Util/ZetaBigFloat.pm |
6 | lib/Math/Prime/Util/ECAffinePoint.pm | |
7 | lib/Math/Prime/Util/ECProjectivePoint.pm | |
6 | 8 | LICENSE |
7 | 9 | Makefile.PL |
8 | 10 | MANIFEST |
55 | 57 | examples/test-factor-gnufactor.pl |
56 | 58 | examples/test-primes-script.pl |
57 | 59 | examples/test-primes-script2.pl |
60 | examples/verify-gmp-eccp-cert.pl | |
58 | 61 | bin/primes.pl |
59 | 62 | bin/factor.pl |
60 | 63 | t/01-load.t |
57 | 57 | "url" : "https://github.com/danaj/Math-Prime-Util" |
58 | 58 | } |
59 | 59 | }, |
60 | "version" : "0.25" | |
60 | "version" : "0.26" | |
61 | 61 | } |
35 | 35 | resources: |
36 | 36 | homepage: https://github.com/danaj/Math-Prime-Util |
37 | 37 | repository: https://github.com/danaj/Math-Prime-Util |
38 | version: 0.25 | |
38 | version: 0.26 |
0 | Math::Prime::Util version 0.25 | |
0 | Math::Prime::Util version 0.26 | |
1 | 1 | |
2 | 2 | A set of utilities related to prime numbers. These include multiple sieving |
3 | 3 | methods, is_prime, prime_count, nth_prime, approximations and bounds for |
9 | 9 | Math::Prime::XS |
10 | 10 | Math::Prime::FastSieve |
11 | 11 | Math::Factor::XS |
12 | Math::Big | |
12 | 13 | Math::Big::Factors |
13 | 14 | Math::Factoring |
14 | 15 | Math::Primality |
15 | 16 | Math::Prime::TiedArray |
17 | Crypt::Primes | |
16 | 18 | For non-bignums, it is typically faster than Math::Pari (and doesn't |
17 | 19 | require Pari to be installed). |
18 | 20 | |
48 | 50 | |
49 | 51 | DEPENDENCIES |
50 | 52 | |
51 | Perl 5.6.2 or later. No modules outside of Core have been used. | |
53 | Perl 5.6.2 or later (5.8 or later is preferred). | |
54 | ||
55 | Bytes::Random::Secure 0.23 or later. | |
52 | 56 | |
53 | 57 | |
54 | 58 | COPYRIGHT AND LICENCE |
55 | 59 | |
56 | Copyright (C) 2011-2012 by Dana Jacobsen <dana@acm.org> | |
60 | Copyright (C) 2011-2013 by Dana Jacobsen <dana@acm.org> | |
57 | 61 | |
58 | 62 | This library is free software; you can redistribute it and/or modify |
59 | 63 | it under the same terms as Perl itself. |
20 | 20 | - Test all functions return either native or bigints. Functions that return |
21 | 21 | raw MPU::GMP results will return strings, which isn't right. |
22 | 22 | |
23 | - Make proper pminus1 in PP code, like factor.c. | |
24 | ||
25 | 23 | - An assembler version of mulmod for i386 would be _really_ helpful for |
26 | 24 | all the non-x86-64 Intel machines. |
27 | 25 | |
33 | 31 | - More efficient totient segment. Do we really need primes to n/2? |
34 | 32 | |
35 | 33 | - Implement S2 calculation for LMO prime count. |
34 | ||
35 | - Add Sage output style verification. Looks like NZMATH has ECPP but doesn't | |
36 | produce a certificate. Adding a Primo parser (see WraithX's code) would | |
37 | be awesome, but may be a lot more work. It would still be nice to have yet | |
38 | another independent codebase for this. |
5 | 5 | use Math::Prime::Util qw/factor nth_prime/; |
6 | 6 | $| = 1; |
7 | 7 | no bigint; |
8 | ||
9 | # Allow execution of any of these functions in the command line | |
10 | my @mpu_funcs = (qw/next_prime prev_prime prime_count nth_prime random_prime | |
11 | random_ndigit_prime random_nbit_prime random_strong_prime | |
12 | random_maurer_prime primorial pn_primorial moebius mertens | |
13 | euler_phi jordan_totient exp_mangoldt divisor_sum | |
14 | consecutive_integer_lcm/); | |
15 | my %mpu_func_map; | |
8 | 16 | |
9 | 17 | my %opts; |
10 | 18 | GetOptions(\%opts, |
41 | 49 | sub eval_expr { |
42 | 50 | my $expr = shift; |
43 | 51 | die "$expr cannot be evaluated" if $expr =~ /:/; # Use : for escape |
44 | $expr =~ s/nth_prime\(/:1(/g; | |
45 | $expr =~ s/log\(/:2(/g; | |
52 | if (scalar(keys %mpu_func_map) == 0) { | |
53 | my $n = 10; | |
54 | foreach my $func (@mpu_funcs) { | |
55 | $mpu_func_map{$func} = sprintf("%03d", $n++); | |
56 | } | |
57 | } | |
58 | $expr =~ s/\blog\(/:001(/g; | |
59 | foreach my $func (@mpu_funcs) { | |
60 | $expr =~ s/\b$func\(/:$mpu_func_map{$func}(/g; | |
61 | } | |
46 | 62 | die "$expr cannot be evaluated" if $expr =~ tr|-0123456789+*/() :||c; |
47 | $expr =~ s/:1/nth_prime/g; | |
48 | $expr =~ s/:2/log/g; | |
49 | $expr =~ s/(\d+)/ Math::BigInt->new($1) /g; | |
63 | $expr =~ s/:001/log/g; | |
64 | foreach my $func (@mpu_funcs) { | |
65 | $expr =~ s/:$mpu_func_map{$func}\(/Math::Prime::Util::$func(/g; | |
66 | } | |
67 | $expr =~ s/(\d+)/ Math::BigInt->new("$1") /g; | |
50 | 68 | my $res = eval $expr; ## no critic |
51 | 69 | die "Cannot eval: $expr\n" if !defined $res; |
52 | 70 | $res = int($res->bstr) if ref($res) eq 'Math::BigInt' && $res <= ~0; |
61 | 79 | Print the prime factors of each positive integer given on the command line, |
62 | 80 | or reads numbers from standard input if called without arguments. |
63 | 81 | |
82 | Math expressions may be given as arguments, which will be evaluated before | |
83 | factoring. This includes most Math::Prime::Util functions including things | |
84 | like prime_count(#), nth_prime(#), primorial(#), random_nbit_prime(#), etc. | |
85 | ||
64 | 86 | --help displays this help message |
65 | 87 | --version displays the version information |
66 | 88 |
8 | 8 | use autodie; |
9 | 9 | use Text::Diff; |
10 | 10 | use Time::HiRes qw(gettimeofday tv_interval); |
11 | my $maxdigits = 50; | |
11 | my $maxdigits = 100; | |
12 | 12 | $| = 1; # fast pipes |
13 | 13 | srand(87431); |
14 | 14 | my $num = 1000; |
0 | #!/usr/bin/env perl | |
1 | use warnings; | |
2 | use strict; | |
3 | use Math::BigInt try=>"GMP,Pari"; | |
4 | use Math::Prime::Util qw/:all/; | |
5 | use Data::Dump qw/dump/; | |
6 | ||
7 | # Takes the output of GMP-ECPP, creates a certificate in the format used | |
8 | # by MPU, and runs it through the verifier. | |
9 | # | |
10 | # Example: | |
11 | # | |
12 | # perl -MMath::Prime::Util -E 'say random_ndigit_prime(60)' | \ | |
13 | # gmp-ecpp -q | \ | |
14 | # perl examples/verify-gmp-eccp-cert.pl | |
15 | ||
16 | ||
17 | my $early_check = 0; | |
18 | ||
19 | my $N; | |
20 | my ($n, $a, $b, $m, $q, $Px, $Py); | |
21 | my @cert; | |
22 | ||
23 | while (<>) { | |
24 | if (/^N\[(\d+)\]\s*=\s*(\d+)/) { | |
25 | $n = $2; | |
26 | if ($1 == 0) { | |
27 | die "Bad input" if defined $N; | |
28 | $N = $n; | |
29 | @cert = ($n, "AGKM"); | |
30 | } | |
31 | } | |
32 | elsif (/^a\s*=\s*(\d+)/) { $a = $1; } | |
33 | elsif (/^b\s*=\s*(\d+)/) { $b = $1; } | |
34 | elsif (/^m\s*=\s*(\d+)/) { $m = $1; } | |
35 | elsif (/^q\s*=\s*(\d+)/) { $q = $1; } | |
36 | elsif (/^P\s*=\s*\(\s*(\d+)\s*,\s*(\d+)\s*\)/) { | |
37 | $Px = $1; | |
38 | $Py = $2; | |
39 | die "Bad input\n" | |
40 | unless defined $N && defined $a && defined $b && defined $m | |
41 | && defined $q && defined $Px && defined $Py; | |
42 | ||
43 | # If for a given q value, is_prime returns 2, that indicates it can | |
44 | # produce an n-1 primality proof very quickly, so we could stop now. | |
45 | if ($early_check) { | |
46 | my $bq = Math::BigInt->new("$q"); | |
47 | if (is_prime($bq) == 2) { | |
48 | push @cert, [$n, $a, $b, $m, [prime_certificate($bq)], [$Px,$Py]]; | |
49 | last; | |
50 | } | |
51 | } | |
52 | push @cert, [$n, $a, $b, $m, $q, [$Px,$Py]]; | |
53 | } | |
54 | else { | |
55 | last if /^proven prime/; | |
56 | } | |
57 | } | |
58 | ||
59 | print dump(\@cert), "\n"; | |
60 | print verify_prime(@cert) ? "SUCCESS\n" : "FAILURE\n"; |
7 | 7 | #include "util.h" |
8 | 8 | #include "sieve.h" |
9 | 9 | #include "mulmod.h" |
10 | #include "cache.h" | |
10 | 11 | |
11 | 12 | /* |
12 | 13 | * You need to remember to use UV for unsigned and IV for signed types that |
622 | 623 | /* Pollard's P-1 */ |
623 | 624 | int pminus1_factor(UV n, UV *factors, UV B1, UV B2) |
624 | 625 | { |
625 | UV q, f; | |
626 | UV f; | |
627 | UV q = 2; | |
626 | 628 | UV a = 2; |
627 | 629 | UV savea = 2; |
628 | 630 | UV saveq = 2; |
0 | package Math::Prime::Util::ECAffinePoint; | |
1 | use strict; | |
2 | use warnings; | |
3 | use Carp qw/carp croak confess/; | |
4 | ||
5 | if (!defined $Math::BigInt::VERSION) { | |
6 | eval { require Math::BigInt; Math::BigInt->import(try=>'GMP,Pari'); 1; } | |
7 | or do { croak "Cannot load Math::BigInt"; }; | |
8 | } | |
9 | ||
10 | BEGIN { | |
11 | $Math::Prime::Util::ECAffinePoint::AUTHORITY = 'cpan:DANAJ'; | |
12 | $Math::Prime::Util::ECAffinePoint::VERSION = '0.26'; | |
13 | } | |
14 | ||
15 | # Pure perl (with Math::BigInt) manipulation of Elliptic Curves | |
16 | # in affine coordinates. Should be split into a point class. | |
17 | ||
18 | sub new { | |
19 | my ($class, $a, $b, $n, $x, $y) = @_; | |
20 | $a = Math::BigInt->new("$a") unless ref($a) eq 'Math::BigInt'; | |
21 | $b = Math::BigInt->new("$b") unless ref($b) eq 'Math::BigInt'; | |
22 | $n = Math::BigInt->new("$n") unless ref($n) eq 'Math::BigInt'; | |
23 | $x = Math::BigInt->new("$x") unless ref($x) eq 'Math::BigInt'; | |
24 | $y = Math::BigInt->new("$y") unless ref($y) eq 'Math::BigInt'; | |
25 | ||
26 | croak "n must be >= 2" unless $n >= 2; | |
27 | $a->bmod($n); | |
28 | $b->bmod($n); | |
29 | ||
30 | my $self = { | |
31 | a => $a, | |
32 | b => $b, | |
33 | n => $n, | |
34 | x => $x, | |
35 | y => $y, | |
36 | f => $n->copy->bone, | |
37 | }; | |
38 | ||
39 | bless $self, $class; | |
40 | return $self; | |
41 | } | |
42 | ||
43 | sub _add { | |
44 | my ($self, $P1x, $P1y, $P2x, $P2y) = @_; | |
45 | my $n = $self->{'n'}; | |
46 | ||
47 | if ($P1x == $P2x) { | |
48 | my $t = ($P1y + $P2y) % $n; | |
49 | return (Math::BigInt->bzero,Math::BigInt->bone) if $t == 0; | |
50 | } | |
51 | my $deltax = ($P2x - $P1x) % $n; | |
52 | $deltax->bmodinv($n); | |
53 | return (Math::BigInt->bzero,Math::BigInt->bone) if $deltax eq "NaN"; | |
54 | ||
55 | my $deltay = ($P2y - $P1y) % $n; | |
56 | my $m = ($deltay * $deltax) % $n; # m = deltay / deltax | |
57 | ||
58 | my $x = ($m*$m - $P1x - $P2x) % $n; | |
59 | my $y = ($m*($P1x - $x) - $P1y) % $n; | |
60 | return ($x,$y); | |
61 | } | |
62 | ||
63 | sub _double { | |
64 | my ($self, $P1x, $P1y) = @_; | |
65 | my $n = $self->{'n'}; | |
66 | ||
67 | my $m = 2*$P1y; | |
68 | $m->bmodinv($n); | |
69 | return (Math::BigInt->bzero,Math::BigInt->bone) if $m eq "NaN"; | |
70 | ||
71 | $m = ((3*$P1x*$P1x + $self->{'a'}) * $m) % $n; | |
72 | ||
73 | my $x = ($m*$m - 2*$P1x) % $n; | |
74 | my $y = ($m*($P1x - $x) - $P1y) % $n; | |
75 | return ($x,$y); | |
76 | } | |
77 | ||
78 | sub mul { | |
79 | my ($self, $k) = @_; | |
80 | my $x = $self->{'x'}; | |
81 | my $y = $self->{'y'}; | |
82 | my $n = $self->{'n'}; | |
83 | my $f = $self->{'f'}; | |
84 | ||
85 | my $Bx = $n->copy->bzero; | |
86 | my $By = $n->copy->bone; | |
87 | my $v = 1; | |
88 | ||
89 | while ($k > 0) { | |
90 | if ( ($k % 2) != 0) { | |
91 | $k--; | |
92 | $f->bmul($Bx-$x)->bmod($n); | |
93 | if ($x == 0 && $y == 1) { } | |
94 | elsif ($Bx == 0 && $By == 1) { ($Bx,$By) = ($x,$y); } | |
95 | else { ($Bx,$By) = $self->_add($x,$y,$Bx,$By); } | |
96 | } else { | |
97 | $k >>= 1; | |
98 | $f->bmul(2*$y)->bmod($n); | |
99 | ($x,$y) = $self->_double($x,$y); | |
100 | } | |
101 | } | |
102 | $f = Math::BigInt::bgcd( $f, $n); | |
103 | $self->{'x'} = $Bx; | |
104 | $self->{'y'} = $By; | |
105 | $self->{'f'} = $f; | |
106 | return $self; | |
107 | } | |
108 | ||
109 | sub add { | |
110 | my ($self, $other) = @_; | |
111 | croak "add takes a EC point" | |
112 | unless ref($other) eq 'Math::Prime::Util::ECAffinePoint'; | |
113 | croak "second point is not on the same curve" | |
114 | unless $self->{'a'} == $other->{'a'} && | |
115 | $self->{'b'} == $other->{'b'} && | |
116 | $self->{'n'} == $other->{'n'}; | |
117 | ||
118 | ($self->{'x'}, $self->{'y'}) = $self->_add($self->{'x'}, $self->{'y'}, | |
119 | $other->{'x'}, $other->{'y'}); | |
120 | return $self; | |
121 | } | |
122 | ||
123 | ||
124 | sub a { return shift->{'a'}; } | |
125 | sub b { return shift->{'b'}; } | |
126 | sub n { return shift->{'n'}; } | |
127 | sub x { return shift->{'x'}; } | |
128 | sub y { return shift->{'y'}; } | |
129 | sub f { return shift->{'f'}; } | |
130 | ||
131 | sub is_infinity { | |
132 | my $self = shift; | |
133 | return ($self->{'x'}->is_zero() && $self->{'y'}->is_one()); | |
134 | } | |
135 | ||
136 | 1; | |
137 | ||
138 | __END__ | |
139 | ||
140 | ||
141 | # ABSTRACT: Elliptic curve operations for affine points | |
142 | ||
143 | =pod | |
144 | ||
145 | =encoding utf8 | |
146 | ||
147 | ||
148 | =head1 NAME | |
149 | ||
150 | Math::Prime::Util::ECAffinePoint - Elliptic curve operations for affine points | |
151 | ||
152 | ||
153 | =head1 VERSION | |
154 | ||
155 | Version 0.26 | |
156 | ||
157 | ||
158 | =head1 SYNOPSIS | |
159 | ||
160 | # Create a point on a curve (a,b,n) with coordinates 0,1 | |
161 | my $ECP = Math::Prime::Util::ECAffinePoint->new($a, $b, $n, 0, 1); | |
162 | ||
163 | # scalar multiplication by k. | |
164 | $ECP->mul($k) | |
165 | ||
166 | # add two points on the same curve | |
167 | $ECP->add($ECP2) | |
168 | ||
169 | say "P = O" if $ECP->is_infinity(); | |
170 | ||
171 | =head1 DESCRIPTION | |
172 | ||
173 | This really should just be in Math::EllipticCurve. | |
174 | ||
175 | To write. | |
176 | ||
177 | ||
178 | =head1 FUNCTIONS | |
179 | ||
180 | =head2 new | |
181 | ||
182 | $point = Math::Prime::Util::ECAffinePoint->new(a, b, n, x, y); | |
183 | ||
184 | Returns a new point at C<(x,y,1)> on the curve C<(a,b,n)>. | |
185 | ||
186 | =head2 a | |
187 | ||
188 | =head2 b | |
189 | ||
190 | =head2 n | |
191 | ||
192 | Returns the C<a>, C<b>, or C<n> values that describe the curve. | |
193 | ||
194 | =head2 x | |
195 | ||
196 | =head2 y | |
197 | ||
198 | Returns the C<x> or C<y> values that define the point on the curve. | |
199 | ||
200 | =head2 f | |
201 | ||
202 | Returns a possible factor found during EC multiplication. | |
203 | ||
204 | =head2 add | |
205 | ||
206 | Takes another point on the same curve as an argument and adds it this point. | |
207 | ||
208 | =head2 mul | |
209 | ||
210 | Takes an integer and performs scalar multiplication of the point. | |
211 | ||
212 | =head2 is_infinity | |
213 | ||
214 | Returns true if the point is (0,1), which is the point at infinity for | |
215 | the affine coordinates. | |
216 | ||
217 | ||
218 | =head1 SEE ALSO | |
219 | ||
220 | L<Math::EllipticCurve::Prime> | |
221 | ||
222 | This really should just be in a L<Math::EllipticCurve> module. | |
223 | ||
224 | =head1 AUTHORS | |
225 | ||
226 | Dana Jacobsen E<lt>dana@acm.orgE<gt> | |
227 | ||
228 | ||
229 | =head1 COPYRIGHT | |
230 | ||
231 | Copyright 2012-2013 by Dana Jacobsen E<lt>dana@acm.orgE<gt> | |
232 | ||
233 | This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. | |
234 | ||
235 | =cut |
0 | package Math::Prime::Util::ECProjectivePoint; | |
1 | use strict; | |
2 | use warnings; | |
3 | use Carp qw/carp croak confess/; | |
4 | ||
5 | if (!defined $Math::BigInt::VERSION) { | |
6 | eval { require Math::BigInt; Math::BigInt->import(try=>'GMP,Pari'); 1; } | |
7 | or do { croak "Cannot load Math::BigInt"; }; | |
8 | } | |
9 | ||
10 | BEGIN { | |
11 | $Math::Prime::Util::ECProjectivePoint::AUTHORITY = 'cpan:DANAJ'; | |
12 | $Math::Prime::Util::ECProjectivePoint::VERSION = '0.26'; | |
13 | } | |
14 | ||
15 | # Pure perl (with Math::BigInt) manipulation of Elliptic Curves | |
16 | # in projective coordinates. | |
17 | ||
18 | sub new { | |
19 | my ($class, $c, $n, $x, $z) = @_; | |
20 | $c = Math::BigInt->new("$c") unless ref($c) eq 'Math::BigInt'; | |
21 | $n = Math::BigInt->new("$n") unless ref($n) eq 'Math::BigInt'; | |
22 | $x = Math::BigInt->new("$x") unless ref($x) eq 'Math::BigInt'; | |
23 | $z = Math::BigInt->new("$z") unless ref($z) eq 'Math::BigInt'; | |
24 | ||
25 | croak "n must be >= 2" unless $n >= 2; | |
26 | $c->bmod($n); | |
27 | ||
28 | my $self = { | |
29 | c => $c, | |
30 | d => ($c + 2) >> 2, | |
31 | n => $n, | |
32 | x => $x, | |
33 | z => $z, | |
34 | f => $n-$n+1, | |
35 | }; | |
36 | ||
37 | bless $self, $class; | |
38 | return $self; | |
39 | } | |
40 | ||
41 | sub _addx { | |
42 | my ($x1, $x2, $xin, $n) = @_; | |
43 | ||
44 | my $u = ($x2 - 1) * ($x1 + 1); | |
45 | my $v = ($x2 + 1) * ($x1 - 1); | |
46 | ||
47 | my $upv2 = ($u + $v) ** 2; | |
48 | my $umv2 = ($u - $v) ** 2; | |
49 | ||
50 | return ( $upv2 % $n, ($umv2*$xin) % $n ); | |
51 | } | |
52 | ||
53 | sub _add3 { | |
54 | my ($x1, $z1, $x2, $z2, $xin, $zin, $n) = @_; | |
55 | ||
56 | my $u = ($x2 - $z2) * ($x1 + $z1); | |
57 | my $v = ($x2 + $z2) * ($x1 - $z1); | |
58 | ||
59 | my $upv2 = ($u + $v) ** 2; | |
60 | my $umv2 = ($u - $v) ** 2; | |
61 | ||
62 | return ( ($upv2*$zin) % $n, ($umv2*$xin) % $n ); | |
63 | } | |
64 | ||
65 | sub _double { | |
66 | my ($x, $z, $n, $d) = @_; | |
67 | ||
68 | my $u = ($x + $z) ** 2; | |
69 | my $v = ($x - $z) ** 2; | |
70 | my $w = $u - $v; | |
71 | my $t = $d * $w + $v; | |
72 | return ( ($u * $v) % $n , ($w * $t) % $n ); | |
73 | } | |
74 | ||
75 | sub mul { | |
76 | my ($self, $k) = @_; | |
77 | my $x = $self->{'x'}; | |
78 | my $z = $self->{'z'}; | |
79 | my $n = $self->{'n'}; | |
80 | my $d = $self->{'d'}; | |
81 | ||
82 | my ($x1, $x2, $z1, $z2); | |
83 | ||
84 | my $r = --$k; | |
85 | my $l = -1; | |
86 | while ($r != 1) { $r >>= 1; $l++ } | |
87 | if ($k & (1 << $l)) { | |
88 | ($x2, $z2) = _double($x, $z, $n, $d); | |
89 | ($x1, $z1) = _add3($x2, $z2, $x, $z, $x, $z, $n); | |
90 | ($x2, $z2) = _double($x2, $z2, $n, $d); | |
91 | } else { | |
92 | ($x1, $z1) = _double($x, $z, $n, $d); | |
93 | ($x2, $z2) = _add3($x, $z, $x1, $z1, $x, $z, $n); | |
94 | } | |
95 | $l--; | |
96 | while ($l >= 1) { | |
97 | if ($k & (1 << $l)) { | |
98 | ($x1, $z1) = _add3($x1, $z1, $x2, $z2, $x, $z, $n); | |
99 | ($x2, $z2) = _double($x2, $z2, $n, $d); | |
100 | } else { | |
101 | ($x2, $z2) = _add3($x2, $z2, $x1, $z1, $x, $z, $n); | |
102 | ($x1, $z1) = _double($x1, $z1, $n, $d); | |
103 | } | |
104 | $l--; | |
105 | } | |
106 | if ($k & 1) { | |
107 | ($x, $z) = _double($x2, $z2, $n, $d); | |
108 | } else { | |
109 | ($x, $z) = _add3($x2, $z2, $x1, $z1, $x, $z, $n); | |
110 | } | |
111 | ||
112 | $self->{'x'} = $x; | |
113 | $self->{'z'} = $z; | |
114 | return $self; | |
115 | } | |
116 | ||
117 | sub add { | |
118 | my ($self, $other) = @_; | |
119 | croak "add takes a EC point" | |
120 | unless ref($other) eq 'Math::Prime::Util::ECProjectivePoint'; | |
121 | croak "second point is not on the same curve" | |
122 | unless $self->{'c'} == $other->{'c'} && | |
123 | $self->{'n'} == $other->{'n'}; | |
124 | ||
125 | ($self->{'x'}, $self->{'z'}) = _add3($self->{'x'}, $self->{'z'}, | |
126 | $other->{'x'}, $other->{'z'}, | |
127 | $self->{'x'}, $self->{'z'}, | |
128 | $self->{'n'}); | |
129 | return $self; | |
130 | } | |
131 | ||
132 | sub double { | |
133 | my ($self) = @_; | |
134 | ($self->{'x'}, $self->{'z'}) = _double($self->{'x'}, $self->{'z'}, $self->{'n'}, $self->{'d'}); | |
135 | return $self; | |
136 | } | |
137 | ||
138 | sub _extended_gcd { | |
139 | my ($a, $b) = @_; | |
140 | my $zero = $a-$a; | |
141 | my ($x, $lastx, $y, $lasty) = ($zero, $zero+1, $zero+1, $zero); | |
142 | while ($b != 0) { | |
143 | my $q = int($a/$b); | |
144 | ($a, $b) = ($b, $a % $b); | |
145 | ($x, $lastx) = ($lastx - $q*$x, $x); | |
146 | ($y, $lasty) = ($lasty - $q*$y, $y); | |
147 | } | |
148 | return ($a, $lastx, $lasty); | |
149 | } | |
150 | ||
151 | sub normalize { | |
152 | my ($self) = @_; | |
153 | my $n = $self->{'n'}; | |
154 | my $z = $self->{'z'}; | |
155 | #my ($f, $u, undef) = _extended_gcd( $z, $n ); | |
156 | my $f = Math::BigInt::bgcd( $z, $n ); | |
157 | my $u = $z->copy->bmodinv($n); | |
158 | $self->{'x'} = ( $self->{'x'} * $u ) % $n; | |
159 | $self->{'z'} = $n-$n+1; | |
160 | $self->{'f'} = ($f * $self->{'f'}) % $n; | |
161 | return $self; | |
162 | } | |
163 | ||
164 | sub c { return shift->{'c'}; } | |
165 | sub d { return shift->{'d'}; } | |
166 | sub n { return shift->{'n'}; } | |
167 | sub x { return shift->{'x'}; } | |
168 | sub z { return shift->{'z'}; } | |
169 | sub f { return shift->{'f'}; } | |
170 | ||
171 | sub is_infinity { | |
172 | my $self = shift; | |
173 | return ($self->{'x'}->is_zero() && $self->{'z'}->is_one()); | |
174 | } | |
175 | ||
176 | sub copy { | |
177 | my $self = shift; | |
178 | return Math::Prime::Util::ECProjectivePoint->new( | |
179 | $self->{'c'}, $self->{'n'}, $self->{'x'}, $self->{'z'}); | |
180 | } | |
181 | ||
182 | 1; | |
183 | ||
184 | __END__ | |
185 | ||
186 | ||
187 | # ABSTRACT: Elliptic curve operations for projective points | |
188 | ||
189 | =pod | |
190 | ||
191 | =encoding utf8 | |
192 | ||
193 | ||
194 | =head1 NAME | |
195 | ||
196 | Math::Prime::Util::ECProjectivePoint - Elliptic curve operations for projective points | |
197 | ||
198 | ||
199 | =head1 VERSION | |
200 | ||
201 | Version 0.26 | |
202 | ||
203 | ||
204 | =head1 SYNOPSIS | |
205 | ||
206 | # Create a point on a curve (a,b,n) with coordinates 0,1 | |
207 | my $ECP = Math::Prime::Util::ECProjectivePoint->new($c, $n, 0, 1); | |
208 | ||
209 | # scalar multiplication by k. | |
210 | $ECP->mul($k) | |
211 | ||
212 | # add two points on the same curve | |
213 | $ECP->add($ECP2) | |
214 | ||
215 | say "P = O" if $ECP->is_infinity(); | |
216 | ||
217 | =head1 DESCRIPTION | |
218 | ||
219 | This really should just be in Math::EllipticCurve. | |
220 | ||
221 | To write. | |
222 | ||
223 | ||
224 | =head1 FUNCTIONS | |
225 | ||
226 | =head2 new | |
227 | ||
228 | $point = Math::Prime::Util::ECProjectivePoint->new(c, n, x, z); | |
229 | ||
230 | Returns a new point on the curve defined by the Montgomery parameter c. | |
231 | ||
232 | =head2 c | |
233 | ||
234 | =head2 n | |
235 | ||
236 | Returns the C<c>, C<d>, or C<n> values that describe the curve. | |
237 | ||
238 | =head2 d | |
239 | ||
240 | Returns the precalculated value of C<int( (c + 2) / 4 )>. | |
241 | ||
242 | =head2 x | |
243 | ||
244 | =head2 z | |
245 | ||
246 | Returns the C<x> or C<z> values that define the point on the curve. | |
247 | ||
248 | =head2 f | |
249 | ||
250 | Returns a possible factor found after L</normalize>. | |
251 | ||
252 | =head2 add | |
253 | ||
254 | Takes another point on the same curve as an argument and adds it this point. | |
255 | ||
256 | =head2 double | |
257 | ||
258 | Double the current point on the curve. | |
259 | ||
260 | =head2 mul | |
261 | ||
262 | Takes an integer and performs scalar multiplication of the point. | |
263 | ||
264 | =head2 is_infinity | |
265 | ||
266 | Returns true if the point is (0,1), which is the point at infinity for | |
267 | the affine coordinates. | |
268 | ||
269 | =head2 copy | |
270 | ||
271 | Returns a copy of the point. | |
272 | ||
273 | =head2 normalize | |
274 | ||
275 | Performs an extended gcd operation to make C<z=1>. If a factor of C<n> is | |
276 | found it is put in C<f>. | |
277 | ||
278 | ||
279 | =head1 SEE ALSO | |
280 | ||
281 | L<Math::EllipticCurve::Prime> | |
282 | ||
283 | This really should just be in a L<Math::EllipticCurve> module. | |
284 | ||
285 | =head1 AUTHORS | |
286 | ||
287 | Dana Jacobsen E<lt>dana@acm.orgE<gt> | |
288 | ||
289 | ||
290 | =head1 COPYRIGHT | |
291 | ||
292 | Copyright 2012-2013 by Dana Jacobsen E<lt>dana@acm.orgE<gt> | |
293 | ||
294 | This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. | |
295 | ||
296 | =cut |
4 | 4 | |
5 | 5 | BEGIN { |
6 | 6 | $Math::Prime::Util::PP::AUTHORITY = 'cpan:DANAJ'; |
7 | $Math::Prime::Util::PP::VERSION = '0.24'; | |
7 | $Math::Prime::Util::PP::VERSION = '0.26'; | |
8 | 8 | } |
9 | 9 | |
10 | 10 | # The Pure Perl versions of all the Math::Prime::Util routines. |
881 | 881 | # It's now time to perform the Lucas pseudoprimality test using $D. |
882 | 882 | |
883 | 883 | if (ref($n) ne 'Math::BigInt') { |
884 | if (!defined $MATH::BigInt::VERSION) { | |
884 | if (!defined $Math::BigInt::VERSION) { | |
885 | 885 | eval { require Math::BigInt; Math::BigInt->import(try=>'GMP,Pari'); 1; } |
886 | 886 | or do { croak "Cannot load Math::BigInt "; } |
887 | 887 | } |
1030 | 1030 | sub is_aks_prime { |
1031 | 1031 | my $n = shift; |
1032 | 1032 | |
1033 | if (!defined $MATH::BigInt::VERSION) { | |
1033 | if (!defined $Math::BigInt::VERSION) { | |
1034 | 1034 | eval { require Math::BigInt; Math::BigInt->import(try=>'GMP,Pari'); 1; } |
1035 | 1035 | or do { croak "Cannot load Math::BigInt "; } |
1036 | 1036 | } |
1037 | if (!defined $MATH::BigFloat::VERSION) { | |
1037 | if (!defined $Math::BigFloat::VERSION) { | |
1038 | 1038 | eval { require Math::BigFloat; Math::BigFloat->import(); 1; } |
1039 | 1039 | or do { croak "Cannot load Math::BigFloat "; } |
1040 | 1040 | } |
1136 | 1136 | @factors; |
1137 | 1137 | } |
1138 | 1138 | |
1139 | my $_holf_r; | |
1140 | my @_fsublist = ( | |
1141 | sub { my $n = shift; return ($n) unless $n < $_half_word; | |
1142 | holf_factor ($n, 64*1024, $_holf_r); $_holf_r += 64*1024; }, | |
1143 | sub { prho_factor (shift, 8*1024, 3) }, | |
1144 | sub { pbrent_factor (shift, 32*1024, 1) }, | |
1145 | sub { pminus1_factor(shift, 10_000); }, | |
1146 | sub { pminus1_factor(shift, 600_000); }, | |
1147 | sub { pbrent_factor (shift, 512*1024, 7) }, | |
1148 | sub { ecm_factor (shift, 1_000, 5_000, 10) }, | |
1149 | sub { pminus1_factor(shift, 4_000_000); }, | |
1150 | sub { pbrent_factor (shift, 512*1024, 11) }, | |
1151 | sub { ecm_factor (shift, 10_000, 50_000, 10) }, | |
1152 | sub { holf_factor (shift, 256*1024, $_holf_r); $_holf_r += 256*1024; }, | |
1153 | sub { pminus1_factor(shift,20_000_000); }, | |
1154 | sub { ecm_factor (shift, 100_000, 800_000, 10) }, | |
1155 | sub { holf_factor (shift, 512*1024, $_holf_r); $_holf_r += 512*1024; }, | |
1156 | sub { pbrent_factor (shift, 2048*1024, 13) }, | |
1157 | sub { holf_factor (shift, 2048*1024, $_holf_r); $_holf_r += 2048*1024; }, | |
1158 | sub { ecm_factor (shift, 1_000_000, 1_000_000, 10) }, | |
1159 | sub { pminus1_factor(shift, 100_000_000, 500_000_000); }, | |
1160 | ); | |
1161 | ||
1139 | 1162 | sub factor { |
1140 | 1163 | my($n) = @_; |
1141 | 1164 | _validate_positive_integer($n); |
1167 | 1190 | #print "Looking at $n with stack ", join(",",@nstack), "\n"; |
1168 | 1191 | while ( ($n >= (31*31)) && !_is_prime7($n) ) { |
1169 | 1192 | my @ftry; |
1170 | my $holf_rounds = 0; | |
1171 | if ($n < $_half_word) { | |
1172 | $holf_rounds = 64*1024; | |
1173 | #warn "trying holf 64k on $n\n"; | |
1174 | @ftry = holf_factor($n, $holf_rounds); | |
1175 | } | |
1176 | if (scalar @ftry < 2) { | |
1177 | foreach my $add (3, 5, 7, 11, 13) { | |
1178 | #warn "trying prho 64k {$add} on $n\n" if scalar @ftry < 2; | |
1179 | @ftry = prho_factor($n, 64*1024, $add) if scalar @ftry < 2; | |
1180 | } | |
1181 | } | |
1182 | if (scalar @ftry < 2) { | |
1183 | #warn "trying holf 128k on $n\n"; | |
1184 | @ftry = holf_factor($n, 128*1024, $holf_rounds); | |
1185 | $holf_rounds += 128*1024; | |
1186 | } | |
1187 | if (scalar @ftry < 2) { | |
1188 | #warn "trying prho 128k {17} on $n\n"; | |
1189 | @ftry = prho_factor($n, 128*1024, 17); | |
1193 | $_holf_r = 1; | |
1194 | foreach my $sub (@_fsublist) { | |
1195 | last if scalar @ftry >= 2; | |
1196 | @ftry = $sub->($n); | |
1190 | 1197 | } |
1191 | 1198 | if (scalar @ftry > 1) { |
1192 | 1199 | #print " split into ", join(",",@ftry), "\n"; |
1205 | 1212 | sort {$a<=>$b} @factors; |
1206 | 1213 | } |
1207 | 1214 | |
1215 | sub _found_factor { | |
1216 | my($f, $n, $what, @factors) = @_; | |
1217 | if ($f == 1 || $f == $n) { | |
1218 | push @factors, $n; | |
1219 | } else { | |
1220 | # Perl 5.6.2 needs things spelled out for it. | |
1221 | my $f2 = (ref($n) eq 'Math::BigInt') ? $n->copy->bdiv($f)->as_int | |
1222 | : int($n/$f); | |
1223 | push @factors, $f; | |
1224 | push @factors, $f2; | |
1225 | croak "internal error in $what" unless $f * $f2 == $n; | |
1226 | # MPU::GMP prints this type of message if verbose, so do the same. | |
1227 | print "$what found factor $f\n" if Math::Prime::Util::prime_get_config()->{'verbose'} > 0; | |
1228 | } | |
1229 | @factors; | |
1230 | } | |
1231 | ||
1208 | 1232 | # TODO: |
1209 | sub fermat_factor { trial_factor(@_) } | |
1210 | 1233 | sub squfof_factor { trial_factor(@_) } |
1211 | 1234 | |
1212 | 1235 | sub prho_factor { |
1228 | 1251 | $V = $n->copy->bzero->badd($V); |
1229 | 1252 | for my $i (1 .. $rounds) { |
1230 | 1253 | # Would use bmuladd here, but old Math::BigInt's barf with scalar $a. |
1231 | #$U->bmuladd($U, $a); $U->bmod($n); | |
1232 | #$V->bmuladd($V, $a); $V->bmod($n); | |
1233 | #$V->bmuladd($V, $a); $V->bmod($n); | |
1234 | $U->bmul($U); $U->badd($a); $U->bmod($n); | |
1235 | $V->bmul($V); $V->badd($a); $V->bmod($n); | |
1236 | $V->bmul($V); $V->badd($a); $V->bmod($n); | |
1254 | $U->bmul($U)->badd($a)->bmod($n); | |
1255 | $V->bmul($V)->badd($a); | |
1256 | $V->bmul($V)->badd($a)->bmod($n); | |
1237 | 1257 | my $f = Math::BigInt::bgcd( ($U > $V) ? $U-$V : $V-$U, $n); |
1238 | 1258 | if ($f == $n) { |
1239 | 1259 | last if $inloop++; # We've been here before |
1240 | 1260 | } elsif ($f != 1) { |
1241 | my $f2 = $n->copy->bdiv($f)->as_int; | |
1242 | push @factors, $f; | |
1243 | push @factors, $f2; | |
1244 | croak "internal error in prho" unless ($f * $f2) == $n; | |
1245 | return @factors; | |
1261 | return _found_factor($f, $n, "prho", @factors); | |
1246 | 1262 | } |
1247 | 1263 | } |
1248 | 1264 | |
1256 | 1272 | if ($f == $n) { |
1257 | 1273 | last if $inloop++; # We've been here before |
1258 | 1274 | } elsif ($f != 1) { |
1259 | push @factors, $f; | |
1260 | push @factors, int($n/$f); | |
1261 | croak "internal error in prho" unless ($f * int($n/$f)) == $n; | |
1262 | return @factors; | |
1275 | return _found_factor($f, $n, "prho", @factors); | |
1263 | 1276 | } |
1264 | 1277 | } |
1265 | 1278 | |
1266 | 1279 | } else { |
1267 | 1280 | |
1268 | 1281 | for my $i (1 .. $rounds) { |
1269 | # U^2+a % n | |
1270 | $U = _mulmod($U, $U, $n); | |
1271 | $U = (($n-$U) > $a) ? $U+$a : $U+$a-$n; | |
1272 | # V^2+a % n | |
1273 | $V = _mulmod($V, $V, $n); | |
1274 | $V = (($n-$V) > $a) ? $V+$a : $V+$a-$n; | |
1275 | # V^2+a % n | |
1276 | $V = _mulmod($V, $V, $n); | |
1277 | $V = (($n-$V) > $a) ? $V+$a : $V+$a-$n; | |
1282 | $U = _mulmod($U, $U, $n); $U = (($n-$U) > $a) ? $U+$a : $U-$n+$a; | |
1283 | $V = _mulmod($V, $V, $n); $V = (($n-$V) > $a) ? $V+$a : $V-$n+$a; | |
1284 | $V = _mulmod($V, $V, $n); $V = (($n-$V) > $a) ? $V+$a : $V-$n+$a; | |
1278 | 1285 | my $f = _gcd_ui( ($U > $V) ? $U-$V : $V-$U, $n ); |
1279 | 1286 | if ($f == $n) { |
1280 | 1287 | last if $inloop++; # We've been here before |
1281 | 1288 | } elsif ($f != 1) { |
1282 | push @factors, $f; | |
1283 | push @factors, int($n/$f); | |
1284 | croak "internal error in prho" unless ($f * int($n/$f)) == $n; | |
1285 | return @factors; | |
1289 | return _found_factor($f, $n, "prho", @factors); | |
1286 | 1290 | } |
1287 | 1291 | } |
1288 | 1292 | |
1292 | 1296 | } |
1293 | 1297 | |
1294 | 1298 | sub pbrent_factor { |
1295 | my($n, $rounds) = @_; | |
1299 | my($n, $rounds, $a) = @_; | |
1296 | 1300 | _validate_positive_integer($n); |
1297 | 1301 | $rounds = 4*1024*1024 unless defined $rounds; |
1302 | $a = 3 unless defined $a; | |
1298 | 1303 | |
1299 | 1304 | my @factors = _basic_factor($n); |
1300 | 1305 | return @factors if $n < 4; |
1301 | 1306 | |
1302 | my $a = 1; | |
1303 | 1307 | my $Xi = 2; |
1304 | 1308 | my $Xm = 2; |
1305 | 1309 | |
1306 | 1310 | if ( ref($n) eq 'Math::BigInt' ) { |
1307 | 1311 | |
1308 | $Xi = $n->copy->bzero->badd($Xi); | |
1309 | $Xm = $n->copy->bzero->badd($Xm); | |
1310 | for my $i (1 .. $rounds) { | |
1311 | $Xi->bmul($Xi); $Xi->badd($a); $Xi->bmod($n); | |
1312 | my $f = Math::BigInt::bgcd( ($Xi > $Xm) ? $Xi-$Xm : $Xm-$Xi, $n); | |
1313 | if ( ($f != 1) && ($f != $n) ) { | |
1314 | my $f2 = $n->copy->bdiv($f)->as_int; | |
1315 | push @factors, $f; | |
1316 | push @factors, $f2; | |
1317 | croak "internal error in pbrent" unless ($f * $f2) == $n; | |
1318 | return @factors; | |
1319 | } | |
1320 | $Xm = $Xi->copy if ($i & ($i-1)) == 0; # i is a power of 2 | |
1312 | # Same code as the GMP version, but runs *much* slower. Even with | |
1313 | # Math::BigInt::GMP it's >200x slower. With the default Calc backend | |
1314 | # it's thousands of times slower. | |
1315 | my $inner = 256; | |
1316 | my $zero = $n->copy->bzero; | |
1317 | my $saveXi; | |
1318 | my $f; | |
1319 | $Xi = $zero->copy->badd($Xi); | |
1320 | $Xm = $zero->copy->badd($Xm); | |
1321 | my $r = 1; | |
1322 | while ($rounds > 0) { | |
1323 | my $rleft = ($r > $rounds) ? $rounds : $r; | |
1324 | while ($rleft > 0) { | |
1325 | my $dorounds = ($rleft > $inner) ? $inner : $rleft; | |
1326 | my $m = $zero->copy->bone; | |
1327 | $saveXi = $Xi->copy; | |
1328 | foreach my $i (1 .. $dorounds) { | |
1329 | $Xi->bmul($Xi)->badd($a)->bmod($n); | |
1330 | $m->bmul($Xi - $Xm); | |
1331 | } | |
1332 | $rleft -= $dorounds; | |
1333 | $rounds -= $dorounds; | |
1334 | $m->bmod($n); | |
1335 | $f = Math::BigInt::bgcd( $m, $n); | |
1336 | last if $f != 1; | |
1337 | } | |
1338 | if ($f == 1) { | |
1339 | $r *= 2; | |
1340 | $Xm = $Xi->copy; | |
1341 | next; | |
1342 | } | |
1343 | if ($f == $n) { # back up to determine the factor | |
1344 | $Xi = $saveXi->copy; | |
1345 | do { | |
1346 | $Xi->bmul($Xi)->badd($a)->bmod($n); | |
1347 | $f = Math::BigInt::bgcd( ($Xi > $Xm) ? $Xi-$Xm : $Xm-$Xi, $n); | |
1348 | } while ($f != 1 && $r-- != 0); | |
1349 | last if $f == 1 || $f == $n; | |
1350 | } | |
1351 | return _found_factor($f, $n, "pbrent", @factors); | |
1321 | 1352 | } |
1322 | 1353 | |
1323 | 1354 | } elsif ($n < $_half_word) { |
1325 | 1356 | for my $i (1 .. $rounds) { |
1326 | 1357 | $Xi = ($Xi * $Xi + $a) % $n; |
1327 | 1358 | my $f = _gcd_ui( ($Xi > $Xm) ? $Xi-$Xm : $Xm-$Xi, $n ); |
1328 | if ( ($f != 1) && ($f != $n) ) { | |
1329 | push @factors, $f; | |
1330 | push @factors, int($n/$f); | |
1331 | croak "internal error in pbrent" unless ($f * int($n/$f)) == $n; | |
1332 | return @factors; | |
1333 | } | |
1359 | return _found_factor($f, $n, "pbrent", @factors) if $f != 1 && $f != $n; | |
1334 | 1360 | $Xm = $Xi if ($i & ($i-1)) == 0; # i is a power of 2 |
1335 | 1361 | } |
1336 | 1362 | |
1341 | 1367 | $Xi = _mulmod($Xi, $Xi, $n); |
1342 | 1368 | $Xi = (($n-$Xi) > $a) ? $Xi+$a : $Xi+$a-$n; |
1343 | 1369 | my $f = _gcd_ui( ($Xi > $Xm) ? $Xi-$Xm : $Xm-$Xi, $n ); |
1344 | if ( ($f != 1) && ($f != $n) ) { | |
1345 | push @factors, $f; | |
1346 | push @factors, int($n/$f); | |
1347 | croak "internal error in pbrent" unless ($f * int($n/$f)) == $n; | |
1348 | return @factors; | |
1349 | } | |
1370 | return _found_factor($f, $n, "pbrent", @factors) if $f != 1 && $f != $n; | |
1350 | 1371 | $Xm = $Xi if ($i & ($i-1)) == 0; # i is a power of 2 |
1351 | 1372 | } |
1352 | 1373 | |
1355 | 1376 | @factors; |
1356 | 1377 | } |
1357 | 1378 | |
1358 | # This code is bollocks. See a proper implementation in factor.c | |
1359 | 1379 | sub pminus1_factor { |
1360 | my($n, $rounds) = @_; | |
1380 | my($n, $B1, $B2) = @_; | |
1361 | 1381 | _validate_positive_integer($n); |
1362 | $rounds = 4*1024*1024 unless defined $rounds; | |
1363 | 1382 | |
1364 | 1383 | my @factors = _basic_factor($n); |
1365 | 1384 | return @factors if $n < 4; |
1366 | 1385 | |
1367 | if ( ref($n) eq 'Math::BigInt' ) { | |
1368 | my $kf = $n->copy->bzero->badd(13); | |
1369 | for my $i (1 .. $rounds) { | |
1370 | $kf->bmodpow($i,$n); | |
1371 | $kf = $n if $kf == 0; | |
1372 | my $f = Math::BigInt::bgcd( $kf-1, $n ); | |
1373 | if ( ($f != 1) && ($f != $n) ) { | |
1374 | my $f2 = $n->copy->bdiv($f)->as_int; | |
1375 | push @factors, $f; | |
1376 | push @factors, $f2; | |
1377 | croak "internal error in pminus1" unless ($f * $f2) == $n; | |
1386 | if ( ref($n) ne 'Math::BigInt' ) { | |
1387 | # Stage 1 only | |
1388 | $B1 = 10_000_000 unless defined $B1; | |
1389 | my $a = 2; | |
1390 | my $f = 1; | |
1391 | my($pc_beg, $pc_end, @bprimes); | |
1392 | $pc_beg = 2; | |
1393 | $pc_end = $pc_beg + 100_000; | |
1394 | my $sqrtb1 = int(sqrt($B1)); | |
1395 | while (1) { | |
1396 | $pc_end = $B1 if $pc_end > $B1; | |
1397 | @bprimes = @{ primes($pc_beg, $pc_end) }; | |
1398 | while (@bprimes) { | |
1399 | my $q = shift @bprimes; | |
1400 | my $k = $q; | |
1401 | if ($q <= $sqrtb1) { | |
1402 | my $kmin = int($B1 / $q); | |
1403 | while ($k <= $kmin) { $k *= $q; } | |
1404 | } | |
1405 | $a = _powmod($a, $k, $n); | |
1406 | if ($a == 0) { push @factors, $n; return @factors; } | |
1407 | my $f = _gcd_ui( $a-1, $n ); | |
1408 | return _found_factor($f, $n, "pminus1", @factors) if $f != 1; | |
1409 | } | |
1410 | last if $pc_end >= $B1; | |
1411 | $pc_beg = $pc_end+1; | |
1412 | $pc_end += 500_000; | |
1413 | } | |
1414 | push @factors, $n; | |
1415 | return @factors; | |
1416 | } | |
1417 | ||
1418 | # Stage 2 isn't really any faster than stage 1 for the examples I've tried. | |
1419 | ||
1420 | if (!defined $B1) { | |
1421 | for my $mul (1, 100, 1000, 10_000, 100_000, 1_000_000) { | |
1422 | $B1 = 1000 * $mul; | |
1423 | $B2 = 1*$B1; | |
1424 | #warn "Trying p-1 with $B1 / $B2\n"; | |
1425 | my @nf = pminus1_factor($n, $B1, $B2); | |
1426 | if (scalar @nf > 1) { | |
1427 | push @factors, @nf; | |
1378 | 1428 | return @factors; |
1379 | 1429 | } |
1380 | 1430 | } |
1381 | } else { | |
1382 | my $kf = 13; | |
1383 | for my $i (1 .. $rounds) { | |
1384 | $kf = _powmod($kf, $i, $n); | |
1385 | $kf = $n if $kf == 0; | |
1386 | my $f = _gcd_ui( $kf-1, $n ); | |
1387 | if ( ($f != 1) && ($f != $n) ) { | |
1388 | push @factors, $f; | |
1389 | push @factors, int($n/$f); | |
1390 | croak "internal error in pminus1" unless ($f * int($n/$f)) == $n; | |
1391 | return @factors; | |
1392 | } | |
1393 | } | |
1394 | } | |
1395 | push @factors, $n; | |
1396 | @factors; | |
1431 | push @factors, $n; | |
1432 | return @factors; | |
1433 | } | |
1434 | $B2 = 1*$B1 unless defined $B2; | |
1435 | ||
1436 | my $one = $n->copy->bone; | |
1437 | my ($j, $q, $saveq) = (1, 2, 2); | |
1438 | my $t = $one->copy; | |
1439 | my $a = $one->copy->badd(1); | |
1440 | my $savea = $a->copy; | |
1441 | my $f = 1; | |
1442 | my($pc_beg, $pc_end, @bprimes); | |
1443 | ||
1444 | $pc_beg = 2; | |
1445 | $pc_end = $pc_beg + 100_000; | |
1446 | while (1) { | |
1447 | $pc_end = $B1 if $pc_end > $B1; | |
1448 | @bprimes = @{ primes($pc_beg, $pc_end) }; | |
1449 | while (@bprimes) { | |
1450 | $q = shift @bprimes; | |
1451 | my $k = $q; | |
1452 | my $kmin = int($B1 / $q); | |
1453 | while ($k <= $kmin) { $k *= $q; } | |
1454 | $t *= $k; # accumulate powers for a | |
1455 | if ( ($j++ % 32) == 0) { | |
1456 | $a->bmodpow($t, $n); | |
1457 | $t = $one->copy; | |
1458 | if ($a == 0) { push @factors, $n; return @factors; } | |
1459 | $f = Math::BigInt::bgcd( $a-1, $n ); | |
1460 | last if $f == $n; | |
1461 | if ($f != 1) { | |
1462 | push @factors, $f, $n/$f; | |
1463 | return @factors; | |
1464 | } | |
1465 | $saveq = $q; | |
1466 | $savea = $a->copy; | |
1467 | } | |
1468 | } | |
1469 | last if $f != 1 || $pc_end >= $B1; | |
1470 | $pc_beg = $pc_end+1; | |
1471 | $pc_end += 500_000; | |
1472 | } | |
1473 | undef @bprimes; | |
1474 | $a->bmodpow($t, $n); | |
1475 | if ($a == 0) { push @factors, $n; return @factors; } | |
1476 | $f = Math::BigInt::bgcd( $a-1, $n ); | |
1477 | if ($f == $n) { | |
1478 | $q = $saveq; | |
1479 | $a = $savea->copy; | |
1480 | while ($q <= $B1) { | |
1481 | my $k = $q; | |
1482 | my $kmin = int($B1 / $q); | |
1483 | while ($k <= $kmin) { $k *= $q; } | |
1484 | $a->bmodpow($k, $n); | |
1485 | my $f = Math::BigInt::bgcd( $a-1, $n ); | |
1486 | if ($f == $n) { push @factors, $n; return @factors; } | |
1487 | last if $f != 1; | |
1488 | $q = next_prime($q); | |
1489 | } | |
1490 | } | |
1491 | # STAGE 2 | |
1492 | if ($f == 1 && $B2 > $B1) { | |
1493 | my $bm = $a->copy; | |
1494 | my $b = $one->copy; | |
1495 | my @precomp_bm; | |
1496 | $precomp_bm[0] = ($bm * $bm) % $n; | |
1497 | foreach my $j (1..19) { | |
1498 | $precomp_bm[$j] = ($precomp_bm[$j-1] * $bm * $bm) % $n; | |
1499 | } | |
1500 | $a->bmodpow($q, $n); | |
1501 | my $j = 1; | |
1502 | $pc_beg = $q+1; | |
1503 | $pc_end = $pc_beg + 100_000; | |
1504 | while (1) { | |
1505 | $pc_end = $B2 if $pc_end > $B2; | |
1506 | @bprimes = @{ primes($pc_beg, $pc_end) }; | |
1507 | while (@bprimes) { | |
1508 | my $lastq = $q; | |
1509 | $q = shift @bprimes; | |
1510 | my $qdiff = ($q - $lastq) / 2 - 1; | |
1511 | if (!defined $precomp_bm[$qdiff]) { | |
1512 | $precomp_bm[$qdiff] = $bm->copy->bmodpow($q-$lastq, $n); | |
1513 | } | |
1514 | $a->bmul($precomp_bm[$qdiff])->bmod($n); | |
1515 | if ($a == 0) { push @factors, $n; return @factors; } | |
1516 | $b->bmul($a-1); | |
1517 | if (($j++ % 64) == 0) { | |
1518 | $b->bmod($n); | |
1519 | $f = Math::BigInt::bgcd( $b, $n ); | |
1520 | last if $f != 1; | |
1521 | } | |
1522 | } | |
1523 | last if $f != 1 || $pc_end >= $B2; | |
1524 | $pc_beg = $pc_end+1; | |
1525 | $pc_end += 500_000; | |
1526 | } | |
1527 | $f = Math::BigInt::bgcd( $b, $n ); | |
1528 | } | |
1529 | return _found_factor($f, $n, "pminus1", @factors); | |
1397 | 1530 | } |
1398 | 1531 | |
1399 | 1532 | sub holf_factor { |
1401 | 1534 | _validate_positive_integer($n); |
1402 | 1535 | $rounds = 64*1024*1024 unless defined $rounds; |
1403 | 1536 | $startrounds = 1 unless defined $startrounds; |
1537 | $startrounds = 1 if $startrounds < 1; | |
1404 | 1538 | |
1405 | 1539 | my @factors = _basic_factor($n); |
1406 | 1540 | return @factors if $n < 4; |
1409 | 1543 | for my $i ($startrounds .. $rounds) { |
1410 | 1544 | my $ni = $n->copy->bmul($i); |
1411 | 1545 | my $s = $ni->copy->bsqrt->bfloor->as_int; |
1412 | $s->binc if ($s * $s) != $ni; | |
1413 | my $m = $s->copy->bmul($s)->bmod($n); | |
1546 | if ($s * $s == $ni) { | |
1547 | # s^2 = n*i, so m = s^2 mod n = 0. Hence f = GCD(n, s) = GCD(n, n*i) | |
1548 | my $f = Math::BigInt::bgcd($ni, $n); | |
1549 | return _found_factor($f, $n, "HOLF", @factors); | |
1550 | } | |
1551 | $s->binc; | |
1552 | my $m = ($s * $s) - $ni; | |
1414 | 1553 | # Check for perfect square |
1415 | 1554 | my $mc = int(($m & 31)->bstr); |
1416 | 1555 | next unless $mc==0||$mc==1||$mc==4||$mc==9||$mc==16||$mc==17||$mc==25; |
1417 | 1556 | my $f = $m->copy->bsqrt->bfloor->as_int; |
1418 | 1557 | next unless ($f*$f) == $m; |
1419 | 1558 | $f = Math::BigInt::bgcd( ($s > $f) ? $s-$f : $f-$s, $n); |
1420 | last if $f == 1 || $f == $n; # Should never happen | |
1421 | my $f2 = $n->copy->bdiv($f)->as_int; | |
1422 | push @factors, $f; | |
1423 | push @factors, $f2; | |
1424 | croak "internal error in HOLF" unless ($f * $f2) == $n; | |
1425 | # print "HOLF found factors in $i rounds\n"; | |
1426 | return @factors; | |
1559 | return _found_factor($f, $n, "HOLF ($i rounds)", @factors); | |
1427 | 1560 | } |
1428 | 1561 | } else { |
1429 | 1562 | for my $i ($startrounds .. $rounds) { |
1436 | 1569 | my $f = int(sqrt($m)); |
1437 | 1570 | next unless $f*$f == $m; |
1438 | 1571 | $f = _gcd_ui( ($s > $f) ? $s - $f : $f - $s, $n); |
1439 | last if $f == 1 || $f == $n; # Should never happen | |
1440 | push @factors, $f; | |
1441 | push @factors, int($n/$f); | |
1442 | croak "internal error in HOLF" unless ($f * int($n/$f)) == $n; | |
1443 | # print "HOLF found factors in $i rounds\n"; | |
1444 | return @factors; | |
1572 | return _found_factor($f, $n, "HOLF ($i rounds)", @factors); | |
1445 | 1573 | } |
1446 | 1574 | } |
1447 | 1575 | push @factors, $n; |
1448 | 1576 | @factors; |
1449 | 1577 | } |
1450 | 1578 | |
1451 | ||
1579 | sub fermat_factor { | |
1580 | my($n, $rounds) = @_; | |
1581 | _validate_positive_integer($n); | |
1582 | $rounds = 64*1024*1024 unless defined $rounds; | |
1583 | ||
1584 | my @factors = _basic_factor($n); | |
1585 | return @factors if $n < 4; | |
1586 | ||
1587 | if ( ref($n) eq 'Math::BigInt' ) { | |
1588 | my $a = $n->copy->bsqrt->bfloor->as_int; | |
1589 | return _found_factor($a, $n, "Fermat", @factors) if $a*$a == $n; | |
1590 | $a++; | |
1591 | my $b2 = $a*$a - $n; | |
1592 | my $lasta = $a + $rounds; | |
1593 | while ($a <= $lasta) { | |
1594 | my $mc = int(($b2 & 31)->bstr); | |
1595 | if ($mc==0||$mc==1||$mc==4||$mc==9||$mc==16||$mc==17||$mc==25) { | |
1596 | my $s = $b2->copy->bsqrt->bfloor->as_int; | |
1597 | if ($s*$s == $b2) { | |
1598 | my $i = $a-($lasta-$rounds)+1; | |
1599 | return _found_factor($a - $s, $n, "Fermat ($i rounds)", @factors); | |
1600 | } | |
1601 | } | |
1602 | $a++; | |
1603 | $b2 = $a*$a-$n; | |
1604 | } | |
1605 | } else { | |
1606 | my $a = int(sqrt($n)); | |
1607 | return _found_factor($a, $n, "Fermat", @factors) if $a*$a == $n; | |
1608 | $a++; | |
1609 | my $b2 = $a*$a - $n; | |
1610 | my $lasta = $a + $rounds; | |
1611 | while ($a <= $lasta) { | |
1612 | my $mc = $b2 & 31; | |
1613 | if ($mc==0||$mc==1||$mc==4||$mc==9||$mc==16||$mc==17||$mc==25) { | |
1614 | my $s = int(sqrt($b2)); | |
1615 | if ($s*$s == $b2) { | |
1616 | my $i = $a-($lasta-$rounds)+1; | |
1617 | return _found_factor($a - $s, $n, "Fermat ($i rounds)", @factors); | |
1618 | } | |
1619 | } | |
1620 | $a++; | |
1621 | $b2 = $a*$a-$n; | |
1622 | } | |
1623 | } | |
1624 | push @factors, $n; | |
1625 | @factors; | |
1626 | } | |
1627 | ||
1628 | ||
1629 | sub ecm_factor { | |
1630 | my($n, $B1, $B2, $ncurves) = @_; | |
1631 | _validate_positive_integer($n); | |
1632 | ||
1633 | my @factors = _basic_factor($n); | |
1634 | return @factors if $n < 4; | |
1635 | ||
1636 | $ncurves = 10 unless defined $ncurves; | |
1637 | ||
1638 | if (!defined $B1) { | |
1639 | for my $mul (1, 10, 100, 1000, 10_000, 100_000, 1_000_000) { | |
1640 | $B1 = 100 * $mul; | |
1641 | $B2 = 10*$B1; | |
1642 | #warn "Trying ecm with $B1 / $B2\n"; | |
1643 | my @nf = ecm_factor($n, $B1, $B2, $ncurves); | |
1644 | if (scalar @nf > 1) { | |
1645 | push @factors, @nf; | |
1646 | return @factors; | |
1647 | } | |
1648 | } | |
1649 | push @factors, $n; | |
1650 | return @factors; | |
1651 | } | |
1652 | ||
1653 | $B2 = 10*$B1 unless defined $B2; | |
1654 | my $sqrt_b1 = int(sqrt($B1)+1); | |
1655 | ||
1656 | # Affine code. About 3x slower than the projective, and no stage 2. | |
1657 | # | |
1658 | #if (!defined $Math::Prime::Util::ECAffinePoint::VERSION) { | |
1659 | # eval { require Math::Prime::Util::ECAffinePoint; 1; } | |
1660 | # or do { croak "Cannot load Math::Prime::Util::ECAffinePoint"; }; | |
1661 | #} | |
1662 | #my @bprimes = @{ primes(2, $B1) }; | |
1663 | #my $irandf = Math::Prime::Util::_get_rand_func(); | |
1664 | #foreach my $curve (1 .. $ncurves) { | |
1665 | # my $a = $irandf->($n-1); | |
1666 | # my $b = 1; | |
1667 | # my $ECP = Math::Prime::Util::ECAffinePoint->new($a, $b, $n, 0, 1); | |
1668 | # foreach my $q (@bprimes) { | |
1669 | # my $k = $q; | |
1670 | # if ($k < $sqrt_b1) { | |
1671 | # my $kmin = int($B1 / $q); | |
1672 | # while ($k <= $kmin) { $k *= $q; } | |
1673 | # } | |
1674 | # $ECP->mul($k); | |
1675 | # my $f = $ECP->f; | |
1676 | # if ($f != 1) { | |
1677 | # last if $f == $n; | |
1678 | # warn "ECM found factors with B1 = $B1 in curve $curve\n"; | |
1679 | # return _found_factor($f, $n, "ECM B1=$B1 curve $curve", @factors); | |
1680 | # } | |
1681 | # last if $ECP->is_infinity; | |
1682 | # } | |
1683 | #} | |
1684 | ||
1685 | if (!defined $Math::Prime::Util::ECProjectivePoint::VERSION) { | |
1686 | eval { require Math::Prime::Util::ECProjectivePoint; 1; } | |
1687 | or do { croak "Cannot load Math::Prime::Util::ECProjectivePoint"; }; | |
1688 | } | |
1689 | ||
1690 | # With multiple curves, it's better to get all the primes at once. | |
1691 | # The downside is this can kill memory with a very large B1. | |
1692 | my @bprimes = @{ primes(3, $B1) }; | |
1693 | my @b2primes = ($B2 > $B1) ? @{primes($B1+1, $B2)} : (); | |
1694 | my $irandf = Math::Prime::Util::_get_rand_func(); | |
1695 | ||
1696 | foreach my $curve (1 .. $ncurves) { | |
1697 | my $sigma = $irandf->($n-1-6) + 6; | |
1698 | my ($u, $v) = ( ($sigma*$sigma - 5) % $n, (4 * $sigma) % $n ); | |
1699 | my ($x, $z) = ( ($u*$u*$u) % $n, ($v*$v*$v) % $n ); | |
1700 | my $b = (4 * $x * $v) % $n; | |
1701 | my $a = ( (($v-$u)**3) * (3*$u + $v) ) % $n; | |
1702 | my $f = Math::BigInt::bgcd( $b, $n ); | |
1703 | $f = Math::BigInt::bgcd( $z, $n ) if $f == 1; | |
1704 | next if $f == $n; | |
1705 | return _found_factor($f,$n, "ECM B1=$B1 curve $curve", @factors) if $f != 1; | |
1706 | $u = $b->copy->bmodinv($n); | |
1707 | $a = (($a*$u) - 2) % $n; | |
1708 | ||
1709 | my $ECP = Math::Prime::Util::ECProjectivePoint->new($a, $n, $x, $z); | |
1710 | my $fm = $n-$n+1; | |
1711 | my $i = 15; | |
1712 | ||
1713 | for (my $q = 2; $q < $B1; $q *= 2) { $ECP->double(); } | |
1714 | foreach my $q (@bprimes) { | |
1715 | my $k = $q; | |
1716 | if ($k < $sqrt_b1) { | |
1717 | my $kmin = int($B1 / $q); | |
1718 | while ($k <= $kmin) { $k *= $q; } | |
1719 | } | |
1720 | $ECP->mul($k); | |
1721 | $fm = ($fm * $ECP->x() ) % $n; | |
1722 | if ($i++ % 32 == 0) { | |
1723 | $f = Math::BigInt::bgcd($fm, $n); | |
1724 | last if $f != 1; | |
1725 | } | |
1726 | } | |
1727 | $f = Math::BigInt::bgcd($fm, $n); | |
1728 | next if $f == $n; | |
1729 | ||
1730 | if ($f == 1 && $B2 > $B1) { # BEGIN STAGE 2 | |
1731 | my $D = int(sqrt($B2/2)); $D++ if $D % 2; | |
1732 | my $one = $n - $n + 1; | |
1733 | my $g = $one; | |
1734 | ||
1735 | my $S2P = $ECP->copy->normalize; | |
1736 | $f = $S2P->f; | |
1737 | if ($f != 1) { | |
1738 | next if $f == $n; | |
1739 | #warn "ECM S2 normalize f=$f\n" if $f != 1; | |
1740 | return _found_factor($f, $n, "ECM S2 B1=$B1 curve $curve"); | |
1741 | } | |
1742 | my $S2x = $S2P->x; | |
1743 | my $S2d = $S2P->d; | |
1744 | my @nqx = ($n-$n, $S2x); | |
1745 | ||
1746 | foreach my $i (2 .. 2*$D) { | |
1747 | my($x2, $z2); | |
1748 | if ($i % 2) { | |
1749 | ($x2, $z2) = Math::Prime::Util::ECProjectivePoint::_addx($nqx[($i-1)/2], $nqx[($i+1)/2], $S2x, $n); | |
1750 | } else { | |
1751 | ($x2, $z2) = Math::Prime::Util::ECProjectivePoint::_double($nqx[$i/2], $one, $n, $S2d); | |
1752 | } | |
1753 | $nqx[$i] = $x2; | |
1754 | #($f, $u, undef) = _extended_gcd($z2, $n); | |
1755 | $f = Math::BigInt::bgcd( $z2, $n ); | |
1756 | last if $f != 1; | |
1757 | $u = $z2->copy->bmodinv($n); | |
1758 | $nqx[$i] = ($x2 * $u) % $n; | |
1759 | } | |
1760 | if ($f != 1) { | |
1761 | next if $f == $n; | |
1762 | #warn "ECM S2 1: B1 $B1 B2 $B2 curve $curve f=$f\n"; | |
1763 | return _found_factor($f, $n, "ECM S2 B1=$B1 curve $curve", @factors); | |
1764 | } | |
1765 | ||
1766 | $x = $nqx[2*$D-1]; | |
1767 | my $m = 1; | |
1768 | while ($m < ($B2+$D)) { | |
1769 | if ($m != 1) { | |
1770 | my $oldx = $S2x; | |
1771 | my ($x1, $z1) = Math::Prime::Util::ECProjectivePoint::_addx($nqx[2*$D], $S2x, $x, $n); | |
1772 | $f = Math::BigInt::bgcd( $z1, $n ); | |
1773 | last if $f != 1; | |
1774 | $u = $z1->copy->bmodinv($n); | |
1775 | $S2x = ($x1 * $u) % $n; | |
1776 | $x = $oldx; | |
1777 | last if $f != 1; | |
1778 | } | |
1779 | if ($m+$D > $B1) { | |
1780 | my @p = grep { $_ >= $m-$D && $_ <= $m+$D } @b2primes; | |
1781 | foreach my $i (@p) { | |
1782 | last if $i >= $m; | |
1783 | $g = ($g * ($S2x - $nqx[$m+$D-$i])) % $n; | |
1784 | } | |
1785 | foreach my $i (@p) { | |
1786 | next unless $i > $m; | |
1787 | next if is_prime($m+$m-$i); | |
1788 | $g = ($g * ($S2x - $nqx[$i-$m])) % $n; | |
1789 | } | |
1790 | $f = Math::BigInt::bgcd($g, $n); | |
1791 | #warn "ECM S2 3: found $f in stage 2\n" if $f != 1; | |
1792 | last if $f != 1; | |
1793 | } | |
1794 | $m += 2*$D; | |
1795 | } | |
1796 | } # END STAGE 2 | |
1797 | ||
1798 | next if $f == $n; | |
1799 | if ($f != 1) { | |
1800 | #warn "ECM found factors with B1 = $B1 in curve $curve\n"; | |
1801 | return _found_factor($f, $n, "ECM B1=$B1 curve $curve", @factors); | |
1802 | } | |
1803 | # end of curve loop | |
1804 | } | |
1805 | push @factors, $n; | |
1806 | @factors; | |
1807 | } | |
1808 | ||
1809 | ||
1810 | sub primality_proof_lucas { | |
1811 | my ($n) = shift; | |
1812 | my @composite = (0, []); | |
1813 | ||
1814 | # Since this can take a very long time with a composite, try some easy cuts | |
1815 | return @composite if !defined $n || $n < 2; | |
1816 | return (2, [$n]) if $n < 4; | |
1817 | return @composite if miller_rabin($n,2,15,325) == 0; | |
1818 | ||
1819 | if (!defined $Math::BigInt::VERSION) { | |
1820 | eval { require Math::BigInt; Math::BigInt->import(try=>'GMP,Pari'); 1; } | |
1821 | or do { croak "Cannot load Math::BigInt"; }; | |
1822 | } | |
1823 | ||
1824 | my $nm1 = $n-1; | |
1825 | my @factors = factor($nm1); | |
1826 | { # remove duplicate factors and make a sorted array of bigints | |
1827 | my %uf; | |
1828 | undef @uf{@factors}; | |
1829 | @factors = sort {$a<=>$b} map { Math::BigInt->new("$_") } keys %uf; | |
1830 | } | |
1831 | for (my $a = 2; $a < $nm1; $a++) { | |
1832 | my $ap = Math::BigInt->new("$a"); | |
1833 | # 1. a must be coprime to n | |
1834 | next unless Math::BigInt::bgcd($ap, $n) == 1; | |
1835 | # 2. a^(n-1) = 1 mod n. | |
1836 | next unless $ap->copy->bmodpow($nm1, $n) == 1; | |
1837 | # 3. a^((n-1)/f) != 1 mod n for all f. | |
1838 | next if (scalar grep { $_ == 1 } | |
1839 | map { $ap->copy->bmodpow(int($nm1/$_),$n); } | |
1840 | @factors) > 0; | |
1841 | # Verify each factor and add to proof | |
1842 | my @fac_proofs; | |
1843 | foreach my $f (@factors) { | |
1844 | my ($isp, $fproof) = Math::Prime::Util::is_provable_prime_with_cert($f); | |
1845 | if ($isp != 2) { | |
1846 | carp "could not prove primality of $n.\n"; | |
1847 | return (1, []); | |
1848 | } | |
1849 | push @fac_proofs, (scalar @$fproof == 1) ? $fproof->[0] : $fproof; | |
1850 | } | |
1851 | my @proof = ("$n", "Pratt", [@fac_proofs], $a); | |
1852 | return (2, [@proof]); | |
1853 | } | |
1854 | return @composite; | |
1855 | } | |
1856 | ||
1857 | sub primality_proof_bls75 { | |
1858 | my ($n) = shift; | |
1859 | my @composite = (0, []); | |
1860 | ||
1861 | # Since this can take a very long time with a composite, try some easy cuts | |
1862 | return @composite if !defined $n || $n < 2; | |
1863 | return (2, [$n]) if $n < 4; | |
1864 | return @composite if ($n & 1) == 0; | |
1865 | return @composite if miller_rabin($n,2,15,325) == 0; | |
1866 | ||
1867 | if (!defined $Math::BigInt::VERSION) { | |
1868 | eval { require Math::BigInt; Math::BigInt->import(try=>'GMP,Pari'); 1; } | |
1869 | or do { croak "Cannot load Math::BigInt"; }; | |
1870 | } | |
1871 | ||
1872 | $n = Math::BigInt->new("$n") unless ref($n) eq 'Math::BigInt'; | |
1873 | my $nm1 = $n-1; | |
1874 | my $A = $nm1->copy->bone; # factored part | |
1875 | my $B = $nm1->copy; # unfactored part | |
1876 | my @factors = (2); | |
1877 | croak "BLS75 error: n-1 not even" unless $nm1->is_even(); | |
1878 | while ($B->is_even) { $B /= 2; $A *= 2; } | |
1879 | foreach my $f (3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79) { | |
1880 | last if $f*$f > $B; | |
1881 | if (($B % $f) == 0) { | |
1882 | push @factors, $f; | |
1883 | do { $B /= $f; $A *= $f; } while (($B % $f) == 0); | |
1884 | } | |
1885 | } | |
1886 | my @nstack; | |
1887 | # nstack should only hold composites | |
1888 | if ($B == 1) { | |
1889 | # Completely factored. Nothing. | |
1890 | } elsif (Math::Prime::Util::is_prob_prime($B)) { | |
1891 | push @factors, $B; | |
1892 | $A *= $B; $B /= $B; # completely factored already | |
1893 | } else { | |
1894 | push @nstack, $B; | |
1895 | } | |
1896 | while (@nstack) { | |
1897 | my ($s,$r) = $B->copy->bdiv($A->copy->bmul(2)); | |
1898 | my $fpart = ($A+1) * (2*$A*$A + ($r-1) * $A + 1); | |
1899 | last if $n < $fpart; | |
1900 | ||
1901 | my $m = pop @nstack; | |
1902 | # Don't use bignum if it has gotten small enough. | |
1903 | $m = int($m->bstr) if ref($m) eq 'Math::BigInt' && $m <= ~0; | |
1904 | # Try to find factors of m, using the default set of factor subs. | |
1905 | my @ftry; | |
1906 | $_holf_r = 1; | |
1907 | foreach my $sub (@_fsublist) { | |
1908 | last if scalar @ftry >= 2; | |
1909 | @ftry = $sub->($m); | |
1910 | } | |
1911 | # If we couldn't find a factor, skip it. | |
1912 | next unless scalar @ftry > 1; | |
1913 | # Process each factor | |
1914 | foreach my $f (@ftry) { | |
1915 | croak "Invalid factoring" if $f == 1 || $f == $m || ($B%$f) != 0; | |
1916 | if (Math::Prime::Util::is_prob_prime($f)) { | |
1917 | push @factors, $f; | |
1918 | do { $B /= $f; $A *= $f; } while (($B % $f) == 0); | |
1919 | } else { | |
1920 | push @nstack, $f; | |
1921 | } | |
1922 | } | |
1923 | } | |
1924 | # Just in case: | |
1925 | foreach my $f (@factors) { | |
1926 | while (($B % $f) == 0) { | |
1927 | $B /= $f; $A *= $f; | |
1928 | } | |
1929 | } | |
1930 | { # remove duplicate factors and make a sorted array of bigints | |
1931 | my %uf = map { $_ => 1 } @factors; | |
1932 | @factors = sort {$a<=>$b} map { Math::BigInt->new("$_") } keys %uf; | |
1933 | } | |
1934 | # Did we factor enough? | |
1935 | my ($s,$r) = $B->copy->bdiv($A->copy->bmul(2)); | |
1936 | my $fpart = ($A+1) * (2*$A*$A + ($r-1) * $A + 1); | |
1937 | return (1,[]) if $n >= $fpart; | |
1938 | # Check we didn't mess up | |
1939 | croak "BLS75 error: $A * $B != $nm1" unless $A*$B == $nm1; | |
1940 | croak "BLS75 error: $A not even" unless $A->is_even(); | |
1941 | croak "BLS75 error: A and B not coprime" unless Math::BigInt::bgcd($A, $B)==1; | |
1942 | ||
1943 | my $rtest = $r*$r - 8*$s; | |
1944 | my $rtestroot = $rtest->copy->bsqrt; | |
1945 | return @composite if $s != 0 && ($rtestroot*$rtestroot) == $rtest; | |
1946 | ||
1947 | my @fac_proofs; | |
1948 | my @as; | |
1949 | foreach my $f (@factors) { | |
1950 | my $success = 0; | |
1951 | foreach my $a (2 .. 10000) { | |
1952 | my $ap = Math::BigInt->new("$a"); | |
1953 | next unless $ap->copy->bmodpow($nm1, $n) == 1; | |
1954 | next unless Math::BigInt::bgcd($ap->copy->bmodpow($nm1/$f, $n)->bsub(1), $n) == 1; | |
1955 | push @as, $a; | |
1956 | $success = 1; | |
1957 | last; | |
1958 | } | |
1959 | return @composite unless $success; | |
1960 | my ($isp, $fproof) = Math::Prime::Util::is_provable_prime_with_cert($f); | |
1961 | if ($isp != 2) { | |
1962 | carp "could not prove primality of $n.\n"; | |
1963 | return (1, []); | |
1964 | } | |
1965 | push @fac_proofs, (scalar @$fproof == 1) ? $fproof->[0] : $fproof; | |
1966 | } | |
1967 | my @proof = ($n, "n-1", [@fac_proofs], [@as]); | |
1968 | return (2, [@proof]); | |
1969 | } | |
1452 | 1970 | |
1453 | 1971 | |
1454 | 1972 | my $_const_euler = 0.57721566490153286060651209008240243104215933593992; |
1471 | 1989 | my $wantbf = 0; |
1472 | 1990 | my $xdigits = 17; |
1473 | 1991 | if (defined $bignum::VERSION || ref($x) =~ /^Math::Big/) { |
1474 | if (!defined $MATH::BigFloat::VERSION) { | |
1992 | if (!defined $Math::BigFloat::VERSION) { | |
1475 | 1993 | eval { require Math::BigFloat; Math::BigFloat->import(); 1; } |
1476 | 1994 | or do { croak "Cannot load Math::BigFloat "; } |
1477 | 1995 | } |
1581 | 2099 | my $wantbf = 0; |
1582 | 2100 | my $xdigits = 17; |
1583 | 2101 | if (defined $bignum::VERSION || ref($x) =~ /^Math::Big/) { |
1584 | if (!defined $MATH::BigFloat::VERSION) { | |
2102 | if (!defined $Math::BigFloat::VERSION) { | |
1585 | 2103 | eval { require Math::BigFloat; Math::BigFloat->import(); 1; } |
1586 | 2104 | or do { croak "Cannot load Math::BigFloat "; } |
1587 | 2105 | } |
1713 | 2231 | my $wantbf = 0; |
1714 | 2232 | my $xdigits = 17; |
1715 | 2233 | if (defined $bignum::VERSION || ref($x) =~ /^Math::Big/) { |
1716 | if (!defined $MATH::BigFloat::VERSION) { | |
2234 | if (!defined $Math::BigFloat::VERSION) { | |
1717 | 2235 | eval { require Math::BigFloat; Math::BigFloat->import(); 1; } |
1718 | 2236 | or do { croak "Cannot load Math::BigFloat "; } |
1719 | 2237 | } |
1804 | 2322 | my $wantbf = 0; |
1805 | 2323 | my $xdigits = 17; |
1806 | 2324 | if (defined $bignum::VERSION || ref($x) =~ /^Math::Big/) { |
1807 | if (!defined $MATH::BigFloat::VERSION) { | |
2325 | if (!defined $Math::BigFloat::VERSION) { | |
1808 | 2326 | eval { require Math::BigFloat; Math::BigFloat->import(); 1; } |
1809 | 2327 | or do { croak "Cannot load Math::BigFloat "; } |
1810 | 2328 | } |
1900 | 2418 | |
1901 | 2419 | =head1 VERSION |
1902 | 2420 | |
1903 | Version 0.14 | |
2421 | Version 0.26 | |
1904 | 2422 | |
1905 | 2423 | |
1906 | 2424 | =head1 SYNOPSIS |
2060 | 2578 | count of primes between the ranges (e.g. C<(13,17)> returns 2, C<14,17> |
2061 | 2579 | and C<13,16> return 1, and C<14,16> returns 0). |
2062 | 2580 | |
2063 | The Lehmer method is used for large values, which speeds up results greatly. | |
2581 | The Lehmer method is used for large values, which greatly speeds up results. | |
2064 | 2582 | |
2065 | 2583 | |
2066 | 2584 | =head2 nth_prime |
2109 | 2627 | prime using the AKS primality test. This code is included for completeness |
2110 | 2628 | and as an example, but is impractically slow. |
2111 | 2629 | |
2630 | =head2 primality_proof_lucas | |
2631 | ||
2632 | Given a positive number C<n> as input, performs a full factorization of C<n-1>, | |
2633 | then attempts a Lucas test on the result. A Pratt-style certificate is | |
2634 | returned. Note that if the input is composite, this will take a B<very> long | |
2635 | time to return. | |
2636 | ||
2637 | =head2 primality_proof_bls75 | |
2638 | ||
2639 | Given a positive number C<n> as input, performs a partial factorization of | |
2640 | C<n-1>, then attempts a proof using theorem 5 of Brillhart, Lehmer, and | |
2641 | Selfridge's 1975 paper. This can take a long time to return if given a | |
2642 | composite, though it should not be anywhere near as long as the Lucas test. | |
2643 | ||
2112 | 2644 | |
2113 | 2645 | =head1 UTILITY FUNCTIONS |
2114 | 2646 | |
2160 | 2692 | |
2161 | 2693 | my @factors = fermat_factor($n); |
2162 | 2694 | |
2163 | Currently unimplementated in Perl. | |
2695 | Produces factors, not necessarily prime, of the positive number input. This | |
2696 | uses Fermat's classic algorithm, without any special improvements (e.g. | |
2697 | Lehman or McKee). This is typically slow and usually L</holf_factor> will | |
2698 | be faster. | |
2164 | 2699 | |
2165 | 2700 | =head2 holf_factor |
2166 | 2701 | |
2178 | 2713 | |
2179 | 2714 | my @factors = squfof_factor($n); |
2180 | 2715 | |
2181 | Currently unimplementated in Perl. | |
2716 | Currently not implemented in Perl. | |
2182 | 2717 | |
2183 | 2718 | =head2 prho_factor |
2184 | 2719 | |
2185 | 2720 | =head2 pbrent_factor |
2186 | ||
2187 | =head2 pminus1_factor | |
2188 | 2721 | |
2189 | 2722 | my @factors = prho_factor($n); |
2190 | 2723 | |
2192 | 2725 | my @factors = prho_factor($n, 1000); |
2193 | 2726 | |
2194 | 2727 | Produces factors, not necessarily prime, of the positive number input. An |
2195 | optional number of rounds can be given as a second parameter. These attempt | |
2196 | to find a single factor using one of the probabilistic algorigthms of | |
2197 | Pollard Rho, Brent's modification of Pollard Rho, or Pollard's C<p - 1>. | |
2198 | These are more specialized algorithms usually used for pre-factoring very | |
2199 | large inputs, or checking very large inputs for naive mistakes. If the | |
2728 | optional number of rounds can be given as a second parameter. An optional | |
2729 | additive factor may be given as a third parameter (default 3). These methods | |
2730 | attempt to find a single factor using Pollard's Rho algorithm (or Brent's | |
2731 | alternative which is typically faster). | |
2732 | These methods can quickly find small factors. If the | |
2200 | 2733 | input is prime or they run out of rounds, they will return the single |
2201 | 2734 | input value. On some inputs they will take a very long time, while on |
2202 | 2735 | others they succeed in a remarkably short time. |
2736 | ||
2737 | =head2 pminus1_factor | |
2738 | ||
2739 | my @factors = pminus1_factor($n); | |
2740 | my @factors = pminus1_factor($n, 1_000); # set B1 smoothness | |
2741 | my @factors = pminus1_factor($n, 1_000, 50_000); # set B1 and B2 | |
2742 | ||
2743 | Produces factors, not necessarily prime, of the positive number input. This | |
2744 | is Pollard's C<p-1> method, using two stages. The default with no B1 or B2 | |
2745 | given is to run with increasing B1 factors. | |
2746 | This method can rapidly find a factor C<p> of C<n> where C<p-1> is smooth | |
2747 | (i.e. C<p-1> has no large factors). | |
2748 | ||
2749 | =head2 ecm_factor | |
2750 | ||
2751 | my @factors = ecm_factor($n); | |
2752 | my @factors = ecm_factor($n, 1000); # B1 = B2 = 1000, curves = 10 | |
2753 | my @factors = ecm_factor($n, 1000, 5000, 10); # Set B1, B2, and ncurves | |
2754 | ||
2755 | Given a positive number input, tries to discover a factor using ECM. The | |
2756 | resulting array will contain either two factors (it succeeded) or the original | |
2757 | number (no factor was found). In either case, multiplying @factors yields the | |
2758 | original input. The B1 and B2 smoothness factors for stage 1 and stage 2 | |
2759 | respectively may be supplied, as can be number of curves to try. | |
2760 | ||
2203 | 2761 | |
2204 | 2762 | |
2205 | 2763 | |
2350 | 2908 | |
2351 | 2909 | =head1 COPYRIGHT |
2352 | 2910 | |
2353 | Copyright 2012 by Dana Jacobsen E<lt>dana@acm.orgE<gt> | |
2911 | Copyright 2012-2013 by Dana Jacobsen E<lt>dana@acm.orgE<gt> | |
2354 | 2912 | |
2355 | 2913 | This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. |
2356 | 2914 |
5 | 5 | |
6 | 6 | BEGIN { |
7 | 7 | $Math::Prime::Util::AUTHORITY = 'cpan:DANAJ'; |
8 | $Math::Prime::Util::VERSION = '0.25'; | |
8 | $Math::Prime::Util::VERSION = '0.26'; | |
9 | 9 | } |
10 | 10 | |
11 | 11 | # parent is cleaner, and in the Perl 5.10.1 / 5.12.0 core, but not earlier. |
14 | 14 | our @EXPORT_OK = |
15 | 15 | qw( prime_get_config prime_set_config |
16 | 16 | prime_precalc prime_memfree |
17 | is_prime is_prob_prime is_provable_prime | |
17 | is_prime is_prob_prime is_provable_prime is_provable_prime_with_cert | |
18 | prime_certificate verify_prime | |
18 | 19 | is_strong_pseudoprime is_strong_lucas_pseudoprime |
19 | 20 | is_aks_prime |
20 | 21 | miller_rabin |
24 | 25 | prime_count_lower prime_count_upper prime_count_approx |
25 | 26 | nth_prime nth_prime_lower nth_prime_upper nth_prime_approx |
26 | 27 | random_prime random_ndigit_prime random_nbit_prime |
27 | random_strong_prime random_maurer_prime | |
28 | random_strong_prime random_maurer_prime random_maurer_prime_with_cert | |
28 | 29 | primorial pn_primorial consecutive_integer_lcm |
29 | 30 | factor all_factors |
30 | 31 | moebius mertens euler_phi jordan_totient exp_mangoldt |
832 | 833 | } |
833 | 834 | |
834 | 835 | sub random_maurer_prime { |
836 | my ($n, $cert) = random_maurer_prime_with_cert(@_); | |
837 | croak "maurer prime $n failed certificate verification!" | |
838 | unless verify_prime(@$cert); | |
839 | return $n; | |
840 | } | |
841 | ||
842 | sub random_maurer_prime_with_cert { | |
835 | 843 | my($k) = @_; |
836 | 844 | _validate_positive_integer($k, 2); |
845 | my @cert; | |
837 | 846 | if ($] < 5.008 && $_Config{'maxbits'} > 32) { |
838 | return random_nbit_prime($k) if $k <= 49; | |
847 | if ($k <= 49) { | |
848 | my $n = random_nbit_prime($k); | |
849 | return ($n, [$n]); | |
850 | } | |
839 | 851 | croak "Random Maurer not supported on old Perl"; |
840 | 852 | } |
841 | 853 | |
844 | 856 | # returning 2. This should be reasonably fast to ~128 bits with MPU::GMP. |
845 | 857 | my $p0 = $_Config{'maxbits'}; |
846 | 858 | |
847 | return random_nbit_prime($k) if $k <= $p0; | |
859 | if ($k <= $p0) { | |
860 | my $n = random_nbit_prime($k); | |
861 | my ($isp, $cert) = is_provable_prime_with_cert($n); | |
862 | croak "small nbit prime could not be proven" if $isp != 2; | |
863 | return ($n, $cert); | |
864 | } | |
848 | 865 | |
849 | 866 | if (!defined $Math::BigInt::VERSION) { |
850 | 867 | eval { require Math::BigInt; Math::BigInt->import(try=>'GMP,Pari'); 1; } |
875 | 892 | } |
876 | 893 | |
877 | 894 | # I've seen +0, +1, and +2 here. Maurer uses +0. Menezes uses +1. |
878 | my $q = random_maurer_prime( ($r * $k)->bfloor + 1 ); | |
895 | my ($q, $certref) = random_maurer_prime_with_cert( ($r * $k)->bfloor + 1 ); | |
879 | 896 | $q = Math::BigInt->new("$q") unless ref($q) eq 'Math::BigInt'; |
880 | 897 | my $I = Math::BigInt->new(2)->bpow($k-2)->bdiv($q)->bfloor->as_int(); |
881 | 898 | print "B = $B r = $r k = $k q = $q I = $I\n" if $verbose && $verbose != 3; |
953 | 970 | # 2) make history by finding the first known BPSW pseudo-prime |
954 | 971 | croak "Maurer prime $n=2*$R*$q+1 failed BPSW" unless is_prob_prime($n); |
955 | 972 | |
956 | return $n; | |
973 | # Build up cert, knowing n-1 = 2*q*R, q > sqrt(n). | |
974 | # We'll need to find the right a value for the factor 2. | |
975 | foreach my $f2a (2 .. 200) { | |
976 | $a = Math::BigInt->new($f2a); | |
977 | next unless $a->copy->bmodpow($n-1, $n) == 1; | |
978 | next unless Math::BigInt::bgcd($a->copy->bmodpow(($n-1)/2, $n)->bsub(1), $n) == 1; | |
979 | @cert = ("$n", "n-1", [2, [@$certref]], [$f2a, $try_a]); | |
980 | return ($n, \@cert); | |
981 | } | |
957 | 982 | } |
958 | 983 | # Didn't pass the selected a values. Try another R. |
959 | 984 | } |
1598 | 1623 | return ($n <= 18446744073709551615) ? 2 : 1; |
1599 | 1624 | } |
1600 | 1625 | |
1626 | # Return just the non-cert portion. | |
1601 | 1627 | sub is_provable_prime { |
1602 | 1628 | my($n) = @_; |
1603 | 1629 | return 0 if defined $n && $n < 2; |
1604 | 1630 | _validate_positive_integer($n); |
1605 | 1631 | |
1606 | # Shortcut some of the calls. | |
1607 | 1632 | return _XS_is_prime($n) if ref($n) ne 'Math::BigInt' && $n <= $_XS_MAXVAL; |
1608 | return Math::Prime::Util::GMP::is_provable_prime($n) if $_HAVE_GMP | |
1609 | && defined &Math::Prime::Util::GMP::is_provable_prime; | |
1610 | ||
1611 | my $is_prob_prime = is_prob_prime($n); | |
1612 | return $is_prob_prime unless $is_prob_prime == 1; | |
1613 | ||
1614 | # At this point we know it is almost certainly a prime, but we need to | |
1615 | # prove it. We should do ECPP or APR-CL now, or failing that, do the | |
1616 | # Brillhart-Lehmer-Selfridge test, or Pocklington-Lehmer. Until those | |
1617 | # are written here, we'll do a Lucas test, which is super simple but may | |
1618 | # be very slow. We have AKS code, but it's insanely slow. | |
1633 | return Math::Prime::Util::GMP::is_provable_prime($n) | |
1634 | if $_HAVE_GMP && defined &Math::Prime::Util::GMP::is_provable_prime; | |
1635 | ||
1636 | my ($is_prime, $cert) = is_provable_prime_with_cert($n); | |
1637 | return $is_prime; | |
1638 | } | |
1639 | ||
1640 | # Return just the cert portion. | |
1641 | sub prime_certificate { | |
1642 | my($n) = @_; | |
1643 | my ($is_prime, $cert) = is_provable_prime_with_cert($n); | |
1644 | return @$cert; | |
1645 | } | |
1646 | ||
1647 | ||
1648 | sub is_provable_prime_with_cert { | |
1649 | my($n) = @_; | |
1650 | return 0 if defined $n && $n < 2; | |
1651 | _validate_positive_integer($n); | |
1652 | ||
1653 | # Set to 0 if you want the proof to go down to 11. | |
1654 | if (1) { | |
1655 | if (ref($n) ne 'Math::BigInt' && $n <= $_XS_MAXVAL) { | |
1656 | my $isp = _XS_is_prime($n); | |
1657 | return ($isp == 2) ? ($isp, [$n]) : ($isp, []); | |
1658 | } | |
1659 | if ($_HAVE_GMP && defined &Math::Prime::Util::GMP::is_provable_prime_with_cert) { | |
1660 | return Math::Prime::Util::GMP::is_provable_prime_with_cert($n); | |
1661 | } | |
1662 | ||
1663 | my $isp = is_prob_prime($n); | |
1664 | if ($isp != 1) { | |
1665 | return ($isp == 2) ? ($isp, [$n]) : ($isp, []); | |
1666 | } | |
1667 | } else { | |
1668 | if ($n <= 10) { | |
1669 | if ($n==2||$n==3||$n==5||$n==7) { | |
1670 | return (2, [$n]); | |
1671 | } | |
1672 | return 0; | |
1673 | } | |
1674 | } | |
1675 | ||
1676 | # Choice of methods for proof: | |
1677 | # ECPP needs a fair bit of programming work | |
1678 | # APRCL needs a lot of programming work | |
1679 | # BLS75 combo Corollary 11 of BLS75. Trial factor n-1 and n+1 to B, find | |
1680 | # factors F1 of n-1 and F2 of n+1. Quit when: | |
1681 | # B > (N/(F1*F1*(F2/2)))^1/3 or B > (N/((F1/2)*F2*F2))^1/3 | |
1682 | # BLS75 n+1 Requires factoring n+1 to (n/2)^1/3 (theorem 19) | |
1683 | # BLS75 n-1 Requires factoring n-1 to (n/2)^1/3 (theorem 5 or 7) | |
1684 | # Pocklington Requires factoring n-1 to n^1/2 (BLS75 theorem 4) | |
1685 | # Lucas Easy, requires factoring of n-1 (BLS75 theorem 1) | |
1686 | # AKS horribly slow | |
1619 | 1687 | # See http://primes.utm.edu/prove/merged.html or other sources. |
1620 | 1688 | |
1621 | # It shouldn't be possible to get here without BigInt already loaded. | |
1689 | #my ($isp, $pref) = Math::Prime::Util::PP::primality_proof_lucas($n); | |
1690 | my ($isp, $pref) = Math::Prime::Util::PP::primality_proof_bls75($n); | |
1691 | carp "proved $n is not prime\n" if !$isp; | |
1692 | return ($isp, $pref); | |
1693 | } | |
1694 | ||
1695 | ||
1696 | sub verify_prime { | |
1697 | my @pdata = @_; | |
1698 | my $verbose = $_Config{'verbose'}; | |
1699 | ||
1700 | # Empty input = no certificate = not prime | |
1701 | return 0 if scalar @pdata == 0; | |
1702 | ||
1703 | # Handle case of being handed a reference to the certificate. | |
1704 | @pdata = @{$pdata[0]} if scalar @pdata == 1 && ref($pdata[0]) eq 'ARRAY'; | |
1705 | ||
1706 | my $n = shift @pdata; | |
1707 | if (length($n) == 1) { | |
1708 | return 1 if $n =~ /^[2357]$/; | |
1709 | print "primality fail: $n tiny and not prime\n" if $verbose; | |
1710 | return 0; | |
1711 | } | |
1712 | ||
1622 | 1713 | if (!defined $Math::BigInt::VERSION) { |
1623 | 1714 | eval { require Math::BigInt; Math::BigInt->import(try=>'GMP,Pari'); 1; } |
1624 | 1715 | or do { croak "Cannot load Math::BigInt"; }; |
1625 | 1716 | } |
1626 | my $nm1 = $n-1; | |
1627 | my @factors = factor($nm1); | |
1628 | # Remember that we have to prove the primality of every factor. | |
1629 | if ( (scalar grep { is_provable_prime($_) != 2 } @factors) > 0) { | |
1630 | carp "could not prove primality of $n.\n"; | |
1717 | $n = Math::BigInt->new("$n") if ref($n) ne 'Math::BigInt'; | |
1718 | if ($n->is_even) { | |
1719 | print "primality fail: $n even\n" if $verbose; | |
1720 | return 0; | |
1721 | } | |
1722 | ||
1723 | my $method = (scalar @pdata > 0) ? shift @pdata : 'BPSW'; | |
1724 | ||
1725 | if ($method eq 'BPSW') { | |
1726 | if ($n > Math::BigInt->new("18446744073709551615")) { | |
1727 | print "primality fail: $n too large for BPSW proof\n" if $verbose; | |
1728 | return 0; | |
1729 | } | |
1730 | my $bpsw = 0; | |
1731 | if ($_HAVE_GMP) { | |
1732 | $bpsw = Math::Prime::Util::GMP::is_prob_prime($n); | |
1733 | } else { | |
1734 | $bpsw = Math::Prime::Util::PP::miller_rabin($n, 2) | |
1735 | && Math::Prime::Util::PP::is_strong_lucas_pseudoprime($n); | |
1736 | } | |
1737 | if (!$bpsw) { | |
1738 | print "primality fail: BPSW indicated $n is composite\n" if $verbose; | |
1739 | return 0; | |
1740 | } | |
1741 | print "primality success: $n by BPSW\n" if $verbose > 1; | |
1631 | 1742 | return 1; |
1632 | 1743 | } |
1633 | 1744 | |
1634 | for (my $a = 2; $a < $nm1; $a++) { | |
1635 | my $ap = Math::BigInt->new("$a"); | |
1636 | # 1. a^(n-1) = 1 mod n. | |
1637 | next if $ap->copy->bmodpow($nm1, $n) != 1; | |
1638 | # 2. a^((n-1)/f) != 1 mod n for all f. | |
1639 | next if (scalar grep { $_ == 1 } | |
1640 | map { $ap->copy->bmodpow(int($nm1/$_),$n); } | |
1641 | @factors) > 0; | |
1642 | return 2; | |
1643 | } | |
1644 | carp "proved $n is not prime\n"; | |
1745 | if ($method eq 'Pratt' || $method eq 'Lucas') { | |
1746 | # Based on Lucas primality test, which requires full n-1 factorization. | |
1747 | if (scalar @pdata != 2 || (ref($pdata[0]) ne 'ARRAY') || (ref($pdata[1]) eq 'ARRAY')) { | |
1748 | warn "verify_prime: incorrect Pratt format, must have factors and a value\n"; | |
1749 | return 0; | |
1750 | } | |
1751 | my @factors = @{shift @pdata}; | |
1752 | my $a = Math::BigInt->new(shift @pdata); | |
1753 | my $nm1 = $n - 1; | |
1754 | my $B = $nm1; # Unfactored part | |
1755 | ||
1756 | my @prime_factors; | |
1757 | my %factors_seen; | |
1758 | foreach my $farray (@factors) { | |
1759 | my $f; | |
1760 | if (ref($farray) eq 'ARRAY') { | |
1761 | $f = Math::BigInt->new("$farray->[0]"); | |
1762 | return 0 unless verify_prime(@$farray); | |
1763 | } else { | |
1764 | $f = $farray; | |
1765 | return 0 unless verify_prime($f); | |
1766 | } | |
1767 | next if defined $factors_seen{"$f"}; # repeated factors | |
1768 | if (($B % $f) != 0) { | |
1769 | print "primality fail: given factor $f does not divide $nm1\n" if $verbose; | |
1770 | return 0; | |
1771 | } | |
1772 | while (($B % $f) == 0) { | |
1773 | $B /= $f; | |
1774 | } | |
1775 | push @prime_factors, $f; | |
1776 | $factors_seen{"$f"} = 1; | |
1777 | } | |
1778 | croak "Pratt error: n-1 not completely factored" unless $B == 1; | |
1779 | ||
1780 | # 1. a must be co-prime to n. | |
1781 | if (Math::BigInt::bgcd($a, $n) != 1) { | |
1782 | print "primality fail: a and n not coprime\n" if $verbose; | |
1783 | return 0; | |
1784 | } | |
1785 | # 2. n is a psp base a | |
1786 | if ($a->copy->bmodpow($nm1, $n) != 1) { | |
1787 | print "primality fail: n is not a psp base a\n" if $verbose; | |
1788 | return 0; | |
1789 | } | |
1790 | # 3. For each factor f of n-1, a^((n-1)/f) != 1 mod n | |
1791 | foreach my $f (@prime_factors) { | |
1792 | if ($a->copy->bmodpow(int($nm1/$f),$n) == 1) { | |
1793 | print "primality fail: factor f fails a^((n-1)/f) != 1 mod n\n" if $verbose; | |
1794 | return 0; | |
1795 | } | |
1796 | } | |
1797 | print "primality success: $n by Lucas test\n" if $verbose > 1; | |
1798 | return 1; | |
1799 | } | |
1800 | ||
1801 | if ($method eq 'n-1') { | |
1802 | # BLS75 or generalized Pocklington | |
1803 | # http://www.ams.org/journals/mcom/1975-29-130/S0025-5718-1975-0384673-1/S0025-5718-1975-0384673-1.pdf | |
1804 | if (scalar @pdata != 2 || (ref($pdata[0]) ne 'ARRAY') || (ref($pdata[1]) ne 'ARRAY')) { | |
1805 | warn "verify_prime: incorrect n-1 format, must have factors and a values\n"; | |
1806 | return 0; | |
1807 | } | |
1808 | my @factors = @{shift @pdata}; | |
1809 | my @as = @{shift @pdata}; | |
1810 | if ($#factors != $#as) { | |
1811 | warn "verify_prime: incorrect n-1 format, must have a value for each factor\n"; | |
1812 | return 0; | |
1813 | } | |
1814 | ||
1815 | my $nm1 = $n - 1; | |
1816 | my $A = $n-$n+1; # Factored part (F_1 in BLS paper) | |
1817 | my $B = $nm1; # Unfactored part (R_1 in BLS paper) | |
1818 | ||
1819 | my @prime_factors; | |
1820 | my @pfas; | |
1821 | my %factors_seen; | |
1822 | foreach my $farray (@factors) { | |
1823 | my $f; | |
1824 | my $a = shift @as; | |
1825 | if (ref($farray) eq 'ARRAY') { | |
1826 | $f = Math::BigInt->new("$farray->[0]"); | |
1827 | return 0 unless verify_prime(@$farray); | |
1828 | } else { | |
1829 | $f = Math::BigInt->new("$farray"); | |
1830 | return 0 unless verify_prime($f); | |
1831 | } | |
1832 | next if defined $factors_seen{"$f"}; # repeated factors | |
1833 | if (($B % $f) != 0) { | |
1834 | print "primality fail: given factor $f does not divide $nm1\n" if $verbose; | |
1835 | return 0; | |
1836 | } | |
1837 | while (($B % $f) == 0) { | |
1838 | $B /= $f; | |
1839 | $A *= $f; | |
1840 | } | |
1841 | push @prime_factors, $f; | |
1842 | push @pfas, $a; | |
1843 | $factors_seen{"$f"} = 1; | |
1844 | } | |
1845 | croak "BLS75 error: $A * $B != $nm1" unless $A*$B == $nm1; | |
1846 | ||
1847 | # The theorems state that A is the even portion, so we are requiring 2 be | |
1848 | # listed as a factor. | |
1849 | if ($A->is_odd) { | |
1850 | print "primality fail: 2 must be included as a factor" if $verbose; | |
1851 | return 0; | |
1852 | } | |
1853 | ||
1854 | # TODO: consider: if B=1 and a single a is given, then Lucas test. | |
1855 | ||
1856 | if (Math::BigInt::bgcd($A, $B) != 1) { | |
1857 | print "primality fail: A and B not coprime\n" if $verbose; | |
1858 | return 0; | |
1859 | } | |
1860 | # Theorem 5, m = 1, page 624 | |
1861 | { | |
1862 | my ($s,$r) = $B->copy->bdiv($A->copy->bmul(2)); | |
1863 | my $fpart = ($A+1) * (2*$A*$A + ($r-1) * $A + 1); | |
1864 | if ($n >= $fpart) { | |
1865 | print "primality fail: not enough factors\n" if $verbose; | |
1866 | return 0; | |
1867 | } | |
1868 | my $rtest = $r*$r - 8*$s; | |
1869 | my $rtestroot = $rtest->copy->bsqrt; | |
1870 | if ($s != 0 && ($rtestroot*$rtestroot) == $rtest) { | |
1871 | print "primality fail: BLS75 theorem 5: s=$s, r=$r indicates composite\n" if $verbose; | |
1872 | return 0; | |
1873 | } | |
1874 | } | |
1875 | # Now verify (I), page 623 | |
1876 | foreach my $i (0 .. $#prime_factors) { | |
1877 | my $f = $prime_factors[$i]; | |
1878 | my $a = Math::BigInt->new("$pfas[$i]"); | |
1879 | if ($a->copy->bmodpow($nm1, $n) != 1 || | |
1880 | Math::BigInt::bgcd($a->copy->bmodpow($nm1/$f, $n)->bsub(1), $n) != 1) { | |
1881 | print "primality fail: BLS75 factor=$f, a=$a failed.\n" if $verbose; | |
1882 | return 0; | |
1883 | } | |
1884 | } | |
1885 | print "primality success: $n by BLS75 theorem 5\n" if $verbose > 1; | |
1886 | return 1; | |
1887 | } | |
1888 | ||
1889 | if ($method eq 'ECPP' || $method eq 'AGKM') { | |
1890 | # EC cert: Atkin-Morain etc. | |
1891 | # Normally we'd have the q values set up recursively, but to follow the | |
1892 | # standard trend, we have this set up as a list: | |
1893 | # n, "AGKM", [n,a,b,m,q,P], [n1,a,b,m,q,P], ... | |
1894 | # | |
1895 | # Examples: | |
1896 | # (100000000000000000039, "AGKM", [100000000000000000039, 31484432173069852672, 39553474583282556928, 100000000014867206541, 539348143913549, [39164891430400385024,86449249723524901718]]) | |
1897 | # (677826928624294778921, "AGKM", [677826928624294778921, 404277700094248015180, 599134911995823048257, 677826928656744857936, 104088901820753203, [2293544533, 356794037129589115041]]) | |
1898 | # Ux,Uy should be 600992528322000913770, 206075883056439332684 | |
1899 | # Vx,Vy should be 0, 1 | |
1900 | if (scalar @pdata < 1) { | |
1901 | warn "verify_prime: incorrect AGKM format\n"; | |
1902 | return 0; | |
1903 | } | |
1904 | my ($ni, $a, $b, $m, $P); | |
1905 | my ($qval, $q) = ($n, $n); | |
1906 | foreach my $block (@pdata) { | |
1907 | if (ref($block) ne 'ARRAY' || scalar @$block != 6) { | |
1908 | warn "verify_prime: incorrect AGKM block format\n"; | |
1909 | return 0; | |
1910 | } | |
1911 | if ($block->[0] != $q) { | |
1912 | warn "verify_prime: incorrect AGKM block format: block n != q\n"; | |
1913 | return 0; | |
1914 | } | |
1915 | ($ni, $a, $b, $m, $qval, $P) = @$block; | |
1916 | $q = ref($qval) eq 'ARRAY' ? $qval->[0] : $qval; | |
1917 | if (ref($P) ne 'ARRAY' || scalar @$P != 2) { | |
1918 | warn "verify_prime: incorrect AGKM block point format\n"; | |
1919 | return 0; | |
1920 | } | |
1921 | my($Px, $Py) = @$P; | |
1922 | $ni = $n->copy->bzero->badd("$ni") unless ref($ni) eq 'Math::BigInt'; | |
1923 | $a = $n->copy->bzero->badd("$a") unless ref($a) eq 'Math::BigInt'; | |
1924 | $b = $n->copy->bzero->badd("$b") unless ref($b) eq 'Math::BigInt'; | |
1925 | $m = $n->copy->bzero->badd("$m") unless ref($m) eq 'Math::BigInt'; | |
1926 | $q = $n->copy->bzero->badd("$q") unless ref($q) eq 'Math::BigInt'; | |
1927 | $Px = $n->copy->bzero->badd("$Px") unless ref($Px) eq 'Math::BigInt'; | |
1928 | $Py = $n->copy->bzero->badd("$Py") unless ref($Py) eq 'Math::BigInt'; | |
1929 | if (Math::BigInt::bgcd($ni, 6) != 1) { | |
1930 | warn "verify_prime: AGKM block n '$ni' is divisible by 2 or 3\n"; | |
1931 | return 0; | |
1932 | } | |
1933 | my $c = $a*$a*$a * 4 + $b*$b * 27; | |
1934 | if (Math::BigInt::bgcd($c, $ni) != 1) { | |
1935 | warn "verify_prime: AGKM block gcd 4a^3+27b^2,n incorrect\n"; | |
1936 | return 0; | |
1937 | } | |
1938 | if ($q <= $ni->copy->broot(4)->badd(1)->bpow(2)) { | |
1939 | warn "verify_prime: AGKM block q is too small\n"; | |
1940 | return 0; | |
1941 | } | |
1942 | # Final check, check that we've got a bound above and below (Hasse) | |
1943 | if (!defined $Math::Prime::Util::ECAffinePoint::VERSION) { | |
1944 | eval { require Math::Prime::Util::ECAffinePoint; 1; } | |
1945 | or do { croak "Cannot load Math::Prime::Util::ECAffinePoint"; }; | |
1946 | } | |
1947 | my $ECP = Math::Prime::Util::ECAffinePoint->new($a, $b, $ni, $Px, $Py); | |
1948 | # Compute U = (m/q)P, check U != point at infinity | |
1949 | $ECP->mul( $m->copy->bdiv($q)->as_int ); | |
1950 | if ($ECP->is_infinity) { | |
1951 | warn "verify_prime: AGKM point does not multiply correctly.\n"; | |
1952 | return 0; | |
1953 | } | |
1954 | # Compute V = qU, check V = point at infinity | |
1955 | $ECP->mul( $q ); | |
1956 | if (! $ECP->is_infinity) { | |
1957 | warn "verify_prime: AGKM point does not multiply correctly.\n"; | |
1958 | return 0; | |
1959 | } | |
1960 | } | |
1961 | # Check primality of last q | |
1962 | return 0 unless verify_prime($qval); | |
1963 | ||
1964 | print "primality success: $n by A-K-G-M elliptic curve\n" if $verbose > 1; | |
1965 | return 1; | |
1966 | } | |
1967 | ||
1968 | warn "verify_prime: Unknown method: '$method'.\n"; | |
1645 | 1969 | return 0; |
1646 | 1970 | } |
1647 | 1971 | |
1991 | 2315 | |
1992 | 2316 | =head1 VERSION |
1993 | 2317 | |
1994 | Version 0.25 | |
2318 | Version 0.26 | |
1995 | 2319 | |
1996 | 2320 | |
1997 | 2321 | =head1 SYNOPSIS |
2135 | 2459 | |
2136 | 2460 | =over 4 |
2137 | 2461 | |
2138 | =item primes.pl displays primes between start and end values, with many | |
2139 | options for filtering (e.g. twin, safe, circular, good, lucky, etc.). | |
2140 | ||
2141 | =item factor.pl operates similar to the GNU C<factor> program. It supports | |
2462 | =item * | |
2463 | ||
2464 | primes.pl displays primes between start and end values or expressions, | |
2465 | with many options for filtering (e.g. twin, safe, circular, good, lucky, | |
2466 | etc.). Use C<--help> to see all the options. | |
2467 | ||
2468 | =item * | |
2469 | ||
2470 | factor.pl operates similar to the GNU C<factor> program. It supports | |
2142 | 2471 | bigint and expression inputs. |
2143 | 2472 | |
2144 | 2473 | =back |
2228 | 2557 | test. If L<Math::Prime::Util::GMP> is installed, some quick primality proofs |
2229 | 2558 | are run on larger numbers, so will return 2 for many of those also. |
2230 | 2559 | |
2231 | Also see the L</"is_prob_prime"> function, which will never do additional | |
2232 | tests, and the L</"is_provable_prime"> function which will try very hard to | |
2560 | Also see the L</is_prob_prime> function, which will never do additional | |
2561 | tests, and the L</is_provable_prime> function which will try very hard to | |
2233 | 2562 | return only 0 or 2 for any input. |
2234 | 2563 | |
2235 | 2564 | For native precision numbers (anything smaller than C<2^64>, all three |
2236 | 2565 | functions are identical and use a deterministic set of Miller-Rabin tests. |
2237 | While L</"is_prob_prime"> and L</"is_prime"> return probable prime results | |
2566 | While L</is_prob_prime> and L</is_prime> return probable prime results | |
2238 | 2567 | for larger numbers, they use the strong Baillie-PSW test, which has had |
2239 | 2568 | no counterexample found since it was published in 1980 (though certainly they |
2240 | 2569 | exist). |
2307 | 2636 | In contrast, even primesieve using 12 cores would take over a week on this |
2308 | 2637 | same computer to determine C<Pi(10^16)>. |
2309 | 2638 | |
2310 | Also see the function L</"prime_count_approx"> which gives a very good | |
2311 | approximation to the prime count, and L</"prime_count_lower"> and | |
2312 | L</"prime_count_upper"> which give tight bounds to the actual prime count. | |
2639 | Also see the function L</prime_count_approx> which gives a very good | |
2640 | approximation to the prime count, and L</prime_count_lower> and | |
2641 | L</prime_count_upper> which give tight bounds to the actual prime count. | |
2313 | 2642 | These functions return quickly for any input, including bigints. |
2314 | 2643 | |
2315 | 2644 | |
2482 | 2811 | |
2483 | 2812 | Takes a positive number as input and returns back either 0 (composite), |
2484 | 2813 | 2 (definitely prime), or 1 (probably prime). This gives it the same return |
2485 | values as C<is_prime> and C<is_prob_prime>. | |
2486 | ||
2487 | The current implementation uses a Lucas test requiring a complete factorization | |
2488 | of C<n-1>, which may not be possible in a reasonable amount of time. The GMP | |
2489 | version uses the BLS (Brillhart-Lehmer-Selfridge) method, requiring C<n-1> to | |
2490 | be factored to the cube root of C<n>, which is more likely to succeed and will | |
2491 | usually take less time, but can still fail. Hence you should always test that | |
2492 | the result is C<2> to ensure the prime is proven. | |
2814 | values as L</is_prime> and L</is_prob_prime>. | |
2815 | ||
2816 | The current implementation of both the Perl and GMP proofs is using theorem 5 | |
2817 | of BLS75 (Brillhart-Lehmer-Selfridge), requiring C<n-1> to be factored to | |
2818 | C<(n/2)^(1/3))>. This takes less time than factoring to C<n^0.5> as required | |
2819 | by the generalized Pocklington test or C<n-1> for the Lucas test. However it | |
2820 | is possible a factor cannot be found in a reasonable amount of time, so you | |
2821 | should always test that the result in C<2> to ensure it was proven. | |
2822 | ||
2823 | A later implementation will use an ECPP test for larger inputs. | |
2824 | ||
2825 | ||
2826 | =head2 prime_certificate | |
2827 | ||
2828 | my @cert = prime_certificate($n); | |
2829 | say verify_prime(@cert) ? "proven prime" : "not prime"; | |
2830 | ||
2831 | Given a positive integer C<n> as input, returns either an empty array (we could | |
2832 | not prove C<n> prime) or an array representing a certificate of primality. | |
2833 | This may be examined or given to L</verify_prime> for verification. The latter | |
2834 | function contains the description of the format. | |
2835 | ||
2836 | ||
2837 | =head2 is_provable_prime_with_cert | |
2838 | ||
2839 | Given a positive integer as input, returns a two element array containing the | |
2840 | result of L</is_provable_prime> and an array reference containing the primality | |
2841 | certificate like L</prime_certificate>. The certificate will be an empty | |
2842 | array reference if the result is not 2 (definitely prime). | |
2843 | ||
2844 | ||
2845 | =head2 verify_prime | |
2846 | ||
2847 | my @cert = prime_certificate($n); | |
2848 | say verify_prime(@cert) ? "proven prime" : "not prime"; | |
2849 | ||
2850 | Given an array representing a certificate of primality, returns either 0 (not | |
2851 | verified), or 1 (verified). The computations are all done using pure Perl | |
2852 | Math::BigInt and should not be time consuming (the Pari or GMP backends will | |
2853 | help with large inputs). | |
2854 | ||
2855 | A certificate is an array holding an C<n-cert>. An C<n-cert> is one of: | |
2856 | ||
2857 | n | |
2858 | implies n,"BPSW" | |
2859 | ||
2860 | n,"BPSW" | |
2861 | the number n is small enough to be proven with BPSW. This | |
2862 | currently means smaller than 2^64. | |
2863 | ||
2864 | n,"Pratt",[n-cert, ...],a | |
2865 | A Pratt certificate. We are given n, the method "Pratt" or | |
2866 | "Lucas", a list of n-certs that indicate all the unique factors | |
2867 | of n-1, and an 'a' value to be used in the Lucas primality test. | |
2868 | The certificate passes if: | |
2869 | 1 all factor n-certs can be verified | |
2870 | 2 all n-certs are factors of n-1 and none are missing | |
2871 | 3 a is coprime to n | |
2872 | 4 a^(n-1) = 1 mod n | |
2873 | 5 a^((n-1)/f) != 1 mod n for each factor | |
2874 | ||
2875 | n,"n-1",[n-cert, ...],[a,...] | |
2876 | An n-1 certificate suitable for the generalized Pocklington or the | |
2877 | BLS75 (Brillhart-Lehmer-Selfridge 1975, theorem 5) test. The | |
2878 | proof is performed using BLS75 theorem 5 which requires n-1 to be | |
2879 | factored up to (n/2)^1/3. If n-1 is factored to more than | |
2880 | sqrt(n), then the conditions are identical to the generalized | |
2881 | Pocklington test. | |
2882 | The certificate passes if: | |
2883 | 1 all factor n-certs can be verified | |
2884 | 2 all factor n-certs are factors of n-1 | |
2885 | 3 there must be a corresponding 'a' for each factor n-cert | |
2886 | 4 given A (the factored part of n-1), B = (n-1)/A (the | |
2887 | unfactored part), s = int(B/(2A)), r = B-s*2A: | |
2888 | - n < (A+1)(2*A*A+(r-a)A+a) [ n-1 factored to (n/2)^1/3 ] | |
2889 | - s = 0 or r*r-8s not a perfect square | |
2890 | - A and B are coprime | |
2891 | 5 for each pair (f,a) representing a factor n-cert and its 'a': | |
2892 | - a^(n-1) = 1 mod n | |
2893 | - gcd( a^((n-1)/f)-1, n ) = 1 | |
2894 | ||
2895 | n,"AGKM",[ec-block],[ec-block],... | |
2896 | An Elliptic Curve certificate. We are given n, the method "AGKM" | |
2897 | or "ECPP", and one or more 6-element blocks representing a | |
2898 | standard ECPP or Atkin-Goldwasser-Kilian-Morain certificate. | |
2899 | In its traditional form, it is non-recursive, with each q value | |
2900 | being proved by successive blocks (this makes it easy to use for | |
2901 | programs like Sage and GMP-ECPP). A q value is also allowed to | |
2902 | be an n-cert, which allows an alternative proof for the last q. | |
2903 | Every ec-block has 6 elements: | |
2904 | N the N value this block proves prime if q is prime | |
2905 | a value describing the elliptic curve to be used | |
2906 | b value describing the elliptic curve to be used | |
2907 | m order of the curve | |
2908 | q a probable prime > (N^1/4+1)^2 (may be an n-cert) | |
2909 | P a point [x,y] on the curve (affine coordinates) | |
2910 | The certificate passes if: | |
2911 | - the final q can be proved with BPSW. | |
2912 | - for each block: | |
2913 | - N is the same as the preceeding block's q | |
2914 | - N is not divisible by 2 or 3 | |
2915 | - gcd( 4a^3 + 27b^2, N ) == 1; | |
2916 | - q > (N^1/4+1)^2 | |
2917 | - U = (m/q)P is not the point at infinity | |
2918 | - V = qU is the point at infinity | |
2493 | 2919 | |
2494 | 2920 | |
2495 | 2921 | =head2 is_aks_prime |
2531 | 2957 | say "Mertens(10M) = ", mertens(10_000_000); # = 1037 |
2532 | 2958 | |
2533 | 2959 | Returns M(n), the Mertens function for a non-negative integer input. This |
2534 | function is defined as C<sum(moebius(1..n))>. This is a much more efficient | |
2535 | solution for larger inputs. For example, computing Mertens(100M) takes: | |
2960 | function is defined as C<sum(moebius(1..n))>, but calculated more efficiently | |
2961 | for large inputs. For example, computing Mertens(100M) takes: | |
2536 | 2962 | |
2537 | 2963 | time approx mem |
2538 | 2964 | 0.4s 0.1MB mertens(100_000_000) |
2547 | 2973 | which involves calculating all moebius values to C<n^1/2>, which in turn will |
2548 | 2974 | require prime sieving to C<n^1/4>. |
2549 | 2975 | |
2550 | Various methods exist for this, using differing quantities of μ(n). The | |
2976 | Various algorithms exist for this, using differing quantities of μ(n). The | |
2551 | 2977 | simplest way is to efficiently sum all C<n> values. Benito and Varona (2008) |
2552 | 2978 | show a clever and simple method that only requires C<n/3> values. Deléglise |
2553 | 2979 | and Rivat (1996) describe a segmented method using only C<n^1/3> values. The |
2554 | current implementation does a simple non-segmented C<n^1/2> version of this. | |
2555 | Kuznetsov (2011) gives an alternate method that he indicates is even faster. | |
2556 | Lastly, one of the advanced prime count algorithms could be theoretically used | |
2557 | to create a faster solution. | |
2980 | current implementation does a simple non-segmented C<n^1/2> version of their | |
2981 | method. Kuznetsov (2011) gives an alternate method that he indicates is even | |
2982 | faster. Lastly, one of the advanced prime count algorithms could be | |
2983 | theoretically used to create a faster solution. | |
2558 | 2984 | |
2559 | 2985 | |
2560 | 2986 | =head2 euler_phi |
2590 | 3016 | |
2591 | 3017 | say "exp(lambda($_)) = ", exp_mangoldt($_) for 1 .. 100; |
2592 | 3018 | |
2593 | Returns Λ(n), the Mangoldt function (also known as von Mangoldt's function) for | |
2594 | an integer value. It is equal to log p if n is prime or a power of a prime, | |
3019 | Returns exp(Λ(n)), the exponential of the Mangoldt function (also known | |
3020 | as von Mangoldt's function) for an integer value. | |
3021 | It is equal to log p if n is prime or a power of a prime, | |
2595 | 3022 | and 0 otherwise. We return the exponential so all results are integers. |
2596 | Hence the return value for C<exp_mangoldt> is: | |
2597 | C<p> if C<n = p^m> for some prime C<p> and integer C<m E<gt>= 1> | |
3023 | Hence the return value for C<exp_mangoldt> is: | |
3024 | ||
3025 | p if n = p^m for some prime p and integer m >= 1 | |
2598 | 3026 | 1 otherwise. |
2599 | 3027 | |
2600 | 3028 | |
2604 | 3032 | |
2605 | 3033 | Returns θ(n), the first Chebyshev function for a non-negative integer input. |
2606 | 3034 | This is the sum of the logarithm of each prime where C<p E<lt>= n>. An |
2607 | alternate computation is as the logarithm of n primorial, hence: | |
2608 | ||
2609 | use List::Util qw/sum/; | |
3035 | alternate computation is as the logarithm of n primorial. | |
3036 | Hence these functions: | |
3037 | ||
3038 | use List::Util qw/sum/; use Math::BigFloat; | |
3039 | ||
2610 | 3040 | sub c1a { 0+sum( map { log($_) } @{primes(shift)} ) } |
2611 | use Math::BigFloat; | |
2612 | 3041 | sub c1b { Math::BigFloat->new(primorial(shift))->blog } |
2613 | 3042 | |
2614 | 3043 | yield similar results, albeit slower and using more memory. |
2624 | 3053 | Another alternate computation is as the logarithm of lcm(1,2,...,n). |
2625 | 3054 | Hence these functions: |
2626 | 3055 | |
2627 | use List::Util qw/sum/; | |
3056 | use List::Util qw/sum/; use Math::BigFloat; | |
3057 | ||
2628 | 3058 | sub c2a { 0+sum( map { log(exp_mangoldt($_)) } 1 .. shift ) } |
2629 | use Math::BigFloat; | |
2630 | 3059 | sub c2b { Math::BigFloat->new(consecutive_integer_lcm(shift))->blog } |
2631 | 3060 | |
2632 | 3061 | yield similar results, albeit slower and using more memory. |
2658 | 3087 | |
2659 | 3088 | divisor_sum( $n, sub { my $d=shift; $d**5 * moebius($n/$d); } ); |
2660 | 3089 | |
2661 | though in the last case we have a function L</"jordan_totient"> to compute | |
3090 | though in the last case we have a function L</jordan_totient> to compute | |
2662 | 3091 | it more efficiently. |
2663 | 3092 | |
2664 | 3093 | This function is useful for calculating things like aliquot sums, abundant |
2742 | 3171 | uniformity but results in many fewer bits of randomness being consumed as |
2743 | 3172 | well as being much faster. |
2744 | 3173 | |
2745 | If an C<irand> function has been set via L</"prime_set_config">, it will be | |
3174 | If an C<irand> function has been set via L</prime_set_config>, it will be | |
2746 | 3175 | used to construct any ranged random numbers needed. The function should |
2747 | 3176 | return a uniformly random 32-bit integer, which is how the irand functions |
2748 | 3177 | exported by L<Math::Random::Secure>, L<Math::Random::MT>, |
2843 | 3272 | advances in factoring and attacks, for practical purposes, using large random |
2844 | 3273 | primes offer security equivalent to using strong primes. |
2845 | 3274 | |
2846 | Similar to L</"random_nbit_prime">, the result will be a BigInt if the | |
3275 | Similar to L</random_nbit_prime>, the result will be a BigInt if the | |
2847 | 3276 | number of bits is greater than the native bit size. For better performance |
2848 | 3277 | with large bit sizes, install L<Math::Prime::Util::GMP>. |
2849 | 3278 | |
3279 | ||
2850 | 3280 | =head2 random_maurer_prime |
2851 | 3281 | |
2852 | 3282 | my $bigprime = random_maurer_prime(512); |
2853 | 3283 | |
2854 | 3284 | Construct an n-bit provable prime, using the FastPrime algorithm of |
2855 | 3285 | Ueli Maurer (1995). This is the same algorithm used by L<Crypt::Primes>. |
2856 | Similar to L</"random_nbit_prime">, the result will be a BigInt if the | |
3286 | Similar to L</random_nbit_prime>, the result will be a BigInt if the | |
2857 | 3287 | number of bits is greater than the native bit size. For better performance |
2858 | 3288 | with large bit sizes, install L<Math::Prime::Util::GMP>. |
2859 | 3289 | |
2860 | 3290 | The differences between this function and that in L<Crypt::Primes> are |
2861 | 3291 | described in the L</"SEE ALSO"> section. |
3292 | ||
3293 | Internally this additionally runs the BPSW probable prime test on every | |
3294 | partial result, and constructs a primality certificate for the final | |
3295 | result, which is verified. These add additional checks that the resulting | |
3296 | value has been properly constructed. | |
3297 | ||
3298 | ||
3299 | =head2 random_maurer_prime_with_cert | |
3300 | ||
3301 | my($n, $cert_ref) = random_maurer_prime_with_cert(512) | |
3302 | ||
3303 | As with L</random_maurer_prime>, but returns a two-element array containing | |
3304 | the n-bit provable prime along with a primality certificate. The certificate | |
3305 | is the same as produced by L</prime_certificate> or | |
3306 | L</is_provable_prime_with_cert>, and can be parsed by L</verify_prime> or | |
3307 | any other software that can parse the certificate (the "n-1" form is described | |
3308 | in detail in L</verify_prime>). | |
2862 | 3309 | |
2863 | 3310 | |
2864 | 3311 | |
2919 | 3366 | |
2920 | 3367 | Allows setting of some parameters. Currently the only parameters are: |
2921 | 3368 | |
2922 | xs Allows turning off the XS code, forcing the Pure Perl code | |
2923 | to be used. Set to 0 to disable XS, set to 1 to re-enable. | |
3369 | xs Allows turning off the XS code, forcing the Pure Perl | |
3370 | code to be used. Set to 0 to disable XS, set to 1 to | |
3371 | re-enable. You probably will never want to do this. | |
3372 | ||
3373 | gmp Allows turning off the use of L<Math::Prime::Util::GMP>, | |
3374 | which means using Pure Perl code for big numbers. Set | |
3375 | to 0 to disable GMP, set to 1 to re-enable. | |
2924 | 3376 | You probably will never want to do this. |
2925 | 3377 | |
2926 | gmp Allows turning off the use of L<Math::Prime::Util::GMP>, | |
2927 | which means using Pure Perl code for big numbers. Set to | |
2928 | 0 to disable GMP, set to 1 to re-enable. | |
2929 | You probably will never want to do this. | |
2930 | ||
2931 | assume_rh Allows functions to assume the Riemann hypothesis is true | |
2932 | if set to 1. This defaults to 0. Currently this setting | |
2933 | only impacts prime count lower and upper bounds, but could | |
2934 | later be applied to other areas such as primality testing. | |
2935 | A later version may also have a way to indicate whether | |
2936 | no RH, RH, GRH, or ERH is to be assumed. | |
2937 | ||
2938 | irand Takes a code ref to an irand function returning a uniform | |
2939 | number between 0 and 2**32-1. This will be used for all | |
2940 | random number generation in the module. | |
3378 | assume_rh Allows functions to assume the Riemann hypothesis is | |
3379 | true if set to 1. This defaults to 0. Currently this | |
3380 | setting only impacts prime count lower and upper | |
3381 | bounds, but could later be applied to other areas such | |
3382 | as primality testing. A later version may also have a | |
3383 | way to indicate whether no RH, RH, GRH, or ERH is to | |
3384 | be assumed. | |
3385 | ||
3386 | irand Takes a code ref to an irand function returning a | |
3387 | uniform number between 0 and 2**32-1. This will be | |
3388 | used for all random number generation in the module. | |
2941 | 3389 | |
2942 | 3390 | |
2943 | 3391 | =head1 FACTORING FUNCTIONS |
2957 | 3405 | a few rounds of Pollard's Rho, SQUFOF, Pollard's p-1, Hart's OLF, a long |
2958 | 3406 | run of Pollard's Rho, and finally trial division if anything survives. This |
2959 | 3407 | process is repeated for each non-prime factor. In practice, it is very rare |
2960 | to require more than the first Rho + SQUFOF to find a factor. | |
3408 | to require more than the first Rho + SQUFOF to find a factor, and I have not | |
3409 | seen anything go to the last step. | |
2961 | 3410 | |
2962 | 3411 | Factoring bigints works with pure Perl, and can be very handy on 32-bit |
2963 | 3412 | machines for numbers just over the 32-bit limit, but it can be B<very> slow |
3308 | 3757 | |
3309 | 3758 | =over 4 |
3310 | 3759 | |
3311 | =item L<Math::Prime::FastSieve> | |
3312 | This is the alternative module I use for basic functionality with small | |
3313 | integers. It's fast and simple, and has a good set of features. | |
3314 | ||
3315 | =item L<Math::Primality> | |
3316 | This is the alternative module I use for primality testing on bigints. | |
3317 | ||
3318 | =item L<Math::Pari> | |
3319 | If you want the kitchen sink and can install it and handle using it. There | |
3320 | are still some functions it doesn't do well (e.g. prime count and nth_prime). | |
3760 | =item * L<Math::Prime::FastSieve> is the alternative module I use for basic | |
3761 | functionality with small integers. It's fast and simple, and has a good | |
3762 | set of features. | |
3763 | ||
3764 | =item * L<Math::Primality> is the alternative module I use for primality | |
3765 | testing on bigints. | |
3766 | ||
3767 | =item * L<Math::Pari> if you want the kitchen sink and can install it and | |
3768 | handle using it. There are still some functions it doesn't do well | |
3769 | (e.g. prime count and nth_prime). | |
3321 | 3770 | |
3322 | 3771 | =back |
3323 | 3772 | |
3324 | 3773 | |
3325 | 3774 | L<Math::Prime::XS> has C<is_prime> and C<primes> functionality. There is no |
3326 | bigint support. The C<is_prime> function is a well-written trial division, | |
3775 | bigint support. The C<is_prime> function uses well-written trial division, | |
3327 | 3776 | meaning it is very fast for small numbers, but terribly slow for large |
3328 | 3777 | 64-bit numbers. The prime sieve is an unoptimized non-segmented SoE which |
3329 | 3778 | which returns an array. It works well for 32-bit values, but speed and |
3358 | 3807 | What Crypt::Primes has that MPU does not is support for returning a generator. |
3359 | 3808 | |
3360 | 3809 | L<Math::Factor::XS> calculates prime factors and factors, which correspond to |
3361 | the L</"factor"> and L<"all_factors"> functions of MPU. These functions do | |
3810 | the L</factor> and L</all_factors> functions of MPU. These functions do | |
3362 | 3811 | not support bigints. Both are implemented with trial division, meaning they |
3363 | 3812 | are very fast for really small values, but quickly become unusably slow |
3364 | 3813 | (factoring 19 digit semiprimes is over 700 times slower). It has additional |
3375 | 3824 | trial division). It supports bigints. Unfortunately it is extremely slow on |
3376 | 3825 | any input that isn't comprised entirely of small factors. Even 7 digit inputs |
3377 | 3826 | can take hundreds or thousands of times longer to factor than MPU or |
3378 | L<Math::Factor::XS>. 19-digit semiprimes will take hours vs. MPU's single | |
3827 | L<Math::Factor::XS>. 19-digit semiprimes will take I<hours> vs. MPU's single | |
3379 | 3828 | milliseconds. |
3380 | 3829 | |
3381 | 3830 | L<Math::Factoring> is a placeholder module for bigint factoring. Version 0.02 |
3399 | 3848 | while MPU was originally targeted to native integers, but both have added |
3400 | 3849 | better support for the other. The main differences are extra functionality |
3401 | 3850 | (MPU has more functions) and performance. With native integer inputs, MPU |
3402 | is generally much faster, especially with L</"prime_count">. For bigints, | |
3851 | is generally much faster, especially with L</prime_count>. For bigints, | |
3403 | 3852 | MPU is slower unless the L<Math::Prime::Util::GMP> module is installed, in |
3404 | 3853 | which case they have somewhat similar speeds. L<Math::Primality> also installs |
3405 | 3854 | a C<primes.pl> program, but it has much less functionality than the one |
3411 | 3860 | count, factor count, Euler totient, primorials, etc. Math::NumSeq is mainly |
3412 | 3861 | set up for accessing these values in order, rather than for arbitrary values, |
3413 | 3862 | though some sequences support that. The primary advantage I see is the |
3414 | uniform access mechanism for a <I>lot</I> of sequences. For those methods that | |
3415 | overlap, MPU is usually much faster. Importantly, most all the sequences in | |
3863 | uniform access mechanism for a I<lot> of sequences. For those methods that | |
3864 | overlap, MPU is usually much faster. Importantly, most of the sequences in | |
3416 | 3865 | Math::NumSeq are limited to 32-bit indices. |
3417 | 3866 | |
3418 | 3867 | L<Math::Pari> supports a lot of features, with a great deal of overlap. In |
3423 | 3872 | |
3424 | 3873 | =over 4 |
3425 | 3874 | |
3426 | =item isprime Similar to MPU's L<is_prob_prime> or L<is_prime> functions. | |
3875 | =item isprime | |
3876 | ||
3877 | Similar to MPU's L<is_prob_prime> or L<is_prime> functions. | |
3427 | 3878 | MPU is deterministic for native integers, and uses a strong |
3428 | 3879 | BPSW test for bigints (with a quick primality proof tried as well). The |
3429 | 3880 | default version of Pari used by L<Math::Pari> (2.1.7) uses 10 random M-R |
3433 | 3884 | can take longer (though will be much faster than the BLS75 proof used in |
3434 | 3885 | MPU's L<is_provable_prime> routine). |
3435 | 3886 | |
3436 | =item primepi Similar to MPU's L<prime_count> function. Pari uses a naive | |
3887 | =item primepi | |
3888 | ||
3889 | Similar to MPU's L<prime_count> function. Pari uses a naive | |
3437 | 3890 | counting algorithm with its precalculated primes, so this is not very useful. |
3438 | 3891 | |
3439 | =item primes Doesn't support ranges, requires bumping up the precalculated | |
3892 | =item primes | |
3893 | ||
3894 | Doesn't support ranges, requires bumping up the precalculated | |
3440 | 3895 | primes for larger numbers, which means knowing in advance the upper limit |
3441 | 3896 | for primes. Support for numbers larger than 400M requires making with Pari |
3442 | 3897 | version 2.3.5. If that is used, sieving is about 2x faster than MPU, but |
3443 | 3898 | doesn't support segmenting. |
3444 | 3899 | |
3445 | =item factorint Similar to MPU's L<factor> though with a different return (I | |
3900 | =item factorint | |
3901 | ||
3902 | Similar to MPU's L<factor> though with a different return (I | |
3446 | 3903 | find the result value quite inconvenient to work with, but others may like |
3447 | 3904 | its vector of factor/exponent format). Slower than MPU for all 64-bit inputs |
3448 | 3905 | on an x86_64 platform, it may be faster for large values on other platforms. |
3449 | 3906 | Bigints are slightly faster with Math::Pari for "small" values, and MPU slows |
3450 | 3907 | down rapidly (the difference is noticeable with 30+ digit numbers). |
3451 | 3908 | |
3452 | =item eulerphi Similar to MPU's L<euler_phi>. MPU is 2-5x faster for native | |
3909 | =item eulerphi | |
3910 | ||
3911 | Similar to MPU's L<euler_phi>. MPU is 2-5x faster for native | |
3453 | 3912 | integers. There is also support for a range, which can be much more efficient. |
3454 | 3913 | Without L<Math::Prime::Util::GMP> installed, MPU is very slow with bigints. |
3455 | 3914 | With it installed, it is about 2x slower than Math::Pari. |
3456 | 3915 | |
3457 | =item moebius Similar to MPU's L<moebius>. Comparisons are similar to | |
3458 | C<eulerphi>. | |
3459 | ||
3460 | =item sumdiv Similar to MPU's L<divisor_sum>. The standard sum (sigma_1) is | |
3916 | =item moebius | |
3917 | ||
3918 | Similar to MPU's L<moebius>. Comparisons are similar to C<eulerphi>. | |
3919 | ||
3920 | =item sumdiv | |
3921 | ||
3922 | Similar to MPU's L<divisor_sum>. The standard sum (sigma_1) is | |
3461 | 3923 | very fast in MPU. Giving it a sub makes it much slower, and for numbers |
3462 | with very many factors, Pari is <I>much</I> faster. | |
3463 | ||
3464 | =item eint1 Similar to MPU's L<ExponentialIntegral>. | |
3465 | ||
3466 | =item zeta A more substantial version of MPU's L<RiemannZeta> function. | |
3924 | with very many factors, Pari is I<much> faster. | |
3925 | ||
3926 | =item eint1 | |
3927 | ||
3928 | Similar to MPU's L<ExponentialIntegral>. | |
3929 | ||
3930 | =item zeta | |
3931 | ||
3932 | A more feature-rich version MPU's L<RiemannZeta> function (supports negative | |
3933 | and complex inputs). | |
3467 | 3934 | |
3468 | 3935 | =back |
3469 | 3936 | |
3615 | 4082 | faster. Without the L<Math::Prime::Util::GMP> module, almost all actions on |
3616 | 4083 | numbers greater than native scalars will be much faster in Pari. |
3617 | 4084 | |
3618 | The presentation here: | |
3619 | L<http://math.boisestate.edu/~liljanab/BOISECRYPTFall09/Jacobsen.pdf> | |
4085 | L<This slide presentation|http://math.boisestate.edu/~liljanab/BOISECRYPTFall09/Jacobsen.pdf> | |
3620 | 4086 | has a lot of data on 64-bit and GMP factoring performance I collected in 2009. |
3621 | 4087 | Assuming you do not know anything about the inputs, trial division and |
3622 | 4088 | optimized Fermat or Lehman work very well for small numbers (<= 10 digits), |
3629 | 4095 | L<msieve|http://sourceforge.net/projects/msieve/>, |
3630 | 4096 | L<gmp-ecm|http://ecm.gforge.inria.fr/>, |
3631 | 4097 | L<GGNFS|http://sourceforge.net/projects/ggnfs/>, |
3632 | and L<Pari|http://pari.math.u-bordeaux.fr/>. | |
4098 | and L<Pari|http://pari.math.u-bordeaux.fr/>. The latest yafu should cover most | |
4099 | uses, with GGNFS likely only providing a benefit for numbers large enough to | |
4100 | warrant distributed processing. | |
3633 | 4101 | |
3634 | 4102 | |
3635 | 4103 | The primality proving algorithms leave much to be desired. If you have |
3636 | numbers larger than C<2^128>, I recommend Pari's C<isprime(n, 2)> which | |
3637 | will run a fast APRCL test, or | |
3638 | L<GMP-ECPP|http://http://sourceforge.net/projects/gmp-ecpp/>. Either one | |
4104 | numbers larger than C<2^128>, I recommend C<isprime(n, 2)> from Pari 2.3+ | |
4105 | which will run a fast APRCL test, | |
4106 | L<GMP-ECPP|http://http://sourceforge.net/projects/gmp-ecpp/>, or | |
4107 | L<Primo|http://www.ellipsa.eu/>. Any of those | |
3639 | 4108 | will be much faster than the Lucas or BLS algorithms used in MPU for large |
3640 | inputs. | |
4109 | inputs. For very large numbers, Primo is the one to use. | |
3641 | 4110 | |
3642 | 4111 | |
3643 | 4112 | =head1 AUTHORS |
3648 | 4117 | =head1 ACKNOWLEDGEMENTS |
3649 | 4118 | |
3650 | 4119 | Eratosthenes of Cyrene provided the elegant and simple algorithm for finding |
3651 | the primes. | |
4120 | primes. | |
3652 | 4121 | |
3653 | 4122 | Terje Mathisen, A.R. Quesada, and B. Van Pelt all had useful ideas which I |
3654 | 4123 | used in my wheel sieve. |
3670 | 4139 | |
3671 | 4140 | =item * |
3672 | 4141 | |
3673 | Pierre Dusart, "Estimates of Some Functions Over Primes without R.H.", preprint, 2010. L<http://arxiv.org/abs/1002.0442/> | |
4142 | Pierre Dusart, "Estimates of Some Functions Over Primes without R.H.", preprint, 2010. Updates to the best non-RH bounds for prime count and nth prime. L<http://arxiv.org/abs/1002.0442/> | |
3674 | 4143 | |
3675 | 4144 | =item * |
3676 | 4145 | |
3678 | 4147 | |
3679 | 4148 | =item * |
3680 | 4149 | |
3681 | Gabriel Mincu, "An Asymptotic Expansion", <Journal of Inequalities in Pure and Applied Mathematics>, v4, n2, 2003. A very readable account of Cipolla's 1902 nth prime approximation. L<http://www.emis.de/journals/JIPAM/images/153_02_JIPAM/153_02.pdf> | |
4150 | Gabriel Mincu, "An Asymptotic Expansion", I<Journal of Inequalities in Pure and Applied Mathematics>, v4, n2, 2003. A very readable account of Cipolla's 1902 nth prime approximation. L<http://www.emis.de/journals/JIPAM/images/153_02_JIPAM/153_02.pdf> | |
3682 | 4151 | |
3683 | 4152 | =item * |
3684 | 4153 | |
3706 | 4175 | |
3707 | 4176 | =item * |
3708 | 4177 | |
3709 | Ueli M. Maurer, "Fast Generation of Prime Numbers and Secure Public-Key Cryptographic Parameters", 1995. L<http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.26.2151> | |
4178 | Ueli M. Maurer, "Fast Generation of Prime Numbers and Secure Public-Key Cryptographic Parameters", 1995. Generating random provable primes by building up the prime. L<http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.26.2151> | |
3710 | 4179 | |
3711 | 4180 | =item * |
3712 | 4181 | |
3713 | Pierre-Alain Fouque and Mehdi Tibouchi, "Close to Uniform Prime Number Generation With Fewer Random Bits", pre-print, 2011. L<http://eprint.iacr.org/2011/481> | |
4182 | Pierre-Alain Fouque and Mehdi Tibouchi, "Close to Uniform Prime Number Generation With Fewer Random Bits", pre-print, 2011. Describes random prime distributions, their algorithm for creating random primes using few random bits, and comparisons to other methods. Definitely worth reading for the discussions of uniformity. L<http://eprint.iacr.org/2011/481> | |
3714 | 4183 | |
3715 | 4184 | =item * |
3716 | 4185 | |
3718 | 4187 | |
3719 | 4188 | =item * |
3720 | 4189 | |
3721 | L<OEIS: Primorial|http://oeis.org/wiki/Primorial>. | |
4190 | L<OEIS: Primorial|http://oeis.org/wiki/Primorial> | |
3722 | 4191 | |
3723 | 4192 | =item * |
3724 | 4193 | |
3730 | 4199 | |
3731 | 4200 | =item * |
3732 | 4201 | |
3733 | Manuel Benito and Juan L. Varona, "Recursive formulas related to the summation of the Möbius function", I<The Open Mathematics Journal>, v1, pp 25-34, 2007. Presents a nice algorithm to compute the Mertens functions with only n/3 Möbius values. L<http://www.unirioja.es/cu/jvarona/downloads/Benito-Varona-TOMATJ-Mertens.pdf> | |
4202 | Manuel Benito and Juan L. Varona, "Recursive formulas related to the summation of the Möbius function", I<The Open Mathematics Journal>, v1, pp 25-34, 2007. Among many other things, shows a simple formula for computing the Mertens functions with only n/3 Möbius values (not as fast as Deléglise and Rivat, but really simple). L<http://www.unirioja.es/cu/jvarona/downloads/Benito-Varona-TOMATJ-Mertens.pdf> | |
3734 | 4203 | |
3735 | 4204 | =back |
3736 | 4205 |
75 | 75 | + scalar(keys %allfactors) |
76 | 76 | + 5 # moebius, euler_phi, jordan totient |
77 | 77 | + 15 # random primes |
78 | + 3 # verify_prime | |
79 | + 2*$extra # "big" prime verification | |
78 | 80 | + 0; |
79 | 81 | |
80 | 82 | # Using GMP makes these tests run about 2x faster on some machines |
112 | 114 | random_nbit_prime |
113 | 115 | random_strong_prime |
114 | 116 | random_maurer_prime |
117 | verify_prime | |
115 | 118 | /; |
116 | 119 | # TODO: is_strong_lucas_pseudoprime |
117 | 120 | # ExponentialIntegral |
285 | 288 | cmp_ok( ($pcapf - $pclo)/$pcapf, '<=', $percent , "PC lower"); |
286 | 289 | cmp_ok( ($pcup - $pcapf)/$pcapf, '<=', $percent , "PC upper"); |
287 | 290 | } |
291 | ||
292 | ############################################################################### | |
293 | ||
294 | # Provable primes | |
295 | { | |
296 | my @proof; | |
297 | ||
298 | @proof = (20907001, "Pratt", [ 2, | |
299 | 3, | |
300 | 5, | |
301 | [23,"Pratt",[2,[11,"Pratt",[2,5],2]],5], | |
302 | [101, "Pratt", [2, 5], 2], | |
303 | ], 14 ); | |
304 | ok( verify_prime(@proof), "simple Lucas/Pratt proof verified" ); | |
305 | ||
306 | @proof = ('3364125245431456304736426076174232972735419017865223025179282077503701', 'n-1', | |
307 | [2,5,127, ['28432789963853652887491983185920687231739655787', 'n-1', | |
308 | [ 2,3,163,650933, [ '44662634059309451871488121651101494489', 'n-1', | |
309 | [ 2,3,23,4021,2321273 ], | |
310 | [ 11, 2, 2, 2, 2 ] | |
311 | ] ], | |
312 | [ 2, 2, 2, 2, 2 ] | |
313 | ], | |
314 | '9316417838190714313' ], | |
315 | [ 2, 2, 2, 2, 2 ]); | |
316 | ok( verify_prime(@proof), "simple n-1 proof verified" ); | |
317 | ||
318 | @proof = ('677826928624294778921',"AGKM", ['677826928624294778921', '404277700094248015180', '599134911995823048257', '677826928656744857936', '104088901820753203', ['2293544533', '356794037129589115041']], ['104088901820753203', '0', '73704321689372825', '104088902465395836', '1112795797', ['3380482019', '53320146243107032']], ['1112795797', '0', '638297481', '1112860899', '39019', ['166385704', '356512285']]); | |
319 | ok( verify_prime(@proof), "ECPP primality proof of 677826928624294778921 verified" ); | |
320 | } | |
321 | ||
322 | if ($extra) { | |
323 | my @proof; | |
324 | #skip "Skipping bigger proofs without fast BigInt library", 2 | |
325 | # if $bigintlib !~ /^(GMP|Pari)/; | |
326 | ||
327 | @proof = ('6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151', 'n-1', | |
328 | [ 2,3,5,11,17,31,41,53,131,157,521,1613,61681,8191,42641,858001,51481, '7623851', '308761441' ], | |
329 | [ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 ] ); | |
330 | ok( verify_prime(@proof), "2**521-1 primality proof verified" ); | |
331 | ||
332 | @proof = ('531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502265229285668889329486246501015346579337652707239409519978766587351943831270835393219031728127', 'n-1', | |
333 | [ 2,3,7,607,'112102729', '341117531003194129', '7432339208719', | |
334 | ['845100400152152934331135470251', 'n-1', | |
335 | [2,5,11,31,41,101,251,601,1801], | |
336 | [2,3,3,3,3,2,3,3,3] | |
337 | ] ], | |
338 | [ 3,5,3,2,3,3,3,3 ] ); | |
339 | ok( verify_prime(@proof), "2**607-1 primality proof verified" ); | |
340 | } |