File Coverage

blib/lib/Math/Prime/Util/PP.pm
Criterion Covered Total %
statement 6872 8065 85.2
branch 3711 5922 62.6
condition 1309 2519 51.9
subroutine 539 577 94.8
pod 0 349 0.0
total 12431 17432 71.3


line stmt bran cond sub pod time code
1             package Math::Prime::Util::PP;
2 77     77   19763057 use strict;
  77         207  
  77         3858  
3 77     77   438 use warnings;
  77         161  
  77         7003  
4 77     77   531 use Carp qw/carp croak confess/;
  77         187  
  77         10058  
5              
6             BEGIN {
7 77     77   378 $Math::Prime::Util::PP::AUTHORITY = 'cpan:DANAJ';
8 77         14560 $Math::Prime::Util::PP::VERSION = '0.74';
9             }
10              
11             our $BIGINTVERSION = 0.0;
12             BEGIN {
13 77 100   77   554 do { require Math::BigInt; Math::BigInt->import(try=>"GMP,GMPz,LTM,Pari"); }
  64         105606  
  64         3281381  
14             unless defined $Math::BigInt::VERSION;
15 77         2179932 $BIGINTVERSION = $Math::BigInt::VERSION;
16 77         5568 $BIGINTVERSION =~ s/^(\d+)\.(\d+).*/$1.$2/;
17             }
18              
19             # The Pure Perl versions of all the Math::Prime::Util routines.
20             #
21             # Some of these will be relatively similar in performance, some will be
22             # very slow in comparison.
23             #
24             # Most of these are pretty simple. Also, you really should look at the C
25             # code for more detailed comments, including references to papers.
26              
27 0         0 BEGIN {
28 77     77   726 use constant OLD_PERL_VERSION=> $] < 5.008;
  77         185  
  77         7154  
29 77     77   505 use constant MPU_MAXBITS => (~0 == 4294967295) ? 32 : 64;
  77         162  
  77         4664  
30 77     77   513 use constant MPU_64BIT => MPU_MAXBITS == 64;
  77         210  
  77         4506  
31 77     77   656 use constant MPU_32BIT => MPU_MAXBITS == 32;
  77         341  
  77         4743  
32             #use constant MPU_MAXPARAM => MPU_32BIT ? 4294967295 : 18446744073709551615;
33             #use constant MPU_MAXDIGITS => MPU_32BIT ? 10 : 20;
34 77     77   743 use constant MPU_MAXPRIME => MPU_32BIT ? 4294967291 : 18446744073709551557;
  77         252  
  77         4040  
35 77     77   517 use constant MPU_MAXPRIMEIDX => MPU_32BIT ? 203280221 : 425656284035217743;
  77         198  
  77         4613  
36 77     77   530 use constant MPU_HALFWORD => MPU_32BIT ? 65536 : OLD_PERL_VERSION ? 33554432 : 4294967296;
  77         145  
  77         4506  
37 77     77   434 use constant UVPACKLET => MPU_32BIT ? 'L' : 'Q';
  77         202  
  77         6193  
38 77     77   473 use constant MPU_INFINITY => (65535 > 0+'inf') ? 20**20**20 : 0+'inf';
  77         164  
  77         6995  
39 77     77   470 use constant INTMAX => (!OLD_PERL_VERSION || MPU_32BIT) ? ~0 : 562949953421312;
  77         218  
  77         5562  
40 77     77   512 use constant INTMIN => (MPU_32BIT ? -2147483648 : !OLD_PERL_VERSION ? -9223372036854775808 : -562949953421312);
  77         221  
  77         4832  
41 77     77   471 use constant SINTMAX => (INTMAX >> 1);
  77         186  
  77         5112  
42 77     77   466 use constant B_PRIM235 => Math::BigInt->new("30");
  77         158  
  77         563  
43 77     77   21254 use constant PI_TIMES_8 => 25.13274122871834590770114707;
  77     0   231  
  77         138976  
44             }
45              
46             # TODO: Change this whole file to use this / tobigint
47             our $_BIGINT;
48             *_BIGINT = \$Math::Prime::Util::_BIGINT;
49              
50              
51             # By using these aliases, we call into the main code instead of
52             # to the PP function.
53             #
54             # If we have turned off XS, then this will call the PPFE or direct function.
55             # This might be the same, but if the PPFE does input validation it will
56             # be slower (albeit every call will be validated).
57             #
58             # Otherwise, we'll go to the XS function, which will either handle it
59             # directly (e.g. we've broken down the input into smaller values which
60             # the XS code can handle), or call the GMP backend, otherwise call here.
61             #
62             # For the usual case where we have XS, this is significantly faster. The
63             # aliases make the code here much easier to read. An alternate
64             # implementation would be to make the perl subs here use a pp_{...} prefix.
65              
66              
67             *validate_integer = \&Math::Prime::Util::_validate_integer;
68             *validate_integer_nonneg = \&Math::Prime::Util::_validate_integer_nonneg;
69             *validate_integer_positive = \&Math::Prime::Util::_validate_integer_positive;
70             *validate_integer_abs = \&Math::Prime::Util::_validate_integer_abs;
71             *_bigint_to_int = \&Math::Prime::Util::_bigint_to_int;
72             *reftyped = \&Math::Prime::Util::_reftyped;
73             #*load_bigint = \&Math::Prime::Util::_load_bigint;
74             *tobigint = \&Math::Prime::Util::_to_bigint;
75             *maybetobigint = \&Math::Prime::Util::_to_bigint_if_needed;
76             *maybetobigintall = \&Math::Prime::Util::_maybe_bigint_allargs;
77             *getconfig = \&Math::Prime::Util::prime_get_config;
78              
79             *Maddint = \&Math::Prime::Util::addint;
80             *Msubint = \&Math::Prime::Util::subint;
81             *Madd1int = \&Math::Prime::Util::add1int;
82             *Msub1int = \&Math::Prime::Util::sub1int;
83             *Mmulint = \&Math::Prime::Util::mulint;
84             *Mdivint = \&Math::Prime::Util::divint;
85             *Mpowint = \&Math::Prime::Util::powint;
86             *Mmodint = \&Math::Prime::Util::modint;
87             *Mcdivint = \&Math::Prime::Util::cdivint;
88             *Mabsint = \&Math::Prime::Util::absint;
89             *Msqrtint = \&Math::Prime::Util::sqrtint;
90             *Mrootint = \&Math::Prime::Util::rootint;
91             *Mlogint = \&Math::Prime::Util::logint;
92             *Mnegint = \&Math::Prime::Util::negint;
93             *Mcmpint = \&Math::Prime::Util::cmpint;
94             *Mlshiftint = \&Math::Prime::Util::lshiftint;
95             *Mrshiftint = \&Math::Prime::Util::rshiftint;
96             *Mdivrem = \&Math::Prime::Util::divrem;
97             *Mtdivrem = \&Math::Prime::Util::tdivrem;
98              
99             *Maddmod = \&Math::Prime::Util::addmod;
100             *Msubmod = \&Math::Prime::Util::submod;
101             *Mmulmod = \&Math::Prime::Util::mulmod;
102             *Mdivmod = \&Math::Prime::Util::divmod;
103             *Mpowmod = \&Math::Prime::Util::powmod;
104             *Minvmod = \&Math::Prime::Util::invmod;
105             *Mrootmod = \&Math::Prime::Util::rootmod;
106             *Mmuladdmod = \&Math::Prime::Util::muladdmod;
107             *Mmulsubmod = \&Math::Prime::Util::mulsubmod;
108              
109             *Mgcd = \&Math::Prime::Util::gcd;
110             *Mlcm = \&Math::Prime::Util::lcm;
111             *Mgcdext = \&Math::Prime::Util::gcdext;
112             *Mfactor = \&Math::Prime::Util::factor;
113             *Mfactor_exp = \&Math::Prime::Util::factor_exp;
114             *Mtrial_factor = \&Math::Prime::Util::trial_factor;
115             *Mdivisors = \&Math::Prime::Util::divisors;
116             *Mdivisor_sum = \&Math::Prime::Util::divisor_sum;
117             *Mis_prime = \&Math::Prime::Util::is_prime;
118             *Mis_semiprime = \&Math::Prime::Util::is_semiprime;
119             *Mis_prime_power = \&Math::Prime::Util::is_prime_power;
120             *Mis_power = \&Math::Prime::Util::is_power;
121             *Mis_square_free = \&Math::Prime::Util::is_square_free;
122             *Mis_odd = \&Math::Prime::Util::is_odd;
123             *Mis_even = \&Math::Prime::Util::is_even;
124             *Mis_congruent = \&Math::Prime::Util::is_congruent;
125             *Mis_divisible = \&Math::Prime::Util::is_divisible;
126             *Mchinese = \&Math::Prime::Util::chinese;
127             *Mvaluation = \&Math::Prime::Util::valuation;
128             *Mkronecker = \&Math::Prime::Util::kronecker;
129             *Mmoebius = \&Math::Prime::Util::moebius;
130             *Mtotient = \&Math::Prime::Util::euler_phi;
131             *Mfactorial = \&Math::Prime::Util::factorial;
132             *Mfalling_factorial = \&Math::Prime::Util::falling_factorial;
133             *Mprimorial = \&Math::Prime::Util::primorial;
134             *Mpn_primorial = \&Math::Prime::Util::pn_primorial;
135             *Mbinomial = \&Math::Prime::Util::binomial;
136             *Mstirling = \&Math::Prime::Util::stirling;
137             *Mpowersum = \&Math::Prime::Util::powersum;
138             *Murandomm = \&Math::Prime::Util::urandomm;
139             *Murandomb = \&Math::Prime::Util::urandomb;
140             *Mnext_prime = \&Math::Prime::Util::next_prime;
141             *Mprev_prime = \&Math::Prime::Util::prev_prime;
142             *Mprime_count = \&Math::Prime::Util::prime_count;
143             *Mlucasumod = \&Math::Prime::Util::lucasumod;
144             *Mznorder = \&Math::Prime::Util::znorder;
145             *Mhclassno = \&Math::Prime::Util::hclassno;
146              
147             *Mvecall = \&Math::Prime::Util::vecall;
148             *Mvecany = \&Math::Prime::Util::vecany;
149             *Mvecnone = \&Math::Prime::Util::vecnone;
150             *Mvecsum = \&Math::Prime::Util::vecsum;
151             *Mvecprod = \&Math::Prime::Util::vecprod;
152             *Mvecmin = \&Math::Prime::Util::vecmin;
153             *Mvecmax = \&Math::Prime::Util::vecmax;
154             *Mvecfirst = \&Math::Prime::Util::vecfirst;
155             *Mvecsort = \&Math::Prime::Util::vecsort;
156             *Mvecsorti = \&Math::Prime::Util::vecsorti;
157             *Mvecslide = \&Math::Prime::Util::vecslide;
158             *Mtoset = \&Math::Prime::Util::toset;
159             *Msetinsert = \&Math::Prime::Util::setinsert;
160             *Msetcontains = \&Math::Prime::Util::setcontains;
161             *Msetunion = \&Math::Prime::Util::setunion;
162             *Msetintersect = \&Math::Prime::Util::setintersect;
163              
164             *Mfromdigits = \&Math::Prime::Util::fromdigits;
165             *Mtodigits = \&Math::Prime::Util::todigits;
166             *Mtodigitstring = \&Math::Prime::Util::todigitstring;
167              
168             *Mprimes = \&Math::Prime::Util::primes;
169             *Mfordivisors = \&Math::Prime::Util::fordivisors;
170             *Mforprimes = \&Math::Prime::Util::forprimes;
171             *MLi = \&Math::Prime::Util::LogarithmicIntegral;
172             *Mprime_omega = \&Math::Prime::Util::prime_omega;
173             *Mnth_prime_upper = \&Math::Prime::Util::nth_prime_upper;
174              
175             if (defined $Math::Prime::Util::GMP::VERSION && $Math::Prime::Util::GMP::VERSION >= 0.53) {
176             *Saddint = \&Math::Prime::Util::GMP::addint;
177             *Ssubint = \&Math::Prime::Util::GMP::subint;
178             *Smulint = \&Math::Prime::Util::GMP::mulint;
179             *Sdivint = \&Math::Prime::Util::GMP::divint;
180             *Spowint = \&Math::Prime::Util::GMP::powint;
181             } else {
182             *Saddint = \&Math::Prime::Util::addint;
183             *Ssubint = \&Math::Prime::Util::subint;
184             *Smulint = \&Math::Prime::Util::mulint;
185             *Sdivint = \&Math::Prime::Util::divint;
186             *Spowint = \&Math::Prime::Util::powint;
187             }
188              
189             # We don't have this function yet. Use a simple version for now.
190             *Mtoint = \&_toint_simple;
191              
192              
193             sub _is_nonneg_int {
194 2 50 33 2   25 ((defined $_[0]) && $_[0] ne '' && ($_[0] !~ tr/0123456789//c));
195             }
196              
197             sub _upgrade_to_float {
198 1037 100   1037   12808 do { require Math::BigFloat; Math::BigFloat->import(); }
  2         4059  
  2         79750  
199             if !defined $Math::BigFloat::VERSION;
200 1037         10182 Math::BigFloat->new(@_);
201             }
202              
203             # Get the accuracy of variable x, or the max default from BigInt/BigFloat
204             # One might think to use ref($x)->accuracy() but numbers get upgraded and
205             # downgraded willy-nilly, and it will do the wrong thing from the user's
206             # perspective.
207             sub _find_big_acc {
208 40     40   131 my($x) = @_;
209 40         83 my $b;
210              
211 40 50       259 $b = $x->accuracy() if ref($x) =~ /^Math::Big/;
212 40 100       545 return $b if defined $b;
213              
214 16         39 my($i,$f);
215 16         79 $i = Math::BigInt->accuracy();
216 16 50       262 $f = defined $Math::BigFloat::VERSION ? Math::BigFloat->accuracy() : undef;
217 16 0 33     235 return (($i > $f) ? $i : $f) if defined $i && defined $f;
    50          
218 16 50       56 return $i if defined $i;
219 16 50       53 return $f if defined $f;
220              
221 16         85 $i = Math::BigInt->div_scale();
222 16 50       367 $f = defined $Math::BigFloat::VERSION ? Math::BigFloat->div_scale() : undef;
223 16 50 33     346 return (($i > $f) ? $i : $f) if defined $i && defined $f;
    50          
224 16 0       0 return $i if defined $i;
225 16 0       0 return $f if defined $f;
226 16         0 return 18;
227             }
228              
229             # Only used by RiemannZeta. TODO: refactor to remove this.
230             sub _bfdigits {
231 0     0   0 my($wantbf, $xdigits) = (0, 17);
232 0 0 0     0 if (defined $bignum::VERSION || ref($_[0]) =~ /^Math::Big/) {
233 0 0       0 do { require Math::BigFloat; Math::BigFloat->import(); }
  0         0  
  0         0  
234             if !defined $Math::BigFloat::VERSION;
235 0 0       0 if (ref($_[0]) eq 'Math::BigInt') {
236 0         0 my $xacc = ($_[0])->accuracy();
237 0         0 $_[0] = Math::BigFloat->new($_[0]);
238 0 0       0 ($_[0])->accuracy($xacc) if $xacc;
239             }
240 0 0       0 $_[0] = Math::BigFloat->new("$_[0]") if ref($_[0]) ne 'Math::BigFloat';
241 0         0 $wantbf = _find_big_acc($_[0]);
242 0         0 $xdigits = $wantbf;
243             }
244 0         0 ($wantbf, $xdigits);
245             }
246              
247              
248             sub _validate_integer {
249 456323     456323   582852 if (OLD_PERL_VERSION && defined $_[0] && !ref($_[0])) {
250 77     77   704 no warnings 'numeric';
  77         192  
  77         53148  
251             $_[0] = "$_[0]" if "$_[0]" > 1e15 || "$_[0]" < -1e15;
252             }
253 456323         738474 my($n) = @_;
254 456323 50       870527 croak "Parameter must be defined" if !defined $n;
255              
256 456323         639846 my $refn = ref($n);
257              
258 456323 100 0     737591 if (!$refn) { # Typical case, an integer or string
    50          
    0          
    0          
259 453867 50 66     1657206 croak "Parameter '$n' must be an integer"
      33        
260             if $n eq '' || ($n =~ tr/0123456789//c && $n !~ /^([+-]?)\d+\z/);
261 453867 50 33     1038478 substr($_[0],0,1,'') if $1 && (substr($n,0,1) eq '+' || $n eq '-0');
      66        
262 453867 100 66     1361036 $_[0] = maybetobigint($n) if $n >= INTMAX || $n <= INTMIN;
263             } elsif ($refn eq 'Math::BigInt') {
264 2456 50       7820 croak "Parameter '$n' must be an integer" unless $n->is_int;
265 2456 0       29519 if ($n->is_negative) { $_[0]=_bigint_to_int($_[0]) if $n >= INTMIN; }
  0 50       0  
266 2456 100       21114 else { $_[0]=_bigint_to_int($_[0]) if $n <= INTMAX; }
267             } elsif ($refn =~ /^Math::/ && $refn ne 'Math::BigFloat') {
268 0 0 0     0 $_[0] = _bigint_to_int($_[0]) if $n <= INTMAX && $n >= INTMIN;
269             } elsif ($refn eq 'CODE') {
270 0         0 $_[0] = $_[0]->();
271 0         0 return _validate_integer($_[0]);
272             } else {
273 0         0 $_[0] = "$_[0]";
274 0         0 return _validate_integer($_[0]);
275             }
276 456323 50 66     1430052 $_[0]->upgrade(undef) if ref($_[0]) eq 'Math::BigInt' && $_[0]->upgrade();
277 456323         740378 1;
278             }
279             sub _validate_integer_nonneg {
280 53551     53551   75538 if (OLD_PERL_VERSION && defined $_[0] && !ref($_[0])) {
281 77     77   689 no warnings 'numeric';
  77         173  
  77         1521282  
282             $_[0] = "$_[0]" if "$_[0]" > 1e15;
283             }
284 53551         82599 my($n) = @_;
285 53551 50       102200 croak "Parameter must be defined" if !defined $n;
286              
287 53551         82200 my $refn = ref($n);
288              
289 53551 100 0     92699 if (!$refn) { # Typical case, an integer or string
    50          
    0          
    0          
290 53356 50 33     270450 croak "Parameter '$n' must be a non-negative integer"
      33        
      33        
291             if $n eq '' || ($n =~ tr/0123456789//c && $n !~ /^(\+?)\d+\z/) || $n < 0;
292 53356 50 66     131628 substr($_[0],0,1,'') if $1 && substr($n,0,1) eq '+';
293             # If probably a bigint, do the upgrade, then verify for edge cases.
294 53356 100       100996 $_[0] = maybetobigint($n) if $n >= INTMAX;
295             } elsif ($refn eq 'Math::BigInt') {
296 195 50 33     751 croak "Parameter '$n' must be a non-negative integer"
297             if !$n->is_int || $n->is_negative;
298 195 100       3771 $_[0] = _bigint_to_int($_[0]) if $n <= INTMAX;
299             } elsif ($refn =~ /^Math::/ && $refn ne 'Math::BigFloat') {
300 0 0       0 croak "Parameter '$n' must be a non-negative integer" if $n < 0;
301 0 0       0 $_[0] = _bigint_to_int($_[0]) if $n <= INTMAX;
302             } elsif ($refn eq 'CODE') {
303 0         0 $_[0] = $_[0]->();
304 0         0 return _validate_integer_nonneg($_[0]);
305             } else {
306 0         0 $_[0] = "$_[0]";
307 0         0 return _validate_integer_nonneg($_[0]);
308             }
309 53551 50 66     148520 $_[0]->upgrade(undef) if ref($_[0]) eq 'Math::BigInt' && $_[0]->upgrade();
310 53551         86792 1;
311             }
312             sub _validate_integer_positive {
313 10677     10677   24598 _validate_integer($_[0]);
314 10677 50       36307 croak "Parameter '$_[0]' must be a positive integer"
315             if "$_[0]" < 1;
316 10677         13723 1;
317             }
318             sub _validate_integer_abs {
319 4537 100   4537   9291 if (ref($_[0])) {
320 21 50       81 $_[0] = -$_[0] if $_[0] < 0;
321             } else {
322 4516 100       14348 $_[0] =~ s/^-// if "$_[0]" < 0;
323             }
324 4537         13933 _validate_integer($_[0]);
325             }
326              
327             sub _try_real_gmp_func {
328 0     0   0 my($fref, $ver, $x) = @_;
329 0 0 0     0 return undef unless defined $Math::Prime::Util::GMP::VERSION &&
330             $Math::Prime::Util::GMP::VERSION >= $ver;
331              
332             # For Math::BigInt input we could return Mtoint($str), FP, or full BigFloat.
333              
334 0 0 0     0 if (!ref($x) || ref($x) eq 'Math::BigInt') {
335 0         0 my $fr = 0.0 + $fref->($x, 40); # enough for full long double
336 0 0 0     0 return $fr if !ref($x) || ($fr < 1e15 && $fr > -1e15);
      0        
337             }
338 0         0 my $dig = _find_big_acc($x);
339 0         0 my $str = $fref->($x, $dig);
340 0         0 return _upgrade_to_float($str);
341             }
342              
343             sub _binary_search {
344 16     16   63 my($n, $lo, $hi, $sub, $exitsub) = @_;
345 16         46 while ($lo < $hi) {
346 183         478 my $mid = $lo + int(($hi-$lo) >> 1);
347 183 50 66     577 return $mid if defined $exitsub && $exitsub->($n,$lo,$hi);
348 183 100       409 if ($sub->($mid) < $n) { $lo = $mid+1; }
  99         348  
349 84         284 else { $hi = $mid; }
350             }
351 16         110 return $lo-1;
352             }
353              
354             ################################################################################
355              
356             # TODO: this is in progress.
357             # It's TBD what should be done on failures (undef? croak?)
358             # Handling of trivial floats is terrible.
359             # A single native int should be as fast as possible
360             sub _toint {
361 0     0   0 my @v = @_; # copy them all
362 0         0 my @out;
363 0         0 for my $v (@v) {
364 0 0       0 if (!defined $v) { push @out, 0; next; }
  0         0  
  0         0  
365 0 0 0     0 if (ref($v)) {
    0          
    0          
366 0 0       0 $v = $v->as_int() if ref($v) eq 'Math::BigFloat';
367             } elsif ($v =~ /^[+-]?\d+\z/) {
368             # Good as-is
369             } elsif ($v =~ /e/i || $v =~ /\./) {
370 0         0 $v = _upgrade_to_float($v)->as_int();
371             } else {
372 0         0 $v = int($v);
373             }
374 0 0       0 if ($v =~ /^nan\z/i) { push @out, undef; next; }
  0         0  
  0         0  
375              
376 0         0 validate_integer($v);
377 0         0 push @out, $v;
378             }
379 0         0 @out;
380             }
381              
382             sub _toint_simple {
383 461     461   5866 my($n) = @_;
384 461 50       1066 if ($n >= 0) {
385 461         11830 my $max = MPU_32BIT ? 4294967295 : 70368744177664; # 2^46
386 461 100       4717 if ($n =~ /^[+]?\d+\z/) {
    100          
387 4 100       80 return int("$n") if $n < $max;
388             } elsif ($n < $max) {
389 428         4000 return int("$n");
390             } else {
391 29         13400 $n = "" . _upgrade_to_float("$n")->bfloor;
392             }
393             } else {
394 0         0 my $min = MPU_32BIT ? -2147483648 : -35184372088832; # -2^45
395 0 0       0 if ($n =~ /^[-]\d+\z/) {
    0          
396 0 0       0 return int($n) if $n > $min;
397             } elsif ($n > $min) {
398 0         0 return int($n);
399             } else {
400 0         0 $n = "" . _upgrade_to_float("$n")->bceil;
401             }
402             }
403 30         18547 validate_integer($n);
404 30 50 66     277 $n = tobigint($n) if ref($n) && defined $_BIGINT && ref($n) ne $_BIGINT;
      66        
405 30         552 $n;
406             }
407              
408             sub _frombinary {
409 27     27   121 my($bstr) = @_;
410 27         181 $bstr =~ s/^0//;
411 27 50       98 return oct('0b' . $bstr) if length($bstr) <= 32;
412             # Avoid the useless portable warning that can't be silenced.
413 27 100       89 if (MPU_MAXBITS >= 64 && length($bstr) <= 64) { # 64-bit Perl, 33-64 bit str
414 1         4 my $low = substr($bstr,-32,32,'');
415 1         32 return (oct('0b'.$bstr) << 32) + oct('0b'.$low);
416             }
417             # Length is bigger than word size, so must be a bigint
418 26 50       207 if (!defined $_BIGINT) {
    50          
419 0         0 return Math::BigInt->new("0b$bstr");
420             } elsif ($_BIGINT =~ /^Math::(BigInt|GMPz|GMP)$/) {
421 26         203 return $_BIGINT->new("0b$bstr");
422             } else {
423 0         0 return tobigint( Math::BigInt->new("0b$bstr") );
424             }
425             }
426              
427             ################################################################################
428             ################################################################################
429              
430             my($_precalc_size, @_primes_small) = (2,undef,2);
431             {
432             my $_init_precalc_size = 5003;
433             _register_free_sub(sub {
434             if ($_precalc_size > $_init_precalc_size) {
435             ($_precalc_size, @_primes_small) = (2,undef,2);
436             _expand_prime_cache($_init_precalc_size);
437             }
438             });
439             _expand_prime_cache($_init_precalc_size);
440             }
441             sub _expand_prime_cache {
442 81     81   252 my($N) = @_;
443 81 100       366 if ($N > $_precalc_size) {
444 80 100       322 if ($_primes_small[-1] < 7) {
445 78         228 @_primes_small = (0,2);
446 78         433 my $sieveref = _sieve_erat_string($N);
447 78         54624 push @_primes_small, 2*pos($$sieveref)-1 while $$sieveref =~ m/0/g;
448             } else {
449 2         10 my($lo,$hi) = ($_primes_small[-1] + 2, $N | 0x1);
450 2         20 my($BASE, $sieveref) = ($lo-2, _sieve_segment($lo, $hi));
451 2         8384 push @_primes_small, $BASE+2*pos($$sieveref) while $$sieveref =~ m/0/g;
452             }
453 80         433 $_precalc_size = $N;
454             }
455 81         314 return $_primes_small[-1];
456             }
457              
458              
459             my @_prime_next_small = (
460             2,2,3,5,5,7,7,11,11,11,11,13,13,17,17,17,17,19,19,23,23,23,23,
461             29,29,29,29,29,29,31,31,37,37,37,37,37,37,41,41,41,41,43,43,47,
462             47,47,47,53,53,53,53,53,53,59,59,59,59,59,59,61,61,67,67,67,67,67,67,71);
463              
464             # For wheel-30
465             my @_prime_indices = (1, 7, 11, 13, 17, 19, 23, 29);
466             my @_nextwheel30 = (1,7,7,7,7,7,7,11,11,11,11,13,13,17,17,17,17,19,19,23,23,23,23,29,29,29,29,29,29,1);
467             my @_prevwheel30 = (29,29,1,1,1,1,1,1,7,7,7,7,11,11,13,13,13,13,17,17,19,19,19,19,23,23,23,23,23,23);
468             my @_wheeladvance30 = (1,6,5,4,3,2,1,4,3,2,1,2,1,4,3,2,1,2,1,4,3,2,1,6,5,4,3,2,1,2);
469             my @_wheelretreat30 = (1,2,1,2,3,4,5,6,1,2,3,4,1,2,1,2,3,4,1,2,1,2,3,4,1,2,3,4,5,6);
470              
471             sub _tiny_prime_count {
472 1288     1288   2248 my($n) = @_;
473 1288 50       2887 return if $n >= $_primes_small[-1];
474 1288         1999 my $j = $#_primes_small;
475 1288         2171 my $i = 1 + ($n >> 4);
476 1288         2810 while ($i < $j) {
477 12356         17494 my $mid = ($i+$j)>>1;
478 12356 100       21169 if ($_primes_small[$mid] <= $n) { $i = $mid+1; }
  1991         4467  
479 10365         19690 else { $j = $mid; }
480             }
481 1288         4094 return $i-1;
482             }
483              
484             sub _is_prime7 { # n must not be divisible by 2, 3, or 5
485 16199     16199   184379 my($n) = @_;
486              
487 16199 100 100     37986 $n = _bigint_to_int($n) if ref($n) && $n <= INTMAX;
488              
489 16199 100       190155 if (ref($n)) {
490             # Check div by 7,11,13,17,19,23,29; then by 31,37,...,109,113
491 661 100       5405 return 0 unless Mgcd($n,215656441) == 1;
492 438 100       2617 return 0 unless Mgcd($n,'4885866070719029716366506343847722513') == 1;
493 345 100       2366 return 0 unless _miller_rabin_2($n);
494 90 50       21911 if (Mcmpint($n,"18446744073709551615") <= 0) {
495 0 0       0 return is_almost_extra_strong_lucas_pseudoprime($n) ? 2 : 0;
496             }
497 90 100       10601 return is_extra_strong_lucas_pseudoprime($n) ? 1 : 0;
498             }
499              
500 15538 100       33344 if ($n < 61*61) {
501 5865         14358 foreach my $i (qw/7 11 13 17 19 23 29 31 37 41 43 47 53 59/) {
502 36135 100       76706 return 2 if $i*$i > $n;
503 32598 100       73770 return 0 if !($n % $i);
504             }
505 151         665 return 2;
506             }
507              
508 9673 100 100     152990 return 0 if !($n % 7) || !($n % 11) || !($n % 13) || !($n % 17) ||
      100        
      100        
      100        
      100        
      100        
      100        
      100        
      100        
      100        
      100        
      100        
      100        
509             !($n % 19) || !($n % 23) || !($n % 29) || !($n % 31) ||
510             !($n % 37) || !($n % 41) || !($n % 43) || !($n % 47) ||
511             !($n % 53) || !($n % 59);
512              
513             # We could do:
514             # return is_strong_pseudoprime($n, (2,299417)) if $n < 19471033;
515             # or:
516             # foreach my $p (@_primes_small[18..168]) {
517             # last if $p > $limit;
518             # return 0 unless $n % $p;
519             # }
520             # return 2;
521              
522 5821 100       17744 if ($n <= 1_500_000) {
523 2530         6538 my $limit = int(sqrt($n));
524 2530         4270 my $i = 61;
525 2530         6589 while (($i+30) <= $limit) {
526 2347 100 100     27145 return 0 unless ($n% $i ) && ($n%($i+ 6)) &&
      100        
      100        
      100        
      100        
      100        
      100        
527             ($n%($i+10)) && ($n%($i+12)) &&
528             ($n%($i+16)) && ($n%($i+18)) &&
529             ($n%($i+22)) && ($n%($i+28));
530 2224         4814 $i += 30;
531             }
532 2407         5189 for my $inc (6,4,2,4,2,4,6,2) {
533 10229 100       20626 last if $i > $limit;
534 8027 100       16321 return 0 if !($n % $i);
535 7912         15007 $i += $inc;
536             }
537 2292         8970 return 2;
538             }
539              
540 3291 100       6068 if ($n < 154639673381) { # BPSW seems to be faster after this
541             # Deterministic set of Miller-Rabin tests. If the MR routines can handle
542             # bases greater than n, this can be simplified. This covers all 64-bit
543             # inputs, even though we restrict it to smaller inputs for performance.
544 3239         4349 my @b;
545             # n > 1_000_000 because of the previous block.
546 3239 100       5562 if ($n < 19471033) {@b=(2,299417)}
  3198 100       7376  
    100          
    100          
    50          
    0          
    0          
547 6         17 elsif ($n < 38010307) {@b=(2,9332593)}
548 14         45 elsif ($n < 316349281) {@b=(11000544,31481107)} # 2 bases
549 8         93 elsif ($n < 4759123141) {@b=(2,7,61)}
550 13         42 elsif ($n < 154639673381) {@b=(15,176006322,4221622697)} # 3 bases
551 0         0 elsif ($n < 47636622961201) {@b=(2,2570940,211991001,3749873356)}# 4 bases
552 0         0 elsif ($n < 3770579582154547) {@b=(2,2570940,880937,610386380,4130785767)}
553 0         0 else {@b=(2,325,9375,28178,450775,9780504,1795265022)}
554 3239 100       6385 return is_strong_pseudoprime($n, @b) ? 2 : 0;
555             }
556              
557             # Inlined BPSW
558 52 100       283 return 0 unless _miller_rabin_2($n);
559 38 50       380 return is_almost_extra_strong_lucas_pseudoprime($n) ? 2 : 0;
560             }
561              
562             sub is_prime {
563 14490     14490 0 94558 my($n) = @_;
564 14490         41077 validate_integer($n);
565 14490 100       75816 return 0 if $n < 2;
566              
567 14487 100       273426 if (ref($n) eq 'Math::BigInt') {
568 1065 100       4067 return 0 unless Math::BigInt::bgcd($n, B_PRIM235)->is_one;
569             } else {
570 13422 100 100     25008 if ($n < 7) { return ($n == 2) || ($n == 3) || ($n == 5) ? 2 : 0; }
  99 100       609  
571 13323 100 100     63052 return 0 if !($n % 2) || !($n % 3) || !($n % 5);
      100        
572             }
573 7821         213109 return _is_prime7($n);
574             }
575              
576             # is_prob_prime is the same thing for us.
577             *is_prob_prime = \&is_prime;
578              
579             # BPSW probable prime. No composites are known to have passed this test
580             # since it was published in 1980, though we know infinitely many exist.
581             # It has also been verified that no 64-bit composite will return true.
582             # Slow since it's all in PP and uses bigints.
583             sub _is_bpsw_prime {
584 29     29   90 my($n) = @_;
585 29 0 0     117 return ($n==2 || $n==3 || $n==5) ? 2 : 0 if $n < 7;
    50          
586 29 50       5360 return 0 unless $n % 2;
587 29 100       8848 return 0 unless _miller_rabin_2($n);
588 8 100       1478 if ($n <= 18446744073709551615) {
589 3 50       12 return is_almost_extra_strong_lucas_pseudoprime($n) ? 2 : 0;
590             }
591 5 50       1410 return is_extra_strong_lucas_pseudoprime($n) ? 1 : 0;
592             }
593             sub is_bpsw_prime {
594 29     29 0 123 my($n) = @_;
595 29         148 validate_integer($n);
596 29         1189 return _is_bpsw_prime($n);
597             }
598              
599             sub is_provable_prime {
600 0     0 0 0 my($n) = @_;
601 0         0 validate_integer($n);
602 0 0       0 return _is_bpsw_prime($n) if $n <= 18446744073709551615;
603 0         0 my($is_prime, $cert) = Math::Prime::Util::is_provable_prime_with_cert($n);
604 0         0 $is_prime;
605             }
606              
607             # Possible sieve storage:
608             # 1) vec with mod-30 wheel: 8 bits / 30
609             # 2) vec with mod-2 wheel : 15 bits / 30
610             # 3) str with mod-30 wheel: 8 bytes / 30
611             # 4) str with mod-2 wheel : 15 bytes / 30
612             #
613             # It looks like using vecs is about 2x slower than strs, and the strings also
614             # let us do some fast operations on the results. E.g.
615             # Count all primes:
616             # $count += $$sieveref =~ tr/0//;
617             # Loop over primes:
618             # foreach my $s (split("0", $$sieveref, -1)) {
619             # $n += 2 + 2 * length($s);
620             # .. do something with the prime $n
621             # }
622             #
623             # We're using method 4, though sadly it is memory intensive relative to the
624             # other methods. I will point out that it is 30-60x less memory than sieves
625             # using an array, and the performance of this function is over 10x that
626             # of naive sieves.
627              
628             sub _sieve_erat_string {
629 112     112   311 my($end) = @_;
630 112 100       606 $end-- if ($end & 1) == 0;
631 112         307 my $s_end = $end >> 1;
632              
633 112         489 my $whole = int( $s_end / 15); # Prefill with 3 and 5 already marked.
634 112 50       468 croak "Sieve too large" if $whole > 1_145_324_612; # ~32 GB string
635 112         6020 my $sieve = '100010010010110' . '011010010010110' x $whole;
636 112         465 substr($sieve, $s_end+1) = ''; # Ensure we don't make too many entries
637 112         429 my ($n, $limit) = ( 7, int(sqrt($end)) );
638 112         465 while ( $n <= $limit ) {
639 2873         6882 for (my $s = ($n*$n) >> 1; $s <= $s_end; $s += $n) {
640 2738328         5398455 substr($sieve, $s, 1) = '1';
641             }
642 2873         4450 do { $n += 2 } while substr($sieve, $n>>1, 1);
  6642         20372  
643             }
644 112         4092 return \$sieve;
645             }
646              
647             # TODO: this should be integrated with prime_precalc
648             {
649             my $primary_size_limit = 15000;
650             my $primary_sieve_size = 0;
651             my $primary_sieve_ref;
652             sub _sieve_erat {
653 2326     2326   3645 my($end) = @_;
654              
655 2326 100       6565 return _sieve_erat_string($end) if $end > $primary_size_limit;
656              
657 2294 100       4045 if ($primary_sieve_size == 0) {
658 2         5 $primary_sieve_size = $primary_size_limit;
659 2         9 $primary_sieve_ref = _sieve_erat_string($primary_sieve_size);
660             }
661 2294         6768 my $sieve = substr($$primary_sieve_ref, 0, ($end+1)>>1);
662 2294         8639 return \$sieve;
663             }
664             _register_free_sub(sub {
665             ($primary_sieve_size, $primary_sieve_ref) = (0,'');
666             });
667             }
668              
669              
670             sub _sieve_segment {
671 634     634   1553 my($beg,$end,$limit) = @_;
672 634 50 33     1557 ($beg, $end) = map { _bigint_to_int($_) } ($beg, $end)
  0         0  
673             if ref($end) && $end <= INTMAX;
674 634 50       1598 croak "Internal error: segment beg is even" if ($beg % 2) == 0;
675 634 50       1339 croak "Internal error: segment end is even" if ($end % 2) == 0;
676 634 50       1404 croak "Internal error: segment end < beg" if $end < $beg;
677 634 50       1449 croak "Internal error: segment beg should be >= 3" if $beg < 3;
678 634         1489 my $range = int( ($end - $beg) / 2 ) + 1;
679              
680             # Prefill with 3 and 5 already marked, and offset to the segment start.
681 634         1238 my $whole = int( ($range+14) / 15);
682 634         1124 my $startp = ($beg % 30) >> 1;
683 634         4123 my $sieve = substr('011010010010110', $startp) . '011010010010110' x $whole;
684             # Set 3 and 5 to prime if we're sieving them.
685 634 100       1356 substr($sieve,0,2) = '00' if $beg == 3;
686 634 100       1506 substr($sieve,0,1) = '0' if $beg == 5;
687             # Get rid of any extra we added.
688 634         1022 substr($sieve, $range) = '';
689              
690             # If the end value is below 7^2, then the pre-sieve is all we needed.
691 634 100       1382 return \$sieve if $end < 49;
692              
693 624         2485 my $sqlimit = Msqrtint($end);
694 624 50 33     1692 $limit = $sqlimit if !defined $limit || $sqlimit < $limit;
695             # For large value of end, it's a huge win to just walk primes.
696              
697 624         1487 my($p, $s, $primesieveref) = (7-2, 3, _sieve_erat($limit));
698 624         1256 my $sieve_end = ($end - $beg) >> 1;
699 624         1701 while ( (my $nexts = 1 + index($$primesieveref, '0', $s)) > 0 ) {
700 40830         49999 $p += 2 * ($nexts - $s);
701 40830         49375 $s = $nexts;
702 40830         47591 my $p2 = $p*$p;
703              
704 40830 100       60802 if ($p2 < $beg) { # Make p2 the next odd multiple of p >= beg
705 40207 50       55861 if ($beg < 2**49) {
706 40207         60153 my $f = int(($beg+$p-1)/$p);
707 40207         54630 $p2 = $p * ($f + (1-($f&1)));
708             } else {
709 0         0 my $f = Mcdivint($beg,$p);
710 0         0 $p2 = Mmulint($p, $f + (1-($f&1)));
711             }
712             }
713              
714             # Large bases and small segments often don't hit the segment at all.
715 40830 100       82301 next if $p2 > $end;
716              
717             # Inner loop marking multiples of p, divide by 2 to keep loop simpler.
718 20939         32783 for ($p2 = ($p2 - $beg) >> 1; $p2 <= $sieve_end; $p2 += $p) {
719 676511         1067804 substr($sieve, $p2, 1) = '1';
720             }
721             }
722 624         2761 \$sieve;
723             }
724              
725             sub trial_primes {
726 2     2 0 3394 my($low,$high) = @_;
727 2 100       8 if (!defined $high) {
728 1         2 $high = $low;
729 1         3 $low = 2;
730             }
731 2         13 validate_integer_nonneg($low);
732 2         40 validate_integer_nonneg($high);
733 2 50       27 return if $low > $high;
734 2         39 my @primes;
735              
736             # For a tiny range, just use next_prime calls
737 2 50       7 if (($high-$low) < 1000) {
738 2 50       323 $low-- if $low >= 2;
739 2         241 my $curprime = Mnext_prime($low);
740 2         7 while ($curprime <= $high) {
741 24         135 push @primes, $curprime;
742 24         37 $curprime = Mnext_prime($curprime);
743             }
744 2         58 return \@primes;
745             }
746              
747             # Sieve to 10k then BPSW test
748 0 0 0     0 push @primes, 2 if ($low <= 2) && ($high >= 2);
749 0 0 0     0 push @primes, 3 if ($low <= 3) && ($high >= 3);
750 0 0 0     0 push @primes, 5 if ($low <= 5) && ($high >= 5);
751 0 0       0 $low = 7 if $low < 7;
752 0 0       0 $low++ if ($low % 2) == 0;
753 0 0       0 $high-- if ($high % 2) == 0;
754 0         0 my $sieveref = _sieve_segment($low, $high, 10000);
755 0         0 my $n = $low-2;
756 0         0 while ($$sieveref =~ m/0/g) {
757 0         0 my $p = $n+2*pos($$sieveref);
758 0 0 0     0 push @primes, $p if _miller_rabin_2($p) && is_extra_strong_lucas_pseudoprime($p);
759             }
760 0         0 return \@primes;
761             }
762              
763             sub primes {
764 2720     2720 0 45608 my($low,$high) = @_;
765 2720 100       7193 if (scalar @_ > 1) {
766 2670         7055 validate_integer_nonneg($low);
767 2670 100       6132 $low = 2 if $low < 2;
768             } else {
769 50         147 ($low,$high) = (2, $low);
770             }
771 2720         6350 validate_integer_nonneg($high);
772 2720         4785 my $sref = [];
773 2720 100 66     14923 return $sref if ($low > $high) || ($high < 2);
774 801 100       6194 return [grep { $_ >= $low && $_ <= $high } @_primes_small]
  646760 100       1706917  
775             if $high <= $_primes_small[-1];
776              
777 10 50 33     254 if ($Math::Prime::Util::_GMPfunc{"sieve_primes"} && $Math::Prime::Util::GMP::VERSION >= 0.34) {
778 0         0 my @pr = Math::Prime::Util::GMP::sieve_primes($low, $high, 0);
779 0 0       0 return ref($high) ? [maybetobigintall(@pr)] : \@pr;
780             }
781              
782             # At some point even the pretty-fast pure perl sieve is going to be a
783             # dog, and we should move to trials. This is typical with a small range
784             # on a large base. More thought on the switchover should be done.
785 10 50 66     134 return trial_primes($low, $high) if ref($low) eq 'Math::BigInt'
      33        
      66        
786             || ref($high) eq 'Math::BigInt'
787             || ($low > 1_000_000_000_000 && ($high-$low) < int($low/1_000_000));
788              
789 9 100 66     49 push @$sref, 2 if ($low <= 2) && ($high >= 2);
790 9 100 66     42 push @$sref, 3 if ($low <= 3) && ($high >= 3);
791 9 100 66     41 push @$sref, 5 if ($low <= 5) && ($high >= 5);
792 9 100       62 $low = 7 if $low < 7;
793 9 100       37 $low++ if ($low % 2) == 0;
794 9 100       62 $high-- if ($high % 2) == 0;
795 9 50       72 return $sref if $low > $high;
796              
797 9         20 my($n,$sieveref);
798 9 100       37 if ($low == 7) {
799 2         6 $n = 0;
800 2         10 $sieveref = _sieve_erat($high);
801 2         15 substr($$sieveref,0,3,'111');
802             } else {
803 7         30 $n = $low-1;
804 7         111 $sieveref = _sieve_segment($low,$high);
805             }
806 9         14798 push @$sref, $n+2*pos($$sieveref)-1 while $$sieveref =~ m/0/g;
807 9         1293 $sref;
808             }
809              
810             sub sieve_range {
811 4     4 0 1706 my($n, $width, $depth) = @_;
812 4         17 validate_integer_nonneg($n);
813 4         11 validate_integer_nonneg($width);
814 4         8 validate_integer_nonneg($depth);
815              
816 4         4 my @candidates;
817 4         6 my $start = $n;
818              
819 4 100       10 if ($n < 5) {
820 1 50 33     4 push @candidates, (2-$n) if $n <= 2 && $n+$width-1 >= 2;
821 1 50 33     4 push @candidates, (3-$n) if $n <= 3 && $n+$width-1 >= 3;
822 1 50 33     11 push @candidates, (4-$n) if $n <= 4 && $n+$width-1 >= 4 && $depth < 2;
      33        
823 1         3 $start = 5;
824 1         3 $width -= ($start - $n);
825             }
826              
827 4 100       11 return @candidates, map {$start+$_-$n } 0 .. $width-1 if $depth < 2;
  3         7  
828 17         39 return @candidates, map { $_ - $n }
829 40 100 100     101 grep { ($_ & 1) && ($depth < 3 || ($_ % 3)) }
830 3 100       17 map { $start+$_ }
  40         57  
831             0 .. $width-1 if $depth < 5;
832              
833 1 50       9 if (!($start & 1)) { $start++; $width--; }
  1         3  
  1         2  
834 1 50       4 $width-- if !($width&1);
835 1 50       6 return @candidates if $width < 1;
836              
837 1         8 my $sieveref = _sieve_segment($start, $start+$width-1, $depth);
838 1         4 my $offset = $start - $n - 2;
839 1         9 while ($$sieveref =~ m/0/g) {
840 6         12 push @candidates, $offset + (pos($$sieveref) << 1);
841             }
842 1         9 return @candidates;
843             }
844              
845             sub sieve_prime_cluster {
846 19     19 0 5523322 my($lo,$hi,@cl) = @_;
847 19         114 my $_verbose = getconfig()->{'verbose'};
848 19         141 validate_integer_nonneg($lo);
849 19         913 validate_integer_nonneg($hi);
850              
851 19 50       479 if ($Math::Prime::Util::_GMPfunc{"sieve_prime_cluster"}) {
852 0         0 return maybetobigintall(
853             Math::Prime::Util::GMP::sieve_prime_cluster($lo,$hi,@cl)
854             );
855             }
856              
857 19 50       85 return @{Mprimes($lo,$hi)} if scalar(@cl) == 0;
  0         0  
858              
859 19         68 unshift @cl, 0;
860 19         84 for my $i (1 .. $#cl) {
861 48         202 validate_integer_nonneg($cl[$i]);
862 48 50       169 croak "sieve_prime_cluster: values must be even" if $cl[$i] & 1;
863 48 50       153 croak "sieve_prime_cluster: values must be increasing" if $cl[$i] <= $cl[$i-1];
864             }
865 19         68 my($p,$sievelim,@p) = (17, 3000);
866 19 100 66     205 if (defined $_BIGINT && (ref($lo) || ref($hi))) {
      33        
867 10 50 33     95 ($lo,$hi) = map {tobigint($_)} ($lo,$hi) if ref($lo) ne $_BIGINT || ref($hi) ne $_BIGINT;
  0         0  
868             }
869 19 50       91 $p = 13 if ($hi-$lo) < 50_000_000;
870 19 50       4841 $p = 11 if ($hi-$lo) < 1_000_000;
871 19 100 100     4240 $p = 7 if ($hi-$lo) < 20_000 && $lo < INTMAX;
872              
873             # Add any cases under our sieving point.
874 19 100       6362 if ($lo <= $sievelim) {
875 7 100       23 $sievelim = $hi if $sievelim > $hi;
876 7         18 for my $n (@{Mprimes($lo,$sievelim)}) {
  7         31  
877 1063         1625 my $ac = 1;
878 1063         2445 for my $ci (1 .. $#cl) {
879 1119 100       2545 if (!Mis_prime($n+$cl[$ci])) { $ac = 0; last; }
  882         1383  
  882         1620  
880             }
881 1063 100       2687 push @p, $n if $ac;
882             }
883 7         60 $lo = Mnext_prime($sievelim);
884             }
885 19 100       2297 return @p if $lo > $hi;
886              
887             # Compute acceptable residues.
888 14         728 my $pr = Mprimorial($p);
889 14         88 my $startpr = _bigint_to_int($lo % $pr);
890              
891 14 100       4161 my @acc = grep { ($_ & 1) && $_%3 } ($startpr .. $startpr + $pr - 1);
  26040         60779  
892 14         1469 for my $c (@cl) {
893 52 50       185 if ($p >= 7) {
894 52 100 100     206 @acc = grep { (($_+$c)%3) && (($_+$c)%5) && (($_+$c)%7) } @acc;
  16854         57646  
895             } else {
896 0 0       0 @acc = grep { (($_+$c)%3) && (($_+$c)%5) } @acc;
  0         0  
897             }
898             }
899 14         57 for my $c (@cl) {
900 52         113 @acc = grep { Mgcd($_+$c,$pr) == 1 } @acc;
  1972         4680  
901             }
902 14         51 @acc = map { $_-$startpr } @acc;
  636         1026  
903              
904 14 50       87 print "cluster sieve using ",scalar(@acc)," residues mod $pr\n" if $_verbose;
905 14 50       61 return @p if scalar(@acc) == 0;
906              
907             # Prepare table for more sieving.
908 14         35 my @mprimes = @{Mprimes( $p+1, $sievelim)};
  14         1494  
909 14         169 my(@lorem,@vprem);
910 14         81 for my $pidx (0..$#mprimes) {
911 5953         13195 my $p = $mprimes[$pidx];
912 5953         15651 $lorem[$pidx] = _bigint_to_int($lo % $p);
913 5953         169287 for my $c (@cl) {
914 22106         130285 $vprem[$pidx]->[ ($p-($c%$p)) % $p ] = 1;
915             }
916             }
917              
918             # Walk the range in primorial chunks, doing primality tests.
919 14         60 my($nummr, $numlucas) = (0,0);
920 14         93 while ($lo <= $hi) {
921              
922 54         3211 my @racc = @acc;
923              
924             # Make sure we don't do anything past the limit
925 54 100       255 if (($lo+$acc[-1]) > $hi) {
926 14         4088 my $max = _bigint_to_int($hi-$lo);
927 14         497 @racc = grep { $_ <= $max } @racc;
  636         1137  
928             }
929              
930             # Sieve more values using native math
931 54         7554 for my $pidx (0 .. $#mprimes) {
932 16108         24109 my $p = $mprimes[$pidx];
933 16108         31993 my $rem = $lorem[$pidx];
934 16108         24216 @racc = grep { !$vprem[$pidx]->[ ($rem+$_) % $p ] } @racc;
  217789         451076  
935 16108 100       33965 last unless scalar(@racc);
936             }
937              
938             # Do final primality tests.
939 54 100       322 if ($lo < 1e13) {
940 26         61 for my $r (@racc) {
941 415         968 my($good, $p) = (1, $lo + $r);
942 415         901 for my $c (@cl) {
943 830         1551 $nummr++;
944 830 50       2266 if (!Mis_prime($p+$c)) { $good = 0; last; }
  0         0  
  0         0  
945             }
946 415 50       1369 push @p, $p if $good;
947             }
948             } else {
949 28         8246 for my $r (@racc) {
950 50         332 my($good, $p) = (1, $lo + $r);
951 50         14989 for my $c (@cl) {
952 66         3436 $nummr++;
953 66 100       278 if (!_miller_rabin_2($p+$c)) { $good = 0; last; }
  46         154  
  46         140  
954             }
955 50 100       1688 next unless $good;
956 4         16 for my $c (@cl) {
957 8         1124 $numlucas++;
958 8 50       42 if (!Math::Prime::Util::is_extra_strong_lucas_pseudoprime($p+$c)) { $good = 0; last; }
  0         0  
  0         0  
959             }
960 4 50       428 push @p, $p if $good;
961             }
962             }
963              
964 54         229 $lo += $pr;
965 54 100       10071 if ($lo <= $hi) { # update native remainders
966 40         10572 $lorem[$_] = ($lorem[$_] + $pr) % $mprimes[$_] for 0..$#mprimes;
967             }
968             }
969 14 50       1236 print "cluster sieve ran $nummr MR and $numlucas Lucas tests\n" if $_verbose;
970 14         39910 @p;
971             }
972              
973             sub prime_powers {
974 2     2 0 1108 my($low,$high) = @_;
975 2 50       10 if (scalar @_ > 1) {
976 2         9 validate_integer_nonneg($low);
977 2 100       7 $low = 2 if $low < 2;
978             } else {
979 0         0 ($low,$high) = (2, $low);
980             }
981 2         8 validate_integer_nonneg($high);
982              
983 2 50 33     13 if ($high > 1e18 || ($high-$low) < 10) {
984 0         0 my $sref = [];
985 0         0 while ($low <= $high) {
986 0 0       0 push @$sref, $low if Mis_prime_power($low);
987 0         0 $low = Madd1int($low);
988             }
989 0         0 return $sref;
990             } else {
991 2         5 my @powers;
992 2         15 for my $k (2 .. Mlogint($high,2)) {
993 18         39 my $P = Mpowint(2,$k);
994 18 100       41 push @powers, $P if $P >= $low;
995             }
996 2         9 for my $k (2 .. Mlogint($high,3)) {
997 10         22 my $P = Mpowint(3,$k);
998 10 100       31 push @powers, $P if $P >= $low;
999             }
1000 2         10 for my $k (2 .. Mlogint($high,5)) {
1001 6         17 my $rootn = Mrootint($high, $k);
1002             Mforprimes( sub {
1003 85     85   145 my $P = Mpowint($_,$k);
1004 85 50       697 push @powers, $P if $P >= $low;
1005 6         58 }, 5, $rootn);
1006             }
1007 2         6 push @powers, @{Mprimes($low,$high)};
  2         11  
1008 2         17 return Mvecsorti(\@powers);
1009             }
1010             }
1011              
1012             sub twin_primes {
1013 5     5 0 2518 my($low,$high) = @_;
1014 5 100       25 if (scalar @_ > 1) {
1015 4         18 validate_integer_nonneg($low);
1016 4 50       44 $low = 2 if $low < 2;
1017             } else {
1018 1         4 ($low,$high) = (2, $low);
1019             }
1020 5         172 validate_integer_nonneg($high);
1021 5         34 my @tp;
1022 5 50       19 if ($Math::Prime::Util::_GMPfunc{"twin_twin_primes"}) {
1023 0         0 @tp = Math::Prime::Util::GMP::sieve_twin_primes($low, $high);
1024             } else {
1025 5         19 @tp = sieve_prime_cluster($low, $high, 2);
1026             }
1027 5 100       62 return ref($high) ? [maybetobigintall(@tp)] : \@tp;
1028             }
1029              
1030             sub semi_primes {
1031 1     1 0 2263 my($low,$high) = @_;
1032 1 50       79 if (scalar @_ > 1) {
1033 1         7 validate_integer_nonneg($low);
1034 1 50       5 $low = 4 if $low < 4;
1035             } else {
1036 0         0 ($low,$high) = (4, $low);
1037             }
1038 1         4 validate_integer_nonneg($high);
1039 1         3 my @sp;
1040 1     17   12 Math::Prime::Util::forsemiprimes(sub { push @sp,$_; }, $low, $high);
  17         47  
1041 1         9 \@sp;
1042             }
1043              
1044             # TODO: Port n_range_ramanujan_primes to replace this.
1045             # export it as a function
1046             #
1047             # For now, let's ignore it, this is only used for the PP.
1048              
1049             sub _n_ramanujan_primes {
1050 5     5   16 my($n) = @_;
1051 5 50       52 return [] if $n <= 0;
1052 5         55 my $max = Mnth_prime_upper(int(48/19*$n)+1);
1053 5         34 my @L = (2, (0) x $n-1);
1054 5         12 my $s = 1;
1055 5         31 for (my $k = 7; $k <= $max; $k += 2) {
1056 6178 100       13508 $s++ if Mis_prime($k);
1057 6178 100       16907 $L[$s] = $k+1 if $s < $n;
1058 6178 100 100     20086 $s-- if ($k&3) == 1 && Mis_prime(($k+1)>>1);
1059 6178 100       21458 $L[$s] = $k+2 if $s < $n;
1060             }
1061 5         22 \@L;
1062             }
1063              
1064             sub ramanujan_primes {
1065 4     4 0 1471 my($low,$high) = @_;
1066 4 50       20 if (scalar @_ > 1) {
1067 4         19 validate_integer_nonneg($low);
1068 4 100       19 $low = 2 if $low < 2;
1069             } else {
1070 0         0 ($low,$high) = (2, $low);
1071             }
1072 4         15 validate_integer_nonneg($high);
1073 4 50 33     39 return [] if ($low > $high) || ($high < 2);
1074 4         78 my $nn = Math::Prime::Util::prime_count_upper($high) >> 1;
1075 4         18 my $L = _n_ramanujan_primes($nn);
1076 4   66     50 shift @$L while @$L && $L->[0] < $low;
1077 4   100     89 pop @$L while @$L && $L->[-1] > $high;
1078 4         19 $L;
1079             }
1080              
1081             sub is_ramanujan_prime {
1082 2     2 0 6 my($n) = @_;
1083 2 50       6 return 1 if $n == 2;
1084 2 50       7 return 0 if $n < 11;
1085 2         29 my $L = Math::Prime::Util::ramanujan_primes($n,$n);
1086 2 100       25 return (scalar(@$L) > 0) ? 1 : 0;
1087             }
1088              
1089             sub nth_ramanujan_prime {
1090 1     1 0 996 my($n) = @_;
1091 1         8 validate_integer_nonneg($n);
1092 1 50       5 return undef if $n <= 0; ## no critic qw(ProhibitExplicitReturnUndef)
1093 1         6 my $L = _n_ramanujan_primes($n);
1094 1         24 return $L->[$n-1];
1095             }
1096              
1097             sub next_prime {
1098 9761     9761 0 37841 my($n) = @_;
1099 9761         23751 validate_integer_nonneg($n);
1100 9760 100       33707 return $_prime_next_small[$n] if $n <= 0+$#_prime_next_small;
1101             # This turns out not to be faster.
1102             # return $_primes_small[1+_tiny_prime_count($n)] if $n < $_primes_small[-1];
1103              
1104 2041 100 100     12244 return tobigint(MPU_32BIT ? "4294967311" : "18446744073709551629") if !ref($n) && $n >= MPU_MAXPRIME;
1105             # n is now either 1) not bigint and < maxprime, or (2) bigint and >= uvmax
1106              
1107 2036 50 66     4999 if ($n > 4294967295 && getconfig()->{'gmp'}) {
1108 0         0 return reftyped($_[0], Math::Prime::Util::GMP::next_prime($n));
1109             }
1110              
1111 2036   100     3134 do {
1112 6600         35058 $n += $_wheeladvance30[$n%30];
1113             } while !($n%7) || !_is_prime7($n);
1114              
1115 2036         11190 $n;
1116             }
1117              
1118             sub prev_prime {
1119 157     157 0 4694 my($n) = @_;
1120 157         609 validate_integer_nonneg($n);
1121 157 100       631 return (undef,undef,undef,2,3,3,5,5,7,7,7,7)[$n] if $n <= 11;
1122 156 50 66     1013 if ($n > 4294967295 && getconfig()->{'gmp'}) {
1123 0         0 return reftyped($_[0], Math::Prime::Util::GMP::prev_prime($n));
1124             }
1125              
1126 156   100     270 do {
1127 3104         9423 $n -= $_wheelretreat30[$n%30];
1128             } while !($n%7) || !_is_prime7($n);
1129              
1130 156 100 100     526 $n = _bigint_to_int($n) if ref($n) && $n <= INTMAX;
1131 156         1286 $n;
1132             }
1133              
1134             sub next_prime_power {
1135 2     2 0 1170 my($n) = @_;
1136 2         9 validate_integer_nonneg($n);
1137 2 50       7 return (2,2,3,4,5,7,7,8,9)[$n] if $n <= 8;
1138 2         3 while (1) {
1139 18         54 $n = Madd1int($n);
1140 18 100       39 return $n if Mis_prime_power($n);
1141             }
1142             }
1143             sub prev_prime_power {
1144 2     2 0 5 my($n) = @_;
1145 2         7 validate_integer_nonneg($n);
1146 2 50       4 return (undef,undef,undef,2,3,4,5,5,7)[$n] if $n <= 8;
1147 2         3 while (1) {
1148 12         24 $n = Msub1int($n);
1149 12 100       24 return $n if Mis_prime_power($n);
1150             }
1151             }
1152              
1153             sub partitions {
1154 5     5 0 4146 my($n) = @_;
1155 5         38 validate_integer_nonneg($n);
1156              
1157 5         105 my $d = Msqrtint(Madd1int($n));
1158 5         29 my @pent = (1, map { (($_*(3*$_+1))>>1, (($_+1)*(3*$_+2))>>1) } 1 .. $d);
  173         316  
1159 5         19 my $bigpn = (~0 > 4294967295) ? 400 : 270;
1160 5 100       11 my($ZERO,$ONE) = map { $n >= $bigpn ? tobigint($_) : $_ } (0,1);
  10         70  
1161 5         26 my @part = ($ONE);
1162 5         21 foreach my $j (scalar @part .. $n) {
1163 8051         1657315 my ($psum1, $psum2) = ($ZERO, $ZERO);
1164 8051         16565 my $k = 1;
1165 8051         19079 foreach my $p (@pent) {
1166 460204 100       51917290 last if $p > $j;
1167 452153 100       938672 if ((++$k) & 2) { $psum1 += $part[ $j - $p ] }
  230126         609017  
1168 222027         623123 else { $psum2 += $part[ $j - $p ] }
1169             }
1170 8051         28889 $part[$j] = $psum1 - $psum2;
1171             }
1172 5         4743 return $part[$n];
1173             }
1174              
1175             my @_lf63 = (0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,1,1,1,0,0,1,0,0,1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,1,1,1,1,1,1,0,0);
1176             my @_small_lucky = (undef,1,3,7,9,13,15,21,25,31,33,37,43,49,51,63,67,69,73,75,79,87,93,99,105,111,115,127,129,133,135,141,151,159,163,169,171,189,193,195);
1177              
1178             sub lucky_numbers {
1179 3     3 0 14 my($lo,$hi) = @_;
1180 3 100       6 if (defined $hi) { validate_integer_nonneg($lo); }
  1         4  
1181 2         4 else { ($lo,$hi) = (1, $lo); }
1182 3         10 validate_integer_nonneg($hi);
1183 3 50 33     21 return [] if $hi < $lo || $hi == 0;
1184              
1185 3         4 my @lucky;
1186             # This wheel handles the evens and every 3rd by a mod 6 wheel,
1187             # then uses the mask to skip every 7th and 9th remaining value.
1188 3         7 for (my $k = 1; $k <= $hi; $k += 6) {
1189 358         345 my $m63 = $k % 63;
1190 358 100       573 push @lucky, $k unless $_lf63[$m63];
1191 358 100       556 push @lucky, $k+2 unless $_lf63[$m63+2];
1192             }
1193 3 50       14 delete $lucky[-1] if $lucky[-1] > $hi;
1194              
1195             # Do the standard lucky sieve.
1196 3   66     19 for (my $k = 4; $k <= $#lucky && $lucky[$k]-1 <= $#lucky; $k++) {
1197 64         84 for (my $skip = my $index = $lucky[$k]-1; $index <= $#lucky; $index += $skip) {
1198 203         315 splice(@lucky, $index, 1);
1199             }
1200             }
1201              
1202 3 100       6 if ($lo > 1) { @lucky = grep { $_ >= $lo } @lucky; }
  1         4  
  114         115  
1203              
1204 3         7 \@lucky;
1205             }
1206              
1207             sub lucky_count {
1208 1     1 0 15 my($lo,$hi) = @_;
1209 1 50       4 if (defined $hi) { validate_integer_nonneg($lo); }
  0         0  
1210 1         2 else { ($lo,$hi) = (1, $lo); }
1211 1         3 validate_integer_nonneg($hi);
1212 1 50 33     7 return 0 if $hi < $lo || $hi == 0;
1213              
1214             # Return from our static data if very small.
1215 1 0 0     4 return scalar(grep { defined $_ && $_ >= $lo && $_ <= $hi } @_small_lucky) if $hi <= $_small_lucky[-1];
  0 50       0  
1216              
1217             # Trivial but slow way:
1218             # return scalar(@{Math::Prime::Util::lucky_numbers($lo, $hi)});
1219              
1220 1 50       4 $lo-- if $lo & 1;
1221 1 50       4 $hi++ if $hi & 1;
1222 1         4 my $lsize = 1 + lucky_count_upper($hi);
1223 1         4 my ($locount, $hicount) = ($lo >> 1, $hi >> 1);
1224 1         3 my $ln = Math::Prime::Util::lucky_numbers($lsize);
1225 1         3 shift @$ln;
1226 1 50       3 if ($lo <= 1) {
1227 1         40 $hicount -= int($hicount / $_) for @$ln;
1228             } else {
1229 0         0 for my $l (@$ln) {
1230 0 0       0 last if $l > $hicount;
1231 0 0       0 $locount -= int($locount / $l) if $l <= $lo;
1232 0         0 $hicount -= int($hicount / $l);
1233             }
1234             }
1235 1         19 return $hicount - $locount;
1236             }
1237             sub _simple_lucky_count_approx {
1238 4     4   5 my($n) = @_;
1239 4 50       9 $n = "$n" if ref($n);
1240 4 50       8 return 0 + ($n > 0) + ($n > 2) if $n < 7;
1241 4 50       12 return 0.9957 * $n/log($n) if $n <= 1000000;
1242 0         0 return (1.03670 - log($n)/299) * $n/log($n);
1243             }
1244             sub _simple_lucky_count_upper {
1245 4     4   5 my($n) = @_;
1246 4 50       12 $n = "$n" if ref($n);
1247 4 50       8 return 0 + ($n > 0) + ($n > 2) if $n < 7;
1248 4 50       7 return int(5 + 1.039 * $n/log($n)) if $n <= 7000;
1249 4 50       10 my $a = ($n < 10017000) ? 0.58003 - 3.00e-9 * ($n-7000) : 0.55;
1250 4         10 return int($n/(1.065*log($n) - $a - 3.1/log($n) - 2.85/(log($n)*log($n))));
1251             }
1252             sub _simple_lucky_count_lower {
1253 4     4   6 my($n) = @_;
1254 4         14 my $approx = _simple_lucky_count_approx($n);
1255 4 50       6 my $est = $approx * (($n <= 10000) ? 0.9 : 0.99);
1256 4         13 int($est);
1257             }
1258             sub lucky_count_approx {
1259 1     1 0 12 my($n) = @_;
1260 1         3 validate_integer_nonneg($n);
1261 1 0       3 return scalar(grep { defined $_ && $_ <= $n } @_small_lucky) if $n <= $_small_lucky[-1];
  0 50       0  
1262 1         4 my($lo,$hi) = (_simple_lucky_count_lower($n), _simple_lucky_count_upper($n));
1263             _binary_search($n, $lo, $hi,
1264 1     7   5 sub{Math::Prime::Util::nth_lucky_approx(shift)});
  7         9  
1265             }
1266             sub lucky_count_upper {
1267 2     2 0 9 my($n) = @_;
1268 2         3 validate_integer_nonneg($n);
1269 2 0       3 return scalar(grep { defined $_ && $_ <= $n } @_small_lucky) if $n <= $_small_lucky[-1];
  0 50       0  
1270 2         4 my($lo,$hi) = (_simple_lucky_count_lower($n), _simple_lucky_count_upper($n));
1271             1+_binary_search($n, $lo, $hi,
1272 2     14   16 sub{Math::Prime::Util::nth_lucky_lower(shift)});
  14         22  
1273             }
1274             sub lucky_count_lower {
1275 1     1 0 907 my($n) = @_;
1276 1         5 validate_integer_nonneg($n);
1277 1 0       5 return scalar(grep { defined $_ && $_ <= $n } @_small_lucky) if $n <= $_small_lucky[-1];
  0 50       0  
1278 1         4 my($lo,$hi) = (_simple_lucky_count_lower($n), _simple_lucky_count_upper($n));
1279             _binary_search($n, $lo, $hi,
1280 1     7   19 sub{Math::Prime::Util::nth_lucky_upper(shift)});
  7         28  
1281             }
1282              
1283             sub nth_lucky {
1284 1     1 0 565 my($n) = @_;
1285 1         4 validate_integer_nonneg($n);
1286 1 50       5 return $_small_lucky[$n] if $n <= 0+$#_small_lucky;
1287 0         0 my $k = $n-1;
1288 0         0 my $ln = lucky_numbers($n);
1289 0         0 shift @$ln;
1290 0         0 $k += int($k / ($_-1)) for reverse @$ln;
1291 0         0 2*$k+1;
1292             }
1293             sub nth_lucky_approx {
1294 31     31 0 33 my($n) = @_;
1295 31         43 validate_integer_nonneg($n);
1296 31 50       45 return $_small_lucky[$n] if $n <= 0+$#_small_lucky;
1297 31 50       55 $n = "$n" if ref($n);
1298 31         39 my($logn, $loglogn, $mult) = (log($n), log(log($n)), 1);
1299 31 100       41 if ($n <= 80000) {
1300 28 50       32 my $c = ($n <= 10000) ? 0.2502 : 0.2581;
1301 28         29 $mult = $logn + 0.5 * $loglogn + $c * $loglogn * $loglogn;
1302             } else {
1303 3 50       9 my $c = ($n <= 10000) ? -0.0173 : ($n <= 100000) ? -0.0318 :
    50          
    50          
    50          
1304             ($n <= 1000000) ? -0.0384 : ($n <= 10000000) ? -0.0422 : -0.0440;
1305 3         5 $mult = $logn + (0.5 + $c) * $loglogn *$loglogn;
1306             }
1307 31         56 return int( $n * $mult + 0.5);
1308             }
1309             sub nth_lucky_upper {
1310 8     8 0 12 my($n) = @_;
1311 8         12 validate_integer_nonneg($n);
1312 8 50       20 return $_small_lucky[$n] if $n <= 0+$#_small_lucky;
1313 8 50       19 my $c = ($n <= 100) ? 1.05 : ($n <= 300) ? 1.03 : ($n <= 800) ? 1.01 : 1.0033;
    50          
    50          
1314 8         17 return 1 + int( $c * nth_lucky_approx($n) + 0.5 );
1315             }
1316             sub nth_lucky_lower {
1317 15     15 0 18 my($n) = @_;
1318 15         27 validate_integer_nonneg($n);
1319 15 50       20 return $_small_lucky[$n] if $n <= 0+$#_small_lucky;
1320 15 100       25 my $c = ($n <= 130) ? 0.985 : ($n <= 1000) ? 0.992 : 0.996;
    50          
1321 15         29 return int( $c * nth_lucky_approx($n) );
1322             }
1323              
1324             sub is_lucky {
1325 2     2 0 1152 my($n) = @_;
1326              
1327             # Pretests
1328 2 50 66     35 return 0 if $n <= 0 || !($n % 2) || ($n % 6) == 5 || $_lf63[$n % 63];
      66        
      66        
1329 1 50       4 return 1 if $n < 45;
1330              
1331             # Really simple but slow:
1332             # return lucky_numbers($n)->[-1] == $n;
1333              
1334 1         7 my $upper = int(200 + 0.994 * $n / log($n));
1335 1         27 my $lucky = lucky_numbers($upper);
1336 1         3 my $pos = ($n+1) >> 1;
1337 1         9 my $i = 1;
1338 1         1 while (1) {
1339 48 50       66 my $l = ($i <= $#$lucky) ? $lucky->[$i++] : nth_lucky($i++);
1340 48 100       61 return 1 if $pos < $l;
1341 47         44 my $quo = int($pos / $l);
1342 47 50       58 return 0 if $pos == $quo * $l;
1343 47         38 $pos -= $quo;
1344             }
1345             }
1346              
1347             sub minimal_goldbach_pair {
1348 2     2 0 1068 my($n) = @_;
1349 2         41 validate_integer_nonneg($n);
1350 2 50       9 return undef if $n < 4;
1351 2 0 33     262 return Mis_prime($n-2) ? 2 : undef if $n == 4 || Mis_odd($n);
    50          
1352 2         446 my($p,$H)=(3,Mrshiftint($n));
1353 2         263 while ($p <= $H) {
1354 721 100       106712 return $p if Mis_prime($n-$p);
1355 719         146361 $p = next_prime($p);
1356             }
1357 0         0 undef;
1358             }
1359             sub goldbach_pair_count {
1360 4     4 0 14 my($n) = @_;
1361 4         18 validate_integer_nonneg($n);
1362 4 50       15 return 0 if $n < 4;
1363 4 100 66     26 return Mis_prime($n-2) ? 1 : 0 if $n == 4 || Mis_odd($n);
    100          
1364 2         22 my $s = 0;
1365             Mforprimes( sub {
1366 296 100   296   897 $s++ if Mis_prime($n-$_);
1367 2         26 }, Mrshiftint($n), $n-3);
1368 2         24 $s;
1369             }
1370             sub goldbach_pairs {
1371 6     6 0 20 my($n) = @_;
1372 6 100       20 return goldbach_pair_count($n) unless wantarray;
1373 3         9 validate_integer_nonneg($n);
1374 3 50       6 return () if $n < 4;
1375 3 100 66     16 return Mis_prime($n-2) ? (2) : () if $n & 1 || $n == 4;
    100          
1376 1         1 my @L;
1377             Mforprimes( sub {
1378 16 100   16   49 push @L,$n-$_ if Mis_prime($n-$_);
1379 1         10 }, Mrshiftint($n,1), $n-3);
1380 1         24 reverse @L;
1381             }
1382              
1383              
1384             sub primorial {
1385 43     43 0 50991 my($n) = @_;
1386              
1387 43         119 my @plist = @{Mprimes($n)};
  43         1109  
1388 43         173 my $max = (MPU_32BIT) ? 29 : (OLD_PERL_VERSION) ? 43 : 53;
1389              
1390             # If small enough, multiply the small primes.
1391 43 100       198 if ($n < $max) {
1392 6         28 my $pn = 1;
1393 6         28 $pn *= $_ for @plist;
1394 6         39 return $pn;
1395             }
1396              
1397             # Otherwise, combine them as UVs, then combine using product tree.
1398 37         93 my $i = 0;
1399 37         135 while ($i < $#plist) {
1400 960         2052 my $m = $plist[$i] * $plist[$i+1];
1401 960 100       1730 if ($m <= INTMAX) { splice(@plist, $i, 2, $m); }
  893         2993  
1402 67         153 else { $i++; }
1403             }
1404 37         5453 Mvecprod(@plist);
1405             }
1406              
1407             sub pn_primorial {
1408 29     29 0 47152 my($n) = @_;
1409 29 100       181 return (1,2,6,30,210,2310,30030,510510,9699690,223092870)[$n] if $n < 10;
1410 20         910 Mprimorial(nth_prime($n));
1411             }
1412              
1413             sub consecutive_integer_lcm {
1414 57     57 0 67463 my($n) = @_;
1415 57         250 validate_integer_nonneg($n);
1416              
1417 57 50       199 return (1,1,2)[$n] if $n <= 2;
1418 57         105 my @powers;
1419 57         196 for (my $p = 2; $p <= $n; $p = Mnext_prime($p)) {
1420 1412         2661 my($p_power, $pmin) = ($p, int($n/$p));
1421 1412         3350 $p_power = Mmulint($p_power,$p) while $p_power <= $pmin;
1422 1412         3863 push @powers, $p_power;
1423             }
1424 57         4342 my $pn = Mvecprod(@powers);
1425 57 100       811 $pn = _bigint_to_int($pn) if $pn <= INTMAX;
1426 57         13133 return $pn;
1427             }
1428              
1429             sub frobenius_number {
1430 3     3 0 1418 my(@A) = @_;
1431 3 50       34 return undef if scalar(@A) == 0;
1432 3         24 validate_integer_positive($_) for @A;
1433 3         75 Mvecsorti(\@A);
1434 3 50       16 return -1 if $A[0] == 1;
1435 3 50 33     23 return undef if $A[0] <= 1 || scalar(@A) <= 1;
1436 3 50       23 croak "Frobenius number set must be coprime" unless Mgcd(@A) == 1;
1437              
1438 3 100       251 return Msubint(Msubint(Mmulint($A[0],$A[1]),$A[0]),$A[1]) if scalar(@A) == 2;
1439              
1440             # Basic Round Robin algorithm from Böcker and Lipták
1441             # https://bio.informatik.uni-jena.de/wp/wp-content/uploads/2024/01/BoeckerLiptak_FastSimpleAlgorithm_reprint_2007.pdf
1442              
1443 1         4 my $nlen = $A[0];
1444 1         19 my @N = (0, (undef) x ($nlen-1));
1445 1         15 for my $i (1 .. $#A) {
1446             { # Optimization 3, skip redundant bases
1447 2         6 my $ai = $A[$i];
  2         13  
1448 2         9 my $np = $N[Mmodint($ai,$nlen)];
1449 2 50 66     36 next if defined $np && $np <= $ai;
1450             }
1451 2         11 my $d = Mgcd($A[0], $A[$i]);
1452 2         24 my $nlend = Mdivint($nlen,$d);
1453 2         18 for my $r (0 .. $d-1) {
1454             my $n = ($r == 0) ? 0
1455 2 50       17 : Mvecmin(grep {defined} @N[map { $r+$_*$d } 0..$nlend]);
  0         0  
  0         0  
1456 2 50       8 if (defined $n) {
1457 2 50       11 if (Maddint($n,Mmulint($A[$i],$nlend-1)) <= INTMAX) {
1458 2         17 for (1 .. $nlend-1) {
1459 8         14 $n += $A[$i];
1460 8         32 my $p = $n % $nlen;
1461 8 100 100     28 if (!defined $N[$p] || $N[$p] >= $n) {$N[$p]=$n;} else {$n=$N[$p];}
  6         15  
  2         7  
1462             }
1463             } else {
1464 0         0 for (1 .. $nlend-1) {
1465 0         0 $n = Maddint($n,$A[$i]);
1466 0         0 my $p = Mmodint($n,$nlen);
1467 0 0 0     0 if (!defined $N[$p] || $N[$p] >= $n) {$N[$p]=$n;} else {$n=$N[$p];}
  0         0  
  0         0  
1468             }
1469             }
1470             }
1471             }
1472             }
1473 1         5 my $max = Mvecmax(grep { defined } @N);
  5         17  
1474 1 50       6 $max -= $nlen if defined $max;
1475 1         9 $max;
1476             }
1477              
1478             sub jordan_totient {
1479 25     25 0 3841 my($k, $n) = @_;
1480 25         59 validate_integer_nonneg($k);
1481 25         204 validate_integer_nonneg($n);
1482 25 0       114 return ($n == 1) ? 1 : 0 if $k == 0;
    50          
1483 25 50       47 return Mtotient($n) if $k == 1;
1484 25 0       41 return ($n == 1) ? 1 : 0 if $n <= 1;
    50          
1485              
1486             return reftyped($_[0], Math::Prime::Util::GMP::jordan_totient($k, $n))
1487 25 50       523 if $Math::Prime::Util::_GMPfunc{"jordan_totient"};
1488              
1489 25         30 my $totient = 1;
1490 25         122 foreach my $f (Mfactor_exp($n)) {
1491 42         75 my ($p, $e) = @$f;
1492 42         503 $p = Mpowint($p,$k);
1493 42         1351 $totient = Mmulint($totient, $p-1);
1494 42         1557 $totient = Mmulint($totient, $p) for 2 .. $e;
1495             }
1496 25         90 $totient;
1497             }
1498              
1499             sub euler_phi {
1500 57 100   57 0 2974 return _euler_phi_range(@_) if scalar @_ > 1;
1501 49         102 my($n) = @_;
1502 49 50 33     224 return 0 if defined $n && $n < 0;
1503              
1504             return reftyped($_[0],Math::Prime::Util::GMP::totient($n))
1505 49 50       1781 if $Math::Prime::Util::_GMPfunc{"totient"};
1506              
1507 49         195 validate_integer_nonneg($n);
1508 49 100       804 return $n if $n <= 1;
1509              
1510 45         850 my ($t2, $tot) = (1,1);
1511              
1512 45 100       147 if ($n % 2 == 0) {
1513 23         1550 my $totk = 0;
1514 23         124 while (($n % 4) == 0) { $n >>= 1; $totk++; }
  145         46745  
  145         28779  
1515 23         1233 $n >>= 1;
1516 23 100       941 $t2 = $totk < 32 ? 1 << $totk : Mlshiftint(1,$totk) if $totk > 0;
    100          
1517             }
1518              
1519 45 100       541 if ($n < INTMAX) {
1520 41         720 foreach my $f (Mfactor_exp($n)) {
1521 65         193 my ($p, $e) = @$f;
1522 65         111 $tot *= $p-1;
1523 65         11380 $tot *= $p for 2 .. $e;
1524             }
1525             } else {
1526 4         521 foreach my $f (Mfactor_exp($n)) {
1527 26         43 my ($p, $e) = @$f;
1528 26         107 $tot = Mmulint($tot, $p-1);
1529 26         185 $tot = Mmulint($tot, $p) for 2 .. $e;
1530             }
1531             }
1532 45         465 Mmulint($t2, $tot);
1533             }
1534              
1535             sub inverse_totient {
1536 2     2 0 7 my($n) = @_;
1537 2         12 validate_integer_nonneg($n);
1538              
1539 2 0       8 return wantarray ? (1,2) : 2 if $n == 1;
    50          
1540 2 0 33     15 return wantarray ? () : 0 if $n < 1 || ($n & 1);
    50          
1541              
1542 2 50       14 if (Mis_prime($n >> 1)) { # Coleman Remark 3.3 (Thm 3.1) and Prop 6.2
1543 0         0 my $np1 = Madd1int($n);
1544 0 0       0 return wantarray ? () : 0 if !Mis_prime($np1);
    0          
1545 0 0       0 return wantarray ? ($np1, Mmulint($np1,2)) : 2 if $n >= 10;
    0          
1546             }
1547              
1548 2 100       10 if (!wantarray) {
1549 1         5 my %r = ( 1 => 1 );
1550 8     8   14 Mfordivisors(sub { my $d = $_;
1551 8         23 my $p = Madd1int($d);
1552 8 100       22 if (Mis_prime($p)) {
1553 4         27 my($dp,@sumi,@sumv) = ($d);
1554 4         18 for my $v (0 .. Mvaluation($n, $p)) {
1555 22         39 Mfordivisors(sub { my $d2 = $_;
1556 22 100       67 if (defined $r{$d2}) { push @sumi, Mmulint($d2,$dp); push @sumv, $r{$d2}; }
  7         26  
  7         22  
1557 7         60 }, Mdivint($n,$dp));
1558 7         48 $dp = Mmulint($dp,$p);
1559             }
1560 4         37 $r{ $sumi[$_] } += $sumv[$_] for 0 .. $#sumi;
1561             }
1562 1         89 }, $n);
1563 1 50       972 return (defined $r{$n}) ? $r{$n} : 0;
1564              
1565             } else {
1566              
1567             # To save memory, we split this into two steps.
1568              
1569 1         24 my $_verbose = getconfig()->{'verbose'};
1570 1         8 my %r = ( 1 => [1] );
1571 1         6 my %needed = ( $n => 0 );
1572 1         4 my @DIVINFO;
1573              
1574             # 1. For each divisor from 1 .. n, track which values are needed.
1575 1         5 for my $d (divisors($n)) {
1576 8         44 my $p = Madd1int($d);
1577 8 100       23 next unless Mis_prime($p);
1578 4         8 my @L;
1579 4         34 for my $v (0 .. Mvaluation($n, $p)) {
1580 7         29 my $pv = Mpowint($p, $v);
1581 7         18 my($dp,$pp) = map { Mmulint($_,$pv) } ($d,$p);
  14         37  
1582 22     22   40 Mfordivisors(sub { my $d2 = $_;
1583 22         56 my $F = Mmulint($d2,$dp);
1584             # In phase 2, we will look at the list in d2 to add to list in F.
1585             # If F isn't needed later then we ignore it completely.
1586 22 100 66     95 if (defined $needed{$F} && $needed{$F} < $d) {
1587 7 100       24 $needed{$d2} = $d unless defined $needed{$d2};
1588 7         48 push @L, [$d2,$pp,$F];
1589             }
1590 7         90 }, Mdivint($n, $dp));
1591             }
1592 4         18 push @DIVINFO, [$d, @L];
1593             }
1594              
1595 1 50       6 print " ... inverse_totient phase 1 complete ...\n" if $_verbose;
1596              
1597             # 2. Process the divisors in reverse order.
1598 1         18 for my $dinfo (reverse @DIVINFO) {
1599 4         12 my($d,@L) = @$dinfo;
1600 4         16 my %todelete;
1601             my @T;
1602             # Multiply through by $pp
1603 4         8 for my $dset (@L) {
1604 7 100       19 if (defined $r{$dset->[0]}) {
1605 3         8 my($d2,$pp,$F) = @$dset;
1606 3         6 push @T, [$F, [map { Mmulint($pp,$_) } @{$r{$d2}}]];
  4         11  
  3         7  
1607 3 100       15 $todelete{$d2} = 1 if $needed{$d2} >= $d;
1608             }
1609             }
1610             # Delete intermediate data that isn't needed any more
1611 4         13 delete $r{$_} for keys %todelete;
1612             # Append the multiplied lists.
1613 4         9 push @{$r{$_->[0]}}, @{$_->[1]} for @T;
  3         9  
  3         13  
1614             }
1615 1         21 undef %needed;
1616 1 50       6 print " ... inverse_totient phase 2 complete ...\n" if $_verbose;
1617              
1618 1 50       5 return (defined $r{$n}) ? @{Mvecsorti($r{$n})} : ();
  1         52  
1619             }
1620             }
1621              
1622             sub _euler_phi_range {
1623 8     8   49 my($lo, $hi) = @_;
1624 8         46 validate_integer($lo);
1625 8         60 validate_integer($hi);
1626              
1627 8         17 my @totients;
1628 8   66     57 while ($lo < 0 && $lo <= $hi) {
1629 5         9 push @totients, 0;
1630 5         16 $lo++;
1631             }
1632 8 50       44 return @totients if $hi < $lo;
1633              
1634 8 100 100     628 if ($hi > 2**30 || $hi-$lo < 100) {
1635 5 100       427 ($lo,$hi) = (tobigint($lo),tobigint($hi)) if $hi > 2**49;
1636 5         48 push @totients, euler_phi($lo++) while $lo <= $hi;
1637             } else {
1638 3         360 my @tot = (0 .. $hi);
1639 3         32 foreach my $i (2 .. $hi) {
1640 1781 100       3621 next unless $tot[$i] == $i;
1641 317         502 $tot[$i] = $i-1;
1642 317         656 foreach my $j (2 .. int($hi / $i)) {
1643 3397         6356 $tot[$i*$j] -= $tot[$i*$j]/$i;
1644             }
1645             }
1646 3 100       30 splice(@tot, 0, $lo) if $lo > 0;
1647 3         562 push @totients, @tot;
1648             }
1649 8         650 @totients;
1650             }
1651              
1652             sub _sumtot {
1653 7     7   21 my($n, $cdata, $ecache) = @_;
1654 7 50       24 return $cdata->[$n] if $n <= 0+$#$cdata;
1655 7 100       27 return $ecache->{$n} if defined $ecache->{$n};
1656              
1657 6         34 my $sum = Mmulint($n, $n+1) >> 1;
1658 6         36 my $s = sqrtint($n);
1659 6         49 my $lim = Mdivint($n, $s+1);
1660              
1661 6         34 my($x, $nextx) = ($n, Mdivint($n,2));
1662 6         27 $sum -= Mmulint($x - $nextx, $cdata->[1]);
1663 6         19 for my $k (2 .. $lim) {
1664 259         607 ($x,$nextx) = ($nextx, Mdivint($n,$k+1));
1665 259 100       687 $sum -= ($x <= 0+$#$cdata) ? $cdata->[$x] : _sumtot($x, $cdata, $ecache);
1666 259 50       783 $sum -= Mmulint($x - $nextx,
1667             ($k <= $#$cdata) ? $cdata->[$k] : _sumtot($k, $cdata, $ecache));
1668             }
1669 6 100       65 if ($s > $lim) {
1670 2         34 ($x,$nextx) = ($nextx, Mdivint($n,$s+1));
1671 2 50       35 $sum -= Mmulint($x - $nextx,
1672             ($s <= 0+$#$cdata) ? $cdata->[$s] : _sumtot($s, $cdata, $ecache));
1673             }
1674 6         43 $ecache->{$n} = $sum;
1675 6         35 $sum;
1676             }
1677              
1678             sub sumtotient {
1679 4     4 0 16 my($n) = @_;
1680 4         29 validate_integer_nonneg($n);
1681 4 50       16 return $n if $n <= 2;
1682              
1683 4 100       30 if ($n < 900) { # Simple linear sum for small values.
1684 2         6 my $sum = 0;
1685 2         11 $sum += $_ for Mtotient(1,$n);
1686 2         45 return $sum;
1687             }
1688              
1689 2         14 my $cbrt = Mrootint($n,3);
1690 2         34 my $csize = Mvecprod(4, $cbrt, $cbrt);
1691 2 50       30 $csize = 50_000_000 if $csize > 50_000_000; # Limit memory use to ~2.5GB
1692 2         21 my @sumcache = Mtotient(0,$csize);
1693 2         545 $sumcache[$_] += $sumcache[$_-1] for 2 .. $csize;
1694 2         35 _sumtot($n, \@sumcache, {});
1695             }
1696              
1697              
1698             sub prime_bigomega {
1699 12     12 0 80 my($n) = @_;
1700 12         52 validate_integer_abs($n);
1701 12         561 return scalar(Mfactor($n));
1702             }
1703             sub prime_omega {
1704 3092     3092 0 10694 my($n) = @_;
1705 3092         7638 validate_integer_abs($n);
1706 3092         9368 return scalar(Mfactor_exp($n));
1707             }
1708              
1709             sub moebius {
1710 1031 100   1031 0 14260 return _moebius_range(@_) if scalar @_ > 1;
1711 663         1270 my($n) = @_;
1712 663         1757 validate_integer_abs($n);
1713 663 50       6994 return ($n == 1) ? 1 : 0 if $n <= 1;
    100          
1714 641 100 100     6546 return 0 if ($n >= 49) && (!($n % 4) || !($n % 9) || !($n % 25) || !($n%49) );
      100        
1715 580         28509 my @factors = Mfactor($n);
1716 580         1440 foreach my $i (1 .. $#factors) {
1717 445 100       1534 return 0 if $factors[$i] == $factors[$i-1];
1718             }
1719 428 100       2192 return ((scalar @factors) % 2) ? -1 : 1;
1720             }
1721             sub is_square_free {
1722 317 100   317 0 1095 return (Mmoebius($_[0]) != 0) ? 1 : 0;
1723             }
1724              
1725             sub is_odd {
1726 343     343 0 593 my($n) = @_;
1727 343         885 validate_integer($n);
1728             # Note: If n is a Math::BigInt (Calc), then performance:
1729             # 0.25x $n->is_odd() # method is fastest
1730             # 0.34x (substr($n,-1,1) =~ tr/13579/13579/) # Perl look at string
1731             # 0.46x is_odd($n) # XS looks at the string
1732             # 1.0x $n % 2 ? 1 : 0
1733             # 1.6x $n & 1 : 1 : 0
1734             # Using LTM backend:
1735             # 0.21 $n->is_odd
1736             # 0.41 (substr($n,-1,1) =~ tr/13579/13579/)
1737             # 0.64 is_odd($n)
1738             # 0.9 $n & 1 ? 1 : 0
1739             # 1.0 $n % 2 ? 1 : 0
1740             #
1741             # Math::GMPz (30x faster baseline)
1742             # 0.23 Math::GMPz::Rmpz_odd_p($n)
1743             # 0.73 (substr($n,-1,1) =~ tr/13579/13579/)
1744             # 0.95 $n & 1 ? 1 : 0
1745             # 1.0 $n % 2 ? 1 : 0
1746             # 1.5 is_odd($n)
1747 343         501 my $R = ref($n);
1748 343 50       713 return $n->is_odd() ? 1 : 0 if $R eq 'Math::BigInt';
    100          
1749 342 0       739 return Math::GMPz::Rmpz_odd_p($n) ? 1 : 0 if $R eq 'Math::GMPz';
    50          
1750 342         455 return (my $k = substr("$n",-1,1)) =~ tr/13579/13579/ if OLD_PERL_VERSION;
1751 342 100       1279 return $n % 2 ? 1 : 0;
1752             }
1753             sub is_even {
1754 113     113 0 911 my($n) = @_;
1755 113         271 validate_integer($n);
1756 113         159 my $R = ref($n);
1757 113 50       289 return $n->is_even() ? 1 : 0 if $R eq 'Math::BigInt';
    100          
1758 109 0       225 return Math::GMPz::Rmpz_even_p($n) ? 1 : 0 if $R eq 'Math::GMPz';
    50          
1759 109         142 return (my $k = substr("$n",-1,1)) =~ tr/02468/02468/ if OLD_PERL_VERSION;
1760 109 100       507 return $n % 2 ? 0 : 1;
1761             }
1762              
1763             sub is_divisible {
1764 857     857 0 20079 my($n,@d) = @_;
1765 857         5010 validate_integer_abs($n);
1766 857         189803 for my $d (@d) {
1767 875         3132 validate_integer_abs($d);
1768 875 0       2961 if ($d == 0) { return 1 if $n == 0; }
  0 50       0  
1769 875 100       3638 else { return 1 if $n % $d == 0; }
1770             }
1771 327         181138 0;
1772             }
1773             sub is_congruent {
1774 8     8 0 417061 my($n,$c,$d) = @_;
1775 8         82 validate_integer($n);
1776 8         198 validate_integer($c);
1777 8         154 validate_integer_abs($d);
1778 8 50       1492 if ($d != 0) {
1779 8 50 33     909 $n = Mmodint($n,$d) if $n < 0 || $n >= $d;
1780 8 100 100     66 $c = Mmodint($c,$d) if $c < 0 || $c >= $d;
1781             }
1782 8         247 return 0+($n == $c);
1783             }
1784              
1785             sub is_smooth {
1786 8     8 0 1956 my($n, $k) = @_;
1787 8         88 validate_integer_abs($n);
1788 8         1178 validate_integer_nonneg($k);
1789              
1790 8 50       27 return 1 if $n <= 1;
1791 8 50       1126 return 0 if $k <= 1;
1792 8 50       39 return 1 if $n <= $k;
1793              
1794             return Math::Prime::Util::GMP::is_smooth($n,$k)
1795 8 50       1018 if $Math::Prime::Util::_GMPfunc{"is_smooth"};
1796              
1797 8 50       25 if ($k <= 10000000) {
1798 8         18 my @f;
1799 8         12 while (1) {
1800 16         112 @f = Mtrial_factor($n, $k);
1801 16 100       54 last if scalar(@f) <= 1;
1802 8 50       25 return 0 if $f[-2] > $k;
1803 8         51 $n = $f[-1];
1804             }
1805 8         135 return 0 + ($f[0] <= $k);
1806             }
1807              
1808 0 0   0   0 return (Mvecnone(sub { $_ > $k }, Mfactor($n))) ? 1 : 0;
  0         0  
1809             }
1810             sub is_rough {
1811 5     5 0 2811 my($n, $k) = @_;
1812 5         55 validate_integer_abs($n);
1813 5         605 validate_integer_nonneg($k);
1814              
1815 5 50       21 return 0+($k == 0) if $n == 0;
1816 5 50 33     546 return 1 if $n == 1 || $k <= 1;
1817 5 50       504 return 0 if $k > $n;
1818 5 50       330 return 0+($n >= 1) if $k == 2;
1819              
1820             return Math::Prime::Util::GMP::is_rough($n,$k)
1821 5 50       20727 if $Math::Prime::Util::_GMPfunc{"is_rough"};
1822              
1823 5 50       19 if ($k < 50000) {
1824 5         33 my @f = Mtrial_factor($n, $k-1);
1825 5         48 return 0 + ($f[0] >= $k);
1826             }
1827              
1828 0 0   0   0 return (Mvecnone(sub { $_ < $k }, Mfactor($n))) ? 1 : 0;
  0         0  
1829             }
1830             sub is_powerful {
1831 6     6 0 1587 my($n, $k) = @_;
1832 6         55 validate_integer($n);
1833 6 100       40 if (defined $k) { validate_integer_nonneg($k); } else { $k = 2; }
  2         8  
  4         8  
1834              
1835 6 50       34 return 0 if $n < 1;
1836 6 50 33     678 return 1 if $n == 1 || $k <= 1;
1837              
1838             return Math::Prime::Util::GMP::is_powerful($n,$k)
1839 6 50       575 if $Math::Prime::Util::_GMPfunc{"is_powerful"};
1840              
1841             # First quick checks for inadmissibility.
1842 6 100       35 if ($k == 2) {
1843 4 50 66     16 return 0 if ($n%3) == 0 && ($n%9) != 0;
1844 4 100 100     1931 return 0 if ($n%5) == 0 && ($n%25) != 0;
1845 3 50 66     1744 return 0 if ($n%7) == 0 && ($n%49) != 0;
1846 3 50 66     1920 return 0 if ($n%11) == 0 && ($n%121) != 0;
1847             } else {
1848 2 50 33     13 return 0 if ($n%3) == 0 && ($n%27) != 0;
1849 2 50 33     342 return 0 if ($n%5) == 0 && ($n%125) != 0;
1850 2 50 33     314 return 0 if ($n%7) == 0 && ($n%343) != 0;
1851 2 50 33     325 return 0 if ($n%11) == 0 && ($n%1331) != 0;
1852             }
1853              
1854             # Next, check and remove all primes under 149 with three 64-bit gcds.
1855 5         3139 for my $GCD ("614889782588491410","3749562977351496827","4343678784233766587") {
1856 10         100 my $g = Mgcd($n, $GCD);
1857 10 100       41 if ($g != 1) {
1858             # Check anything that divides n also divides k times (and remove).
1859 4         88 my $gk = Mpowint($g, $k);
1860 4 100       145 return 0 if ($n % $gk) != 0;
1861 3         569 $n = Mdivint($n, $gk);
1862             # Now remove any possible further amounts of these divisors.
1863 3         14 $g = Mgcd($n, $g);
1864 3   100     16 while ($n > 1 && $g > 1) {
1865 37         1083 $n = Mdivint($n, $g);
1866 37         106 $g = Mgcd($n, $g);
1867             }
1868 3 100       22 return 1 if $n == 1;
1869             }
1870             }
1871              
1872             # For small primes, check for perfect powers and thereby limit the search
1873             # to divisibiilty conditions on primes less than n^(1/(2k)). This is
1874             # usually faster than full factoring.
1875             #
1876             # But ... it's possible this will take far too long (e.g. n=2^256+1). So
1877             # limit to something reasonable.
1878              
1879 2 50 33     19 return 1 if $n == 1 || Mis_power($n) >= $k;
1880 2 100       85 return 0 if $n < Mpowint(149, 2*$k);
1881              
1882 1         5 my $lim_actual = Mrootint($n, 2*$k);
1883 1 50       23 my $lim_effect = ($lim_actual > 10000) ? 10000 : $lim_actual;
1884              
1885 1 50       8 if ($Math::Prime::Util::_GMPfunc{"trial_factor"}) {
1886 0         0 while (1) {
1887 0         0 my @fac = Math::Prime::Util::GMP::trial_factor($n, $lim_effect);
1888 0 0       0 last if scalar(@fac) <= 1;
1889 0         0 my $f = $fac[0];
1890 0 0       0 my $fk = ($k==2) ? $f*$f : Mpowint($f,$k);
1891 0 0       0 return 0 if ($n % $fk) != 0;
1892 0         0 $n = Mdivint($n, $fk);
1893 0         0 $n = Mdivint($n, $f) while !($n % $f);
1894 0 0 0     0 return 1 if $n == 1 || Mis_power($n) >= $k;
1895 0 0       0 return 0 if $n < $fk*$fk;
1896             }
1897             } else {
1898             Mforprimes( sub {
1899 2 50   2   11 my $pk = ($k==2) ? $_*$_ : Mpowint($_,$k);
1900 2 50       8 Math::Prime::Util::lastfor(),return if $n < $pk*$pk;
1901 2 100       21 if (($n%$_) == 0) {
1902 1 50       23 Math::Prime::Util::lastfor(),return if ($n % $pk) != 0;
1903 1         5 $n = Mdivint($n, $pk);
1904 1         6 $n = Mdivint($n, $_) while ($n % $_) == 0;
1905 1 50 33     10 Math::Prime::Util::lastfor(),return if $n == 1 || Mis_power($n) >= $k;
1906             }
1907 1         26 }, 149, $lim_effect);
1908             }
1909 1 50 33     16 return 1 if $n == 1 || Mis_power($n) >= $k;
1910 0 0       0 return 0 if $n <= Mpowint($lim_effect, 2*$k);
1911              
1912             # Taking too long. Factor what is left.
1913 0 0   0   0 return (Mvecall(sub { $_->[1] >= $k }, Mfactor_exp($n))) ? 1 : 0;
  0         0  
1914             }
1915              
1916             sub _powerful_count_recurse {
1917 19158     19158   2001324 my($n, $k, $m, $r) = @_;
1918 19158         92263 my $lim = Mrootint(Mdivint($n, $m), $r);
1919              
1920 19158 100       112006 return $lim if $r <= $k;
1921              
1922 7766         14579 my $sum = 0;
1923 7766         22992 for my $i (1 .. $lim) {
1924 35872 100 100     221886 if (Mgcd($m,$i) == 1 && Mis_square_free($i)) {
1925 19154         566424 $sum += _powerful_count_recurse($n, $k, Mmulint($m,Mpowint($i,$r)), $r-1);
1926             }
1927             }
1928 7766         33413 $sum;
1929             }
1930              
1931             sub powerful_count {
1932 20     20 0 25410 my($n, $k) = @_;
1933 20 50       87 validate_integer($n); $n = 0 if $n < 0;
  20         71  
1934 20 100       534 if (defined $k) { validate_integer_nonneg($k); } else { $k = 2; }
  19         72  
  1         12  
1935              
1936 20 50 33     162 return $n if $k <= 1 || $n <= 1;
1937              
1938 20 100       670 if ($k == 2) {
1939 16         35 my $sum = 0;
1940             # Simple but very slow for n > 2^64.
1941             # Math::Prime::Util::forsquarefreeint(
1942             # sub { $sum += Msqrtint(Mdivint($n,Mpowint($_,3))); },
1943             # Mrootint($n,3)
1944             # );
1945 16         58 my($l,$j) = (0,Msqrtint($n));
1946 16         61 while ($j > 1) {
1947 345         853 my $k2 = Mrootint(Mdivint($n,Mmulint($j,$j)),3)+1;
1948 345         1008 my $w = Math::Prime::Util::powerfree_count($k2-1,2);
1949 345         919 $sum += Mmulint($j,Msubint($w,$l));
1950 345         659 $l = $w;
1951 345         902 $j = Msqrtint(Mdivint($n,Mpowint($k2,3)));
1952             }
1953 16         56 $sum += Math::Prime::Util::powerfree_count(Mrootint($n,3)) - $l;
1954 16         82 return $sum;
1955             }
1956              
1957 4         24 _powerful_count_recurse($n, $k, 1, 2*$k-1);
1958             }
1959              
1960             sub nth_powerful {
1961 1     1 0 5 my($n, $k) = @_;
1962 1         6 validate_integer_nonneg($n);
1963 1 50       17 if (defined $k) { validate_integer_nonneg($k); } else { $k = 2; }
  0         0  
  1         4  
1964              
1965 1 50       5 return undef if $n == 0;
1966 1 50 33     8 return $n if $k <= 1 || $n <= 1;
1967 1 50       5 return Mpowint(2,$k) if $n == 2;
1968 1 50       5 return Mpowint(2,$k+1) if $n == 3;
1969              
1970             # For small n, we can generate k-powerful numbers rapidly. But without
1971             # a reasonable upper limit, it's not clear how to effectively do it.
1972             # E.g. nth_powerful(100,60) = 11972515182562019788602740026717047105681
1973              
1974 1         5 my $lo = Mpowint(2, $k+1);
1975 1         16 my $hi = ~0;
1976 1 50       5 if ($k == 2) {
1977 1         8 $lo = int( $n*$n/4.72303430688484 + 0.3 * $n**(5/3) );
1978 1         4 $hi = int( $n*$n/4.72303430688484 + 0.5 * $n**(5/3) ); # for n >= 170
1979 1 50       4 $hi = ~0 if $hi > ~0;
1980 1 50       5 $lo = $hi >> 1 if $lo > $hi;
1981             }
1982             # We should use some power estimate here.
1983              
1984             # hi could be too low.
1985 1         5 while (Math::Prime::Util::powerful_count($hi,$k) < $n) {
1986 0         0 $lo = Madd1int($hi);
1987 0         0 $hi = Mmulint($k, $hi);
1988             }
1989              
1990             # Simple binary search
1991 1         6 while ($lo < $hi) {
1992 14         38 my $mid = $lo + (($hi-$lo) >> 1);
1993 14 100       51 if (Math::Prime::Util::powerful_count($mid,$k) < $n) { $lo = $mid+1; }
  7         35  
1994 7         35 else { $hi = $mid; }
1995             }
1996 1         25 $hi;
1997             }
1998              
1999             sub _genpowerful {
2000             # uncoverable subroutine
2001 0     0   0 my($m, $r, $n, $k, $arr) = @_;
2002 0 0       0 if ($r < $k) { push @$arr, $m; return; }
  0         0  
  0         0  
2003 0         0 my $rootdiv = Mrootint(Mdivint($n, $m), $r);
2004 0 0       0 if ($r == $k) {
2005 0         0 push @$arr, Mmulint($m, Mpowint($_,$k)) for 1 .. $rootdiv;
2006             } else {
2007 0         0 for my $i (1 .. $rootdiv) {
2008 0 0 0     0 if (Mgcd($m,$i) == 1 && Mis_square_free($i)) {
2009 0         0 _genpowerful(Mmulint($m, Mpowint($i,$r)), $r-1, $n, $k, $arr);
2010             }
2011             }
2012             }
2013             }
2014              
2015             sub _sumpowerful {
2016 1368     1368   2939 my($m, $r, $n, $k) = @_;
2017 1368 50       2761 return $m if $r < $k;
2018              
2019 1368         3890 my $rootdiv = Mrootint(Mdivint($n, $m), $r);
2020              
2021 1368 100       4275 return Mmulint($m, Mpowersum($rootdiv, $k)) if $r == $k;
2022              
2023             # Faster to generate the terms and add at the end
2024 705         1140 my $R = $r-1;
2025 705         1436 my @v = (_sumpowerful($m, $R, $n, $k));
2026 705         1808 for my $i (2 .. $rootdiv) {
2027 17943 100 100     77226 next unless Mgcd($m,$i) == 1 && Mis_square_free($i);
2028 9254         24626 my $M = Mmulint($m, Mpowint($i,$r));
2029 9254 100       38563 push @v, $R == $k ? Mmulint($M,Mpowersum(Mrootint(Mdivint($n,$M),$k),$k))
2030             : _sumpowerful($M, $R, $n, $k);
2031             }
2032 705         2555 Mvecsum(@v);
2033             }
2034              
2035             sub _sumpowerful2 {
2036 2     2   7 my($n) = @_;
2037 2         7 my($lR,$lPS,@v) = (0,0);
2038             Math::Prime::Util::forsquarefreeint(sub {
2039 65233     65233   145337 my $M = Mpowint($_,3);
2040 65233         168868 my $R = Msqrtint(Mdivint($n, $M));
2041 65233 100       131069 ($lR,$lPS) = ($R,Mpowersum($R,2)) if $R != $lR;
2042 65233         141154 push @v, Mmulint($M, $lPS);
2043 2         51 },Mrootint($n,3));
2044 2         1256 Mvecsum(@v);
2045             }
2046              
2047             sub sumpowerful {
2048 12     12 0 25659 my($n, $k) = @_;
2049 12 50       35 validate_integer($n); $n = 0 if $n < 0;
  12         36  
2050 12 50       27 if (defined $k) { validate_integer_nonneg($k); } else { $k = 2; }
  12         34  
  0         0  
2051              
2052 12 50       28 return $n if $n <= 1;
2053 12 100       113 return Mrshiftint(Mmulint($n,Madd1int($n))) if $k <= 1;
2054              
2055 9 100       496 return _sumpowerful2($n) if $k == 2;
2056              
2057             # Alternate method for testing.
2058             # my @a; _genpowerful(1, 2*$k-1, $n, $k, \@a); return Mvecsum(@a);
2059              
2060 7         975 return _sumpowerful(1, 2*$k-1, $n, $k);
2061             }
2062              
2063              
2064             # Generate k-powerful numbers. See Trizen, Feb 2020 and Feb 2024
2065              
2066             sub _pcg {
2067 16     16   55 my($lo, $hi, $k, $m, $r, $pn) = @_;
2068 16         45 my($beg,$end) = (1, Mrootint(Mdivint($hi,$m), $r));
2069              
2070 16 100       97 if ($r <= $k) {
2071 15 100       46 if ($lo > $m) {
2072 14         65 my $lom = Mcdivint($lo,$m);
2073 14 100       34 if ( ($lom >> $r) == 0) {
2074 3         6 $beg = 2;
2075             } else {
2076 11         31 $beg = Mrootint($lom,$r);
2077 11 100       38 $beg++ if Mpowint($beg,$r) != $lom;
2078             }
2079             }
2080 15         61 push @$pn, $m * Mpowint($_,$r) for ($beg .. $end);
2081 15         61 return;
2082             }
2083              
2084 1         6 for my $v ($beg .. $end) {
2085 22 100 66     96 _pcg($lo, $hi, $k, $m * Mpowint($v,$r), $r-1, $pn)
2086             if Mgcd($m,$v) == 1 && Mis_square_free($v);
2087             }
2088             }
2089             sub powerful_numbers {
2090 1     1 0 14 my($lo, $hi, $k) = @_;
2091 1 50       6 if (defined $k) { validate_integer_nonneg($k); } else { $k = 2; }
  0         0  
  1         3  
2092 1 50       4 if (defined $hi) {
2093 1         5 validate_integer_nonneg($lo);
2094             } else {
2095 0         0 ($lo, $hi) = (1, $lo);
2096             }
2097 1         5 validate_integer_nonneg($hi);
2098 1 50       6 return [] if $hi < $lo;
2099 1 50       5 return [$lo .. $hi] if $k <= 1;
2100              
2101 1         3 my $pn = [];
2102 1         18 _pcg($lo, $hi, $k, 1, 2*$k-1, $pn);
2103 1         5 Mvecsorti($pn);
2104             }
2105              
2106             sub is_powerfree {
2107 8     8 0 979 my($n, $k) = @_;
2108 8         18 validate_integer_abs($n);
2109 8 100       15 if (defined $k) { validate_integer_nonneg($k); }
  6         17  
2110 2         47 else { $k = 2; }
2111              
2112 8 0 33     23 return (($n == 1) ? 1 : 0) if $k < 2 || $n <= 1;
    50          
2113             #return 1 if $n < Mpowint(2,$k);
2114 8 50       21 return 1 if $n < 4;
2115              
2116 8 50       17 if ($k == 2) {
    0          
2117 8 100 100     43 return 0 if !($n % 4) || !($n % 9) || !($n % 25);
      66        
2118 5 50       12 return 1 if $n < 49; # 7^2
2119             } elsif ($k == 3) {
2120 0 0 0     0 return 0 if !($n % 8) || !($n % 27) || !($n % 125);
      0        
2121 0 0       0 return 1 if $n < 343; # 7^3
2122             }
2123              
2124             # return (Mvecall(sub { $_->[1] < $k }, Mfactor_exp($n))) ? 1 : 0;
2125 5         14 for my $pe (Mfactor_exp($n)) {
2126 14 50       22 return 0 if $pe->[1] >= $k;
2127             }
2128 5         16 1;
2129             }
2130              
2131             sub powerfree_count {
2132 367     367 0 652 my($n, $k) = @_;
2133 367         992 validate_integer_abs($n);
2134 367 100       771 if (defined $k) { validate_integer_nonneg($k); }
  350         615  
2135 17         41 else { $k = 2; }
2136              
2137 367 50 66     1301 return (($n >= 1) ? 1 : 0) if $k < 2 || $n <= 1;
    100          
2138              
2139 351         814 my $count = 0;
2140 351         808 my $nk = Mrootint($n, $k);
2141              
2142             # If we can do everything native, do that.
2143 351 100 100     5389 if ($n < SINTMAX && $nk < 20000) {
    100 66        
2144 77     77   1215 use integer;
  77         219  
  77         834  
2145 349         1010 my @mu = Mmoebius(0, $nk);
2146 349         857 foreach my $i (2 .. $nk) {
2147 1367 100       3034 $count += $mu[$i] * $n/($i**$k) if $mu[$i];
2148             }
2149 349         924 return Maddint($count,$n);
2150             } elsif ($n < SINTMAX && $nk < 1e8) {
2151             # Split out the trailing n/i^k = 1, saves memory and time if large enough.
2152 77     77   12122 use integer;
  77         215  
  77         631  
2153 1         4 my $L1 = Mrootint($n/2,$k);
2154 1         5 my @mu = Mmoebius(0, $L1);
2155 1         65 foreach my $i (2 .. $L1) {
2156 14141 100       30470 $count += $mu[$i] * $n/($i**$k) if $mu[$i];
2157             }
2158             #@mu = Mmoebius($L1+1, $nk); my $c1 = 0; $c1 += $_ for @mu;
2159 1         11 my $c1 = Math::Prime::Util::mertens($nk) - Math::Prime::Util::mertens($L1);
2160 1         131 return Mvecsum($count,$c1,$n);
2161             }
2162              
2163             # Simple way. All the bigint math kills performance.
2164             # Math::Prime::Util::forsquarefree(
2165             # sub {
2166             # my $t = Mdivint($n, Mpowint($_, $k));
2167             # $count = (scalar(@_) & 1) ? Msubint($count,$t) : Maddint($count,$t);
2168             # },
2169             # 2, $nk
2170             # );
2171              
2172             # Optimization 1: pull out all the ranges at the end with small constant
2173             # multiplications.
2174             # Optimization 2: Use GMP basic arithmetic functions if possible, saving
2175             # all the bigint object overhead. Can be 10x faster.
2176              
2177 1         519 my $A = Msqrtint($nk);
2178 1         5 my @L = (0, $nk, map { Mrootint(Mdivint($n,$_),$k) } 2..$A);
  3         15  
2179 1         3 my @C;
2180              
2181             Math::Prime::Util::forsquarefree(
2182             sub {
2183 12 100   12   74 $count = (scalar(@_) & 1)
2184             ? Ssubint($count, Sdivint($n, Spowint($_, $k)))
2185             : Saddint($count, Sdivint($n, Spowint($_, $k)));
2186             },
2187 1         33 2, $L[$A]
2188             );
2189 1         30 for my $i (2 .. $A) {
2190 3         14 my($c, $lo, $hi) = (0, $L[$i], $L[$i-1]);
2191 3 50       12 if ($i < 15) {
2192 3         12 $c = Math::Prime::Util::mertens($hi) - Math::Prime::Util::mertens($lo);
2193             } else {
2194 0         0 $c += $_ for Mmoebius( Madd1int($lo), $hi );
2195             }
2196 3         11 push @C, $c * ($i-1);
2197 3 50       13 @C = (Mvecsum(@C)) if scalar(@C) > 100000; # Save/restrict memory.
2198             }
2199 1         9 my $ctot = Mvecsum(@C); # Can typically be done in native math.
2200 1         6 Mvecsum($count, $n, $ctot);
2201             }
2202              
2203             sub nth_powerfree {
2204 1     1 0 3 my($n, $k) = @_;
2205 1         5 validate_integer_nonneg($n);
2206 1 50       10 if (defined $k) { validate_integer_nonneg($k); }
  0         0  
2207 1         2 else { $k = 2; }
2208              
2209 1 50 33     7 return undef if $n == 0 || $k < 2;
2210 1 50       4 return $n if $n < 4;
2211              
2212             # 1. zm is the zeta multiplier (float), qk is the expected value (integer).
2213 1         1 my($zm, $qk);
2214 1 50       3 if ($n <= 2**52) {
2215 1 50       4 $zm = ($k == 2) ? 1.644934066848226 : 1.0 + RiemannZeta($k);
2216             } else {
2217 0 0       0 do { require Math::BigFloat; Math::BigFloat->import(); }
  0         0  
  0         0  
2218             if !defined $Math::BigFloat::VERSION;
2219 0         0 require Math::Prime::Util::ZetaBigFloat;
2220 0         0 my $acc = length("$n")+10;
2221 0         0 my $bk = Math::BigFloat->new($k); $bk->accuracy($acc);
  0         0  
2222 0         0 $zm = Math::Prime::Util::ZetaBigFloat::RiemannZeta($bk)->badd(1)->numify;
2223             }
2224 1         5 my $verbose = getconfig()->{'verbose'};
2225              
2226 1         9 $qk = Mtoint($zm * "$n");
2227 1 50       4 print "nth_powerfree: zm $zm qk $qk\n" if $verbose;
2228              
2229 1         2 my($count, $diff);
2230             # In practice this converges very rapidly, usually needing only one iteration.
2231 1         3 for (1 .. 10) {
2232             # 2. Get the actual count at qk and the difference from our goal.
2233 1         3 $count = Math::Prime::Util::powerfree_count($qk,$k);
2234 1 50       5 $diff = ($count >= $n) ? $count-$n : $n-$count;
2235 1 50       4 print "nth_powerfree: iter $_, count $count diff $diff\n" if $verbose;
2236 1 50       14 last if $diff <= 300; # Threshold could be improved.
2237              
2238             # 3. If not close, update the estimate using the expected density zm.
2239 0         0 my $delta = Mtoint($zm * "$diff");
2240 0 0       0 $qk = $count > $n ? Msubint($qk,$delta) : Maddint($qk,$delta);
2241             }
2242 1 50       20 print "nth_powerfree: $qk, moving down to a powerfree number\n" if $verbose;
2243              
2244             # 4. Make sure we're on a powerfree number.
2245 1         4 $qk-- while !Math::Prime::Util::is_powerfree($qk,$k);
2246 1 50       3 print "nth_powerfree: $qk, need to move ",abs($n-$count)," steps\n" if $verbose;
2247              
2248             # 5. Walk forward or backward to next/prev powerfree number.
2249 1 50       12 my $adder = ($count < $n) ? 1 : -1;
2250 1         4 while ($count != $n) {
2251 3         5 do { $qk += $adder; } while !Math::Prime::Util::is_powerfree($qk,$k);
  4         9  
2252 3         7 $count += $adder;
2253             }
2254 1         8 $qk;
2255             }
2256              
2257             sub powerfree_sum {
2258 8     8 0 33 my($n, $k) = @_;
2259 8         25 validate_integer_nonneg($n);
2260 8 50       16 if (defined $k) { validate_integer_nonneg($k); }
  8         16  
2261 0         0 else { $k = 2; }
2262              
2263 8 50 66     33 return (($n >= 1) ? 1 : 0) if $k < 2 || $n <= 1;
    100          
2264              
2265 7         13 my $sum = 0;
2266 7         12 my($ik, $nik, $T);
2267             Math::Prime::Util::forsquarefree(
2268             sub {
2269 76     76   184 $ik = Mpowint($_, $k);
2270 76         167 $nik = Mdivint($n, $ik);
2271 76         176 $T = Mrshiftint(Mmulint($nik, Madd1int($nik)));
2272 76 100       197 $sum = (scalar(@_) & 1) ? Msubint($sum, Mmulint($ik,$T)) :
2273             Maddint($sum, Mmulint($ik,$T));
2274             },
2275 7         62 Mrootint($n, $k)
2276             );
2277 7         103 $sum;
2278             }
2279              
2280             sub powerfree_part {
2281 1003     1003 0 32081 my($n, $k) = @_;
2282 1003 50       1528 my $negmul = ($n < 0) ? -1 : 1;
2283 1003         1659 validate_integer_abs($n);
2284 1003 100       2960 if (defined $k) { validate_integer_nonneg($k); }
  1001         1190  
2285 2         3 else { $k = 2; }
2286              
2287 1003 50       1488 return $negmul if $n == 1;
2288 1003 100 66     4087 return 0 if $k < 2 || $n == 0;
2289              
2290             #return Mvecprod(map { Mpowint($_->[0], $_->[1] % $k) } Mfactor_exp($n));
2291              
2292             # Rather than build with k-free section, we will remove excess powers
2293 9         1201 my $P = $n;
2294 9         53 for my $pe (Mfactor_exp($n)) {
2295 83 100       547 $P = Mdivint($P, Mpowint($pe->[0], $pe->[1] - ($pe->[1] % $k)))
2296             if $pe->[1] >= $k;
2297             }
2298 9 50       64 $P = Mnegint($P) unless $negmul == 1;
2299 9         84 $P;
2300             }
2301              
2302             sub _T {
2303 379     379   627 my($n) = @_;
2304 379 100       1043 return $n < 65536 ? ($n*($n+1))>>1 : Mrshiftint(Mmulint($n, Madd1int($n)));
2305             }
2306             sub _fprod {
2307 376     376   580 my($n,$k) = @_;
2308 376         911 Mvecprod(map { 1 - Mpowint($_->[0], $k) } Mfactor_exp($n));
  704         1321  
2309             }
2310              
2311             sub powerfree_part_sum {
2312 3     3 0 10 my($n, $k) = @_;
2313 3         15 validate_integer_abs($n);
2314 3 100       11 if (defined $k) { validate_integer_nonneg($k); }
  2         7  
2315 1         3 else { $k = 2; }
2316              
2317 3 0 33     31 return (($n >= 1) ? 1 : 0) if $k < 2 || $n <= 1;
    50          
2318              
2319             Mvecsum( _T($n),
2320 3         12 map { Mmulint(_fprod($_,$k), _T(Mdivint($n, Mpowint($_, $k)))) }
  376         650  
2321             2 .. Mrootint($n,$k)
2322             );
2323             }
2324              
2325             sub squarefree_kernel {
2326 2     2 0 6 my($n) = @_;
2327 2         7 validate_integer($n);
2328 2 50       5 return Mnegint(Mlcm(Mfactor(Mnegint($n)))) if $n < 0;
2329 2         6 Mlcm(Mfactor($n));
2330             }
2331              
2332             sub is_perfect_power {
2333 3     3 0 1156 my($n) = @_;
2334 3         27 validate_integer($n);
2335 3 50       10 if ($n < 0) {
2336 0         0 my $res = Mis_power(Mnegint($n));
2337 0 0 0     0 return ($n == -1 || ($res > 2 && (($res & ($res-1)) != 0))) ? 1 : 0;
2338             }
2339 3 50       384 return (1,1,0,0,1,0,0,0,1,1)[$n] if $n <= 9;
2340 3 100       275 return (Mis_power($n) > 1) ? 1 : 0;
2341             }
2342              
2343             sub _perfect_power_count {
2344 8     8   21 my($n) = @_;
2345 8 50       32 return 0+($n>=1)+($n>=4) if $n < 8;
2346             #return reftyped($_[0], Math::Prime::Util::GMP::perfect_power_count($n))
2347             # if $Math::Prime::Util::_GMPfunc{"perfect_power_count"};
2348 8         666 my @T = (1);
2349              
2350 8         35 my $log2n = Mlogint($n,2);
2351 8         27 for my $k (2 .. $log2n) {
2352 394         1145 my $m = Mmoebius($k);
2353 394 100       954 next if $m == 0;
2354 247         808 push @T, Mmulint(-$m, Msub1int(Mrootint($n,$k)));
2355             }
2356 8         92 Mvecsum(@T);
2357             }
2358             sub perfect_power_count {
2359 2     2 0 10 my($lo,$hi) = @_;
2360 2 100       11 if (defined $hi) { validate_integer_nonneg($lo); }
  1         5  
2361 1         4 else { ($lo,$hi) = (1, $lo); }
2362 2         11 validate_integer_nonneg($hi);
2363 2 50 33     14 return 0 if $hi < $lo || $hi == 0;
2364 2 100       10 return _perfect_power_count($hi) - (($lo <= 1) ? 0 : _perfect_power_count($lo-1));
2365             }
2366              
2367             sub perfect_power_count_approx {
2368 1     1 0 4 my($n) = @_;
2369 1         4 validate_integer_nonneg($n);
2370 1         4 _perfect_power_count($n);
2371             }
2372             sub perfect_power_count_lower {
2373 1     1 0 4 my($n) = @_;
2374 1         4 validate_integer_nonneg($n);
2375 1         4 _perfect_power_count($n);
2376             }
2377             sub perfect_power_count_upper {
2378 1     1 0 4 my($n) = @_;
2379 1         4 validate_integer_nonneg($n);
2380 1         4 _perfect_power_count($n);
2381             }
2382              
2383             sub _next_perfect_power {
2384 5     5   153 my($n, $only_oddpowers) = @_;
2385 5 50       16 croak "_npp must have positive n" if $n < 0;
2386              
2387 5 50       239 return 1 if $n == 0;
2388 5 0       245 return ($only_oddpowers ? 8 : 4) if $n == 1;
    50          
2389              
2390 5         253 my $log2n = Mlogint($n,2);
2391 5 100       147 my $kinit = $only_oddpowers ? 3 : 2;
2392 5 100       15 my $kinc = $only_oddpowers ? 2 : 1;
2393              
2394 5         68 my $best = Mpowint(Madd1int(Mrootint($n,$kinit)),$kinit);
2395 5         425 for (my $k = $kinit+$kinc; $k <= 1+$log2n; $k += $kinc) {
2396 177         9811 my $r = Mrootint($n,$k);
2397 177         12291 my $c = Mpowint(Madd1int($r),$k);
2398 177 50 33     26358 $best = addint($c,0) if $c < $best && $c > $n; # OLD_PERL_VERSION
2399             }
2400 5         224 $best;
2401             }
2402             sub _prev_perfect_power {
2403 8     8   155 my($n, $only_oddpowers) = @_;
2404 8 50       34 croak "_ppp must have positive n" if $n < 0;
2405              
2406 8 50       1577 return 0 + ($n>1) - ($n==0) if $n <= 4;
2407 8 0       1505 return $only_oddpowers ? 1 : 4 if $n <= 8;
    50          
2408              
2409 8         1483 my $log2n = Mlogint($n,2);
2410 8 100       32 my $kinit = $only_oddpowers ? 3 : 2;
2411 8 100       23 my $kinc = $only_oddpowers ? 2 : 1;
2412              
2413 8         16 my $best = 8;
2414 8         28 for (my $k = $kinit; $k <= $log2n; $k += $kinc) {
2415 425         54603 my $r = Mrootint($n,$k);
2416 425 50       1419 if ($r > 1) {
2417 425         4887 my $c = Mpowint($r,$k);
2418 425 100       11092 $c = Mpowint(Msub1int($r),$k) if $c >= $n;
2419 425 100 66     71660 $best = addint($c,0) if $c > $best && $c < $n; # OLD_PERL_VERSION
2420             }
2421             }
2422 8         422 $best;
2423             }
2424              
2425             sub next_perfect_power {
2426 4     4 0 361 my($n) = @_;
2427 4         30 validate_integer($n);
2428              
2429 4 50 66     24 return 0 + ($n>=0) - ($n<-1) if $n < 1 && $n >= -4;
2430              
2431 4 100       466 return Mnegint( _prev_perfect_power( Mnegint($n), 1 ) ) if $n < 0;
2432 3         25 _next_perfect_power($n, 0);
2433             }
2434              
2435             sub prev_perfect_power {
2436 9     9 0 956 my($n) = @_;
2437 9         67 validate_integer($n);
2438              
2439 9 50 66     307 return 0 + ($n>1) - ($n==0) if $n <= 4 && $n >= 0;
2440              
2441 9 100       2957 return Mnegint( _next_perfect_power( Mnegint($n), 1 ) ) if $n < 0;
2442 7         1368 _prev_perfect_power($n, 0);
2443             }
2444              
2445              
2446             sub nth_perfect_power_approx {
2447 3     3 0 11 my($n) = @_;
2448 3         10 validate_integer_nonneg($n);
2449 3 50       19 return (undef,1,4,8,9,16,25,27)[$n] if $n < 8;
2450              
2451             # See https://www.emis.de/journals/JIS/VOL15/Jakimczuk/jak29.pdf
2452             # See https://www.researchgate.net/publication/268998744_Sums_of_perfect_powers
2453              
2454             # This is more accurate and about 200x faster than using BigFloat.
2455 3 50 66     14 if ($n > 2**32 && $Math::Prime::Util::_GMPfunc{"powreal"}) {
2456 0         0 *Gaddreal = \&Math::Prime::Util::GMP::addreal;
2457 0         0 *Gmulreal = \&Math::Prime::Util::GMP::mulreal;
2458 0         0 *Gpowreal = \&Math::Prime::Util::GMP::powreal;
2459 0         0 my $d = 2 * length($n) + 2;
2460 0         0 my $pp = Gmulreal($n,$n,$d);
2461 0         0 $pp = Gaddreal($pp, Gmulreal(13/3 ,Gpowreal($n, 4/3 ,$d),$d),$d);
2462 0         0 $pp = Gaddreal($pp, Gmulreal(32/15,Gpowreal($n,16/15,$d),$d),$d);
2463 0         0 $pp = Gaddreal($pp, Gmulreal(-2 ,Gpowreal($n, 5/3 ,$d),$d),$d);
2464 0         0 $pp = Gaddreal($pp, Gmulreal(-2 ,Gpowreal($n, 7/5 ,$d),$d),$d);
2465 0         0 $pp = Gaddreal($pp, Gmulreal(-2 ,Gpowreal($n, 9/7 ,$d),$d),$d);
2466 0         0 $pp = Gaddreal($pp, Gmulreal( 2 ,Gpowreal($n,12/10,$d),$d),$d);
2467 0         0 $pp = Gaddreal($pp, Gmulreal(-2 ,Gpowreal($n,13/11,$d),$d),$d);
2468 0         0 $pp = Gaddreal($pp, Gmulreal(-2 ,Gpowreal($n,15/13,$d),$d),$d);
2469 0         0 $pp = Gaddreal($pp, Gmulreal( 2 ,Gpowreal($n,16/14,$d),$d),$d);
2470 0         0 $pp = Gaddreal($pp, Gmulreal( 2 ,Gpowreal($n,17/15,$d),$d),$d);
2471 0         0 $pp = Gaddreal($pp, Gmulreal(-0.48,Gpowreal($n,19/17,$d),$d),$d);
2472 0         0 $pp = Gaddreal($pp, -1.5,$d);
2473 0         0 $pp =~ s/\..*//;
2474 0         0 return Mtoint("$pp");
2475             }
2476              
2477             # Without this upgrade, it will return non-integers.
2478 3 100       16 $n = _upgrade_to_float($n) if $n > 2**32;
2479              
2480 3 100       208 if (!ref($n)) {
2481 2         17 my $pp = $n*$n + (13/3)*$n**(4/3) + (32/15)*$n**(16/15);
2482 2         6 $pp += -2*$n**( 5/ 3) + -2*$n**( 7/ 5);
2483 2         7 $pp += -2*$n**( 9/ 7) + 2*$n**(12/10);
2484 2         5 $pp += -2*$n**(13/11) + -2*$n**(15/13);
2485 2         8 $pp += 2*$n**(16/14) + 2*$n**(17/15);
2486 2         5 $pp -= 0.48*$n**(19/17);
2487 2         20 return Mtoint($pp - 1.5);
2488             }
2489              
2490             # Taking roots is very expensive with Math::BigFloat, so minimize.
2491 1         6 my $n143 = $n->copy->broot(143);
2492 1         250375 my $n105 = $n->copy->broot(105);
2493              
2494 1         295744 my $n15 = $n105->copy->bpow(7);
2495 1         3272 my $n13 = $n143->copy->bpow(11);
2496 1         5287 my $n11 = $n143->copy->bpow(13);
2497 1         6255 my $n7 = $n105->copy->bpow(15);
2498 1         7968 my $n5 = $n105->copy->bpow(21);
2499 1         13049 my $n3 = $n105->copy->bpow(35);
2500              
2501 1         30022 my $pp = $n*$n + (13/3)*$n*$n3 + (32/15)*$n*$n15;
2502 1         6775 $pp += -2*$n*$n3**2 + -2*$n*$n5**2;
2503 1         116233 $pp += -2*$n*$n7**2 + 2*$n*$n5;
2504 1         23495 $pp += -2*$n*$n11**2 + -2*$n*$n13**2;
2505 1         32104 $pp += 2*$n*$n7 + 2*$n*$n15**2;
2506 1         8184 $pp -= 0.48*$n*$n143**16.82352941176470588; # close to 2/17
2507 1         339603 $pp -= 1.5;
2508 1         2638 $pp = $pp->as_int();
2509 1         841 Mtoint($pp);
2510             }
2511              
2512             sub nth_perfect_power_lower {
2513 1     1 0 3 my($n) = @_;
2514 1         19 validate_integer_nonneg($n);
2515 1 50       6 return (undef,1,4,8,9,16,25,27)[$n] if $n < 8;
2516 1 50 33     9 $n = _upgrade_to_float($n) if ref($n) || $n > 2**32;
2517              
2518 1         7 my $pp = $n*$n + (13/3)*$n**(4/3) + (32/15)*$n**(16/15);
2519 1         4 $pp += -2*$n**( 5/ 3) + -2*$n**( 7/ 5);
2520 1         5 $pp += -2*$n**( 9/ 7) + 2*$n**(12/10);
2521 1         3 $pp += -2*$n**(13/11) + -2*$n**(15/13);
2522 1         13 $pp += 1.5;
2523 1         7 Mtoint($pp);
2524             }
2525             sub nth_perfect_power_upper {
2526 1     1 0 3 my($n) = @_;
2527 1         5 validate_integer_nonneg($n);
2528 1 50       6 return (undef,1,4,8,9,16,25,27)[$n] if $n < 8;
2529 1 50 33     10 $n = _upgrade_to_float($n) if ref($n) || $n > 2**32;
2530              
2531 1         7 my $pp = $n*$n + (13/3)*$n**(4/3) + (32/15)*$n**(16/15);
2532 1         5 $pp += -2*$n**( 5/ 3) + -2*$n**( 7/ 5);
2533 1         5 $pp += -2*$n**( 9/ 7) + 2*$n**(12/10);
2534 1         4 $pp += 2*$n**(16/14);
2535 1         3 $pp -= 3.5;
2536 1         4 Mtoint($pp);
2537             }
2538              
2539             sub nth_perfect_power {
2540 2     2 0 10491 my($n) = @_;
2541 2         9 validate_integer_nonneg($n);
2542 2 50       8 return (undef,1,4,8,9,16,25,27)[$n] if $n < 8;
2543 2         4 my($g,$c,$apn,$gn);
2544              
2545 2         10 $gn = 1;
2546 2         20 $g = $apn = nth_perfect_power_approx($n);
2547 2         11 $c = _perfect_power_count($g);
2548 2   33     40 while ($n != $c && abs($n-$c) > 1000) {
2549 0         0 $g += $apn - nth_perfect_power_approx($c);
2550 0         0 $c = _perfect_power_count($g);
2551 0 0       0 last if $gn++ >= 20;
2552             }
2553 2 100       12 if ($c >= $n) {
2554 1         8 for ($g = Math::Prime::Util::prev_perfect_power($g+1); $c > $n; $c--) {
2555 4         27 $g = Math::Prime::Util::prev_perfect_power($g);
2556             }
2557             } else {
2558 1         6 for ( ; $c < $n; $c++) {
2559 1         8 $g = Math::Prime::Util::next_perfect_power($g);
2560             }
2561             }
2562 2         26 $g;
2563             }
2564              
2565             sub _prime_power_count {
2566 13     13   26 my($n) = @_;
2567 13 50       32 return (0,0,1,2,3,4)[$n] if $n <= 5;
2568             Mvecsum(
2569 13         60 map { Mprime_count( Mrootint($n, $_)) } 1 .. Mlogint($n,2)
  185         404  
2570             );
2571             }
2572             sub prime_power_count {
2573 13     13 0 50 my($lo,$hi) = @_;
2574 13 50       50 if (defined $hi) { validate_integer_nonneg($lo); }
  0         0  
2575 13         52 else { ($lo,$hi) = (2, $lo); }
2576 13         45 validate_integer_nonneg($hi);
2577 13 50 33     72 return 0 if $hi < $lo || $hi == 0;
2578 13 50       50 return _prime_power_count($hi) - (($lo <= 2) ? 0 : _prime_power_count($lo-1));
2579             }
2580             sub prime_power_count_lower {
2581 20     20 0 52 my($n) = @_;
2582 20         90 validate_integer_nonneg($n);
2583 20 50       71 return (0,0,1,2,3,4)[$n] if $n <= 5;
2584             Mvecsum(
2585 20         85 map { Math::Prime::Util::prime_count_lower( Mrootint($n, $_)) } 1 .. Mlogint($n,2)
  455         1282  
2586             );
2587             }
2588             sub prime_power_count_upper {
2589 20     20 0 79 my($n) = @_;
2590 20         76 validate_integer_nonneg($n);
2591 20 50       56 return (0,0,1,2,3,4)[$n] if $n <= 5;
2592             Mvecsum(
2593 20         113 map { Math::Prime::Util::prime_count_upper( Mrootint($n, $_)) } 1 .. Mlogint($n,2)
  455         1260  
2594             );
2595             }
2596             sub prime_power_count_approx {
2597 19     19 0 44 my($n) = @_;
2598 19         55 validate_integer_nonneg($n);
2599 19 50       43 return (0,0,1,2,3,4)[$n] if $n <= 5;
2600             Mvecsum(
2601 19         68 map { Math::Prime::Util::prime_count_approx( Mrootint($n, $_)) } 1 .. Mlogint($n,2)
  432         831  
2602             );
2603             }
2604              
2605             sub _simple_nth_prime_power_upper {
2606 4     4   13 my($n) = @_;
2607 4         18 Mnth_prime_upper($n);
2608             }
2609             sub _simple_nth_prime_power_lower {
2610 4     4   11 my $n = shift;
2611 4 50       26 return nth_prime_lower(int(0.65*$n)) if $n < 90;
2612 4         22 int( 0.98 * Math::Prime::Util::nth_prime_lower($n) - 400 );
2613             }
2614             sub nth_prime_power_lower {
2615 1     1 0 5 my($n) = @_;
2616 1         6 validate_integer_nonneg($n);
2617 1 50       5 return (undef,2,3,4,5,7,8,9)[$n] if $n < 8;
2618 1         5 my($lo,$hi) = (_simple_nth_prime_power_lower($n), _simple_nth_prime_power_upper($n));
2619             _binary_search($n, $lo, $hi,
2620 1     19   11 sub{Math::Prime::Util::prime_power_count_upper(shift)});
  19         80  
2621             }
2622             sub nth_prime_power_upper {
2623 1     1 0 17 my($n) = @_;
2624 1         7 validate_integer_nonneg($n);
2625 1 50       5 return (undef,2,3,4,5,7,8,9)[$n] if $n < 8;
2626 1         6 my($lo,$hi) = (_simple_nth_prime_power_lower($n), _simple_nth_prime_power_upper($n));
2627             1+_binary_search($n, $lo, $hi,
2628 1     19   11 sub{Math::Prime::Util::prime_power_count_lower(shift)});
  19         73  
2629             }
2630             sub nth_prime_power_approx {
2631 1     1 0 16 my($n) = @_;
2632 1         5 validate_integer_nonneg($n);
2633 1 50       6 return (undef,2,3,4,5,7,8,9)[$n] if $n < 8;
2634 1         5 my($lo,$hi) = (_simple_nth_prime_power_lower($n), _simple_nth_prime_power_upper($n));
2635             _binary_search($n, $lo, $hi,
2636 1     18   9 sub{Math::Prime::Util::prime_power_count_approx(shift)});
  18         47  
2637             }
2638             sub nth_prime_power {
2639 1     1 0 721 my($n) = @_;
2640 1         4 validate_integer_nonneg($n);
2641 1 50       4 return (undef,2,3,4,5,7,8,9)[$n] if $n < 8;
2642             # TODO: This is a good candidte for the approx interpolation method
2643 1         4 my($lo,$hi) = (_simple_nth_prime_power_lower($n), _simple_nth_prime_power_upper($n));
2644             1+_binary_search($n, $lo, $hi,
2645 1     11   7 sub{Math::Prime::Util::prime_power_count(shift)});
  11         38  
2646             }
2647              
2648              
2649             sub smooth_count {
2650 710     710 0 1055 my($n, $k) = @_;
2651 710         3344 validate_integer_nonneg($n);
2652 710         1241 validate_integer_nonneg($k);
2653 710 50       1309 return 0 if $n < 1;
2654 710 50       1122 return 1 if $k <= 1;
2655 710 50       1218 return $n if $k >= $n;
2656              
2657 710         1341 my $sum = 1 + Mlogint($n,2);
2658 710 50       3337 if ($k >= 3) {
2659 710         1350 my $n3 = Mdivint($n, 3);
2660 710         1256 while ($n3 > 3) {
2661 1623         2840 $sum += 1 + Mlogint($n3,2);
2662 1623         2605 $n3 = Mdivint($n3, 3);
2663             }
2664 710         926 $sum += $n3;
2665             }
2666 710 50       1268 if ($k >= 5) {
2667 710         1128 my $n5 = Mdivint($n, 5);
2668 710         1220 while ($n5 > 5) {
2669 815         1403 $sum += 1 + Mlogint($n5,2);
2670 815         1284 my $n3 = Mdivint($n5, 3);
2671 815         1562 while ($n3 > 3) {
2672 1247         2029 $sum += 1 + Mlogint($n3,2);
2673 1247         2046 $n3 = Mdivint($n3, 3);
2674             }
2675 815         1032 $sum += $n3;
2676 815         1179 $n5 = Mdivint($n5, 5);
2677             }
2678 710         895 $sum += $n5;
2679             }
2680 710         2092 my $p = 7;
2681 710         1124 while ($p <= $k) {
2682 1663         2353 my $np = Mdivint($n, $p);
2683 1663 100       3227 $sum += ($p >= $np) ? $np : Math::Prime::Util::smooth_count($np, $p);
2684 1663         2772 $p = Mnext_prime($p);
2685             }
2686 710         990 $sum;
2687             }
2688              
2689             sub rough_count {
2690 1     1 0 2 my($n, $k) = @_;
2691 1         5 validate_integer_nonneg($n);
2692 1         2 validate_integer_nonneg($k);
2693 1 50       4 return $n if $k <= 2;
2694 1 50       3 return $n-($n>>1) if $k <= 3;
2695 1         35 Math::Prime::Util::legendre_phi($n, Mprime_count($k-1));
2696             }
2697              
2698              
2699             # Recursive almost primes from Trizen.
2700             sub _genkap {
2701 89     89   251 my($A, $B, $k, $m, $p, $cb) = @_;
2702 89 100       184 if ($k == 1) {
2703             Mforprimes( sub {
2704 37     37   214 $cb->(Mmulint($m, $_));
2705 80         597 }, Mvecmax($p, Mcdivint($A, $m)), Mdivint($B, $m));
2706             } else {
2707 9         30 my $s = Mrootint(Mdivint($B, $m), $k);
2708 9         32 while ($p <= $s) {
2709 154         566 my $t = mulint($m, $p);
2710 154 100       481 _genkap($A, $B, $k-1, $t, $p, $cb)
2711             if Mcdivint($A, $t) <= Mdivint($B, $t); # Faster for tight ranges
2712 154         792 $p = next_prime($p);
2713             }
2714             }
2715             }
2716              
2717             sub _generate_almost_primes {
2718 5     5   15 my($A, $B, $k, $cb) = @_;
2719 5         37 $A = Mvecmax($A, Mpowint(2, $k));
2720 5 50       51 _genkap($A, $B, $k, 1, 2, $cb) if $A <= $B;
2721             }
2722              
2723              
2724             sub almost_primes {
2725 8     8 0 1590 my($k, $low, $high) = @_;
2726 8         44 validate_integer_nonneg($k);
2727 8 100       27 if (defined $high) { validate_integer_nonneg($low); }
  4         34  
2728 4         11 else { ($low,$high) = (1, $low); }
2729 8         181 validate_integer_nonneg($high);
2730              
2731 8 0 0     125 if ($k == 0) { return ($low <= 1 && $high >= 1) ? [1] : [] }
  0 50       0  
2732 8 100       31 if ($k == 1) { return Mprimes($low,$high); }
  1         6  
2733             # Don't call this, we could end up back here
2734             #if ($k == 2) { return Math::Prime::Util::semi_primes($low,$high); }
2735              
2736 7         37 my $minlow = Mpowint(2,$k);
2737 7 100       29 $low = $minlow if $low < $minlow;
2738 7 50       534 return [] if $low > $high;
2739 7         171 my @ap;
2740              
2741 7 100       27 if ($low > 1e9) {
2742             #while ($low <= $high) {
2743             # push @ap, $low if is_almost_prime($k, $low);
2744             # $low = add1int($low);
2745             #}
2746 2 100   5   676 Math::Prime::Util::forfactored(sub { push @ap,$_ if scalar(@_) == $k }, $low, $high);
  5         42  
2747 2         29 return \@ap;
2748             }
2749              
2750 5     37   103 _generate_almost_primes($low, $high, $k, sub { push @ap,$_[0]; });
  37         114  
2751 5         42 Mvecsorti(\@ap);
2752             }
2753              
2754             sub _rec_omega_primes {
2755 2613     2613   7521 my($k, $lo, $hi, $m, $p, $opl) = @_;
2756 2613         6433 my $s = Mrootint(Mdivint($hi, $m), $k);
2757 2613         4416 foreach my $q (@{Mprimes($p, $s)}) {
  2613         6850  
2758 1065 100       4912 next if $m % $q == 0;
2759 367         1186 for (my $v = Mmulint($m, $q); $v <= $hi ; $v = Mmulint($v, $q)) {
2760 2979 100       5841 if ($k == 1) {
2761 5 50       43 push @$opl, $v if $v >= $lo;
2762             } else {
2763 2974 100       5758 _rec_omega_primes($k-1,$lo,$hi,$v,$q,$opl) if Mmulint($v,$q) <= $hi;
2764             }
2765             }
2766             }
2767             }
2768              
2769             sub omega_primes {
2770 5     5 0 1579 my($k, $low, $high) = @_;
2771 5         26 validate_integer_nonneg($k);
2772 5 100       18 if (defined $high) { validate_integer_nonneg($low); }
  1         5  
2773 4         13 else { ($low,$high) = (1, $low); }
2774 5         19 validate_integer_nonneg($high);
2775              
2776 5 0 0     20 if ($k == 0) { return ($low <= 1 && $high >= 1) ? [1] : [] }
  0 50       0  
2777 5 100       18 if ($k == 1) { return Math::Prime::Util::prime_powers($low,$high); }
  1         23  
2778              
2779 4         27 $low = Mvecmax($low, Mpn_primorial($k));
2780 4 50       29 return [] if $low > $high;
2781              
2782 4         12 my $opl = [];
2783              
2784 4 100 33     28 if ($high-$low > 1000000000 || ($k >= 10 && $high-$low > 10000000)) {
      66        
2785             # Recursive method from trizen
2786 1         7 _rec_omega_primes($k, $low, $high, 1, 2, $opl);
2787 1         9 Mvecsorti($opl);
2788             } else {
2789             # Simple iteration
2790 3         9 while ($low <= $high) {
2791 377 100       960 push @$opl, $low if Mprime_omega($low) == $k;
2792 377         1058 $low++;
2793             }
2794             }
2795 4         57 $opl;
2796             }
2797              
2798             sub is_semiprime {
2799 9     9 0 1623 my($n) = @_;
2800 9         43 validate_integer($n);
2801 9 50       39 return 0+($n == 4) if $n < 6;
2802 9 50       395 if ($n > 15) {
2803 9 50 33     356 return 0 if ($n % 4) == 0 || ($n % 6) == 0 || ($n % 9) == 0
      66        
      66        
      66        
      33        
2804             || ($n % 10) == 0 || ($n % 14) == 0 || ($n % 15) == 0;
2805             }
2806 8 0       25 return (Math::Prime::Util::is_prob_prime($n>>1) ? 1 : 0) if ($n % 2) == 0;
    50          
2807 8 50       33 return (Math::Prime::Util::is_prob_prime($n/3) ? 1 : 0) if ($n % 3) == 0;
    100          
2808 6 50       73 return (Math::Prime::Util::is_prob_prime($n/5) ? 1 : 0) if ($n % 5) == 0;
    100          
2809              
2810 5         13 if (0) { # TODO: This is all REALLY slow without GMP
2811             # TODO: Something with GMP. If nothing else, just factor.
2812             {
2813             my @f = trial_factor($n, 4999);
2814             return 0 if @f > 2;
2815             return (_is_prime7($f[1]) ? 1 : 0) if @f == 2;
2816             }
2817             return 0 if _is_prime7($n);
2818             {
2819             my @f = pminus1_factor ($n, 250_000);
2820             return 0 if @f > 2;
2821             return (_is_prime7($f[1]) ? 1 : 0) if @f == 2;
2822             }
2823             {
2824             my @f = pbrent_factor ($n, 128*1024, 3, 1);
2825             return 0 if @f > 2;
2826             return (_is_prime7($f[1]) ? 1 : 0) if @f == 2;
2827             }
2828             }
2829 5 100       27 return (scalar(Mfactor($n)) == 2) ? 1 : 0;
2830             }
2831              
2832             sub is_almost_prime {
2833 32     32 0 212 my($k, $n) = @_;
2834 32         122 validate_integer_nonneg($k);
2835 32         97 validate_integer($n);
2836 32 50       73 return 0 if $n <= 0;
2837              
2838 32 50       92 return 0+($n==1) if $k == 0;
2839 32 100       104 return (Mis_prime($n) ? 1 : 0) if $k == 1;
    100          
2840 28 100       79 return Mis_semiprime($n) if $k == 2;
2841 24 50       107 return 0 if ($n >> $k) == 0;
2842              
2843             # TODO: Optimization here
2844 24         35 if (0) { # This seems to just be slower
2845             while ($k > 0 && !($n % 2)) { $k--; $n >>= 1; }
2846             while ($k > 0 && !($n % 3)) { $k--; $n /= 3; }
2847             while ($k > 0 && !($n % 5)) { $k--; $n /= 5; }
2848             while ($k > 0 && !($n % 7)) { $k--; $n /= 7; }
2849             return 0+($n == 1) if $k == 0;
2850             return (Mis_prime($n) ? 1 : 0) if $k == 1;
2851             return Mis_semiprime($n) if $k == 2;
2852             return 0 if $n < Mpowint(11,$k);
2853             }
2854              
2855 24 100       70 return (scalar(Mfactor($n)) == $k) ? 1 : 0;
2856             }
2857             sub is_chen_prime {
2858 1     1 0 5 my($n) = @_;
2859 1         6 validate_integer($n);
2860 1 50       5 return 0 if $n < 2;
2861 1         5 my $n2 = Maddint($n,2);
2862 1   33     5 return (Mis_prime($n) && (Mis_prime($n2) || Mis_semiprime($n2)));
2863             }
2864             sub next_chen_prime {
2865 1     1 0 4 my($n) = @_;
2866 1         14 validate_integer_nonneg($n);
2867 1         7 $n = Mnext_prime($n);
2868 1         3 while (1) {
2869 2         18 my $n2 = Maddint($n,2);
2870 2 100 66     8 return $n if Mis_prime($n2) || Mis_semiprime($n2);
2871 1         4 $n = Mnext_prime($n2);
2872             }
2873             }
2874              
2875             sub is_omega_prime {
2876 22     22 0 169 my($k, $n) = @_;
2877 22         115 validate_integer_nonneg($k);
2878 22         105 validate_integer($n);
2879 22 50       62 return 0 if $n <= 0;
2880              
2881 22 50       1134 return 0+($n==1) if $k == 0;
2882              
2883 22 100       128 return (Mprime_omega($n) == $k) ? 1 : 0;
2884             }
2885              
2886             sub is_practical {
2887 2     2 0 17 my($n) = @_;
2888 2         10 validate_integer($n);
2889 2 50       7 return 0 if $n <= 0;
2890              
2891 2 50       27 return $n==1?1:0 if $n % 2;
    100          
2892 1 50       7 return 1 if ($n & ($n-1)) == 0;
2893 1 0 33     7 return 0 if ($n % 6) && ($n % 20) && ($n % 28) && ($n % 88) && ($n % 104) && ($n % 16);
      33        
      0        
      0        
      0        
2894              
2895 1         4 my $prod = 1;
2896 1         6 my @pe = Mfactor_exp($n);
2897 1         4 for my $i (1 .. $#pe) {
2898 3         7 my($f,$e) = @{$pe[$i-1]};
  3         27  
2899 3         8 my $fmult = $f + 1;
2900 3 100       10 if ($e >= 2) {
2901 1         2 my $pke = $f;
2902 1         4 for (2 .. $e) {
2903 1         4 $pke = Mmulint($pke, $f);
2904 1         24 $fmult = Maddint($fmult, $pke);
2905             }
2906             }
2907 3         14 $prod = Mmulint($prod, $fmult);
2908 3 50       17 return 0 if $pe[$i]->[0] > (1 + $prod);
2909             }
2910 1         12 1;
2911             }
2912              
2913             sub is_delicate_prime {
2914 3     3 0 25 my($n, $b) = @_;
2915 3         55 validate_integer_nonneg($n);
2916 3 100       15 if (defined $b) {
2917 1         5 validate_integer_nonneg($b);
2918 1 50       6 croak "is_delicate_prime base must be >= 2" if $b < 2;
2919             } else {
2920 2         986 $b = 10;
2921             }
2922              
2923 3 50 66     41 return 0 if $b == 10 && $n < 100; # Easy shown.
2924 3 50 33     264 return 1 if $b == 3 && $n == 2;
2925 3 50       16 return 0 unless Mis_prime($n);
2926              
2927 3 100       14 if ($b == 10) {
2928             # String replacement method. Faster in Perl.
2929 2         30 my $ndigits = length($n);
2930 2         53 for my $d (0 .. $ndigits-1) {
2931 27         493 my $N = "$n";
2932 27         1202 my $dold = substr($N,$d,1);
2933 27         82 for my $dnew (0 .. 9) {
2934 270 100       25078 next if $dnew == $dold;
2935 243 100 100     817 if ($d == 0 && $dnew == 0) { # Leading zeros
2936 2         17 (my $T = substr($N,1)) =~ s/^0*//;
2937 2 50       101 return 0 if Mis_prime($T);
2938             } else {
2939 241         726 substr($N,$d,1) = $dnew;
2940 241 50       19203 return 0 if Mis_prime($N);
2941             }
2942             }
2943             }
2944             } else {
2945             # Using todigitstring is slightly faster for bases < 10, but this is
2946             # decent and works for all 32-bit bases.
2947             # This is faster than Stamm's algorithm (in Perl, for possible bigints).
2948 1         8 my $D = [Mtodigits($n, $b)];
2949 1         6 for my $d (0 .. $#$D) {
2950 5         16 my $dold = $D->[$d];
2951 5         20 for my $dnew (0 .. $b-1) {
2952 80 100       236 next if $dnew == $dold;
2953 75         184 $D->[$d] = $dnew;
2954 75 50       204 return 0 if Mis_prime(Mfromdigits($D,$b));
2955             }
2956 5         19 $D->[$d] = $dold;
2957             }
2958             }
2959 3         36 1;
2960             }
2961              
2962             sub _totpred {
2963 34     34   1834 my($n, $maxd) = @_;
2964 34 100 100     179 return 0 if $maxd <= 1 || Mis_odd($n);
2965 11 100       1320 return 1 if ($n & ($n-1)) == 0;
2966 9         4647 $n >>= 1;
2967 9 100 100     1557 return 1 if $n == 1 || ($n < $maxd && Mis_prime(2*$n+1));
      66        
2968 8         874 for my $d (Mdivisors($n)) {
2969 67 100       1689 last if $d >= $maxd;
2970 63 100       1949 my $p = ($d < (INTMAX >> 2)) ? ($d << 1) + 1 :
2971             Madd1int(Mlshiftint($d));
2972 63 100       2312 next unless Mis_prime($p);
2973 25         103 my $r = Mdivint($n,$d);
2974 25         53 while (1) {
2975 29 100 66     119 return 1 if $r == $p || _totpred($r, $d);
2976 27         435 my($Q,$R) = divrem($r,$p);
2977 27 100       113 last if $R != 0;
2978 4         8 $r = $Q;
2979             }
2980             }
2981 6         209 0;
2982             }
2983             sub is_totient {
2984 5     5 0 1718 my($n) = @_;
2985 5         52 validate_integer($n);
2986 5 50       22 return 0+($n==1) if $n <= 1;
2987 5         737 return _totpred($n,$n);
2988             }
2989              
2990              
2991             sub _moebius_range {
2992 371     371   778 my($lo, $hi) = @_;
2993 371         1005 validate_integer($lo);
2994 371         768 validate_integer($hi);
2995 371 50       773 return () if $hi < $lo;
2996 371 50       1232 return moebius($lo) if $lo == $hi;
2997 371 100       1142 if ($lo < 0) {
2998 2 100       8 if ($hi < 0) {
2999 1         7 return reverse(_moebius_range(-$hi,-$lo));
3000             } else {
3001 1         5 return (reverse(_moebius_range(1,-$lo)), _moebius_range(0,$hi));
3002             }
3003             }
3004 369         601 my @mu;
3005 369 100       921 if ($hi > 2**32) {
3006 2 50       394 ($lo,$hi) = (tobigint($lo),tobigint($hi)) if $hi > 2**49;
3007 2         6 push @mu, moebius($lo++) while $lo <= $hi;
3008 2         509 return @mu;
3009             }
3010 367         935 for (my $i = $lo; $i <= $hi; $i++) { push @mu, 1; }
  17233         22194  
3011 367 100       849 $mu[0] = 0 if $lo == 0;
3012 367         1179 my($p, $sqrtn) = (2, Msqrtint($hi));
3013 367         1205 while ($p <= $sqrtn) {
3014 223         459 my $i = $p * $p;
3015 223 100       463 $i = $i * int($lo/$i) + (($lo % $i) ? $i : 0) if $i < $lo;
    100          
3016 223         473 while ($i <= $hi) {
3017 7150         9632 $mu[$i-$lo] = 0;
3018 7150         11514 $i += $p * $p;
3019             }
3020 223         329 $i = $p;
3021 223 100       495 $i = $i * int($lo/$i) + (($lo % $i) ? $i : 0) if $i < $lo;
    100          
3022 223         470 while ($i <= $hi) {
3023 28475         43082 $mu[$i-$lo] *= -$p;
3024 28475         51778 $i += $p;
3025             }
3026 223         702 $p = Mnext_prime($p);
3027             }
3028 367         834 for (my $i = $lo; $i <= $hi; $i++) {
3029 17233         27011 my $m = $mu[$i-$lo];
3030 17233 100       31704 $m *= -1 if abs($m) != $i;
3031 17233         36989 $mu[$i-$lo] = ($m>0) - ($m<0);
3032             }
3033 367         3500 return @mu;
3034             }
3035              
3036             sub _omertens {
3037 9     9   32 my($n) = @_;
3038             # This is the most basic Deléglise and Rivat algorithm. u = n^1/2
3039             # and no segmenting is done. Their algorithm uses u = n^1/3, breaks
3040             # the summation into two parts, and calculates those in segments. Their
3041             # computation time growth is half of this code.
3042 9 50       34 return $n if $n <= 1;
3043 9         30 my $u = int(sqrt($n));
3044 9         62 my @mu = (0, Mmoebius(1, $u)); # Hold values of mu for 0-u
3045 9         37 my $musum = 0;
3046 9         33 my @M = map { $musum += $_; } @mu; # Hold values of M for 0-u
  238         409  
3047 9         37 my $sum = $M[$u];
3048 9         32 foreach my $m (1 .. $u) {
3049 229 100       615 next if $mu[$m] == 0;
3050 148         231 my $inner_sum = 0;
3051 148         312 my $lower = int($u/$m) + 1;
3052 148         307 my $last_nmk = int($n/($m*$lower));
3053 148         390 my ($denom, $this_k, $next_k) = ($m, 0, int($n/($m*1)));
3054 148         326 for my $nmk (1 .. $last_nmk) {
3055 9754         16264 $denom += $m;
3056 9754         15662 $this_k = int($n/$denom);
3057 9754 100       23763 next if $this_k == $next_k;
3058 3995         7171 ($this_k, $next_k) = ($next_k, $this_k);
3059 3995         16009 $inner_sum += $M[$nmk] * ($this_k - $next_k);
3060             }
3061 148         351 $sum -= $mu[$m] * $inner_sum;
3062             }
3063 9         169 return $sum;
3064             }
3065              
3066             sub _rmertens {
3067 1173     1173   2523 my($n, $Mref, $Href, $size) = @_;
3068 1173 50       2602 return $Mref->[$n] if $n <= $size;
3069 1173 100       4874 return $Href->{$n} if exists $Href->{$n};
3070 304         973 my $s = Msqrtint($n);
3071 304         811 my $ns = int($n/($s+1));
3072              
3073 304         1108 my ($nk, $nk1) = ($n, Mrshiftint($n));
3074 304         890 my $SUM = Msubint(1,Msubint($nk,$nk1));
3075 304         624 my @S;
3076 304         797 foreach my $k (2 .. $ns) {
3077 6524         12513 ($nk, $nk1) = ($nk1, Mdivint($n,$k+1));
3078 6524 100       14080 push @S, ($nk <= $size) ? $Mref->[$nk]
3079             : _rmertens($nk, $Mref, $Href, $size);
3080 6524         12336 push @S, $Mref->[$k] * ($nk - $nk1);
3081             }
3082 304 100       1035 push @S, Mmulint($Mref->[$s], Mdivint($n,$s) - $ns) if $s > $ns;
3083 304         1621 $SUM = Msubint($SUM, Mvecsum(@S));
3084              
3085 304         1882 $Href->{$n} = $SUM;
3086 304         1556 $SUM;
3087             }
3088              
3089             sub mertens {
3090 11     11 0 36 my($n) = @_;
3091 11         56 validate_integer_nonneg($n);
3092              
3093 11 100       105 return _omertens($n) if $n < 20000;
3094              
3095             # Larger size would be faster, but more memory.
3096 2         13 my $size = (Mrootint($n, 3)**2) >> 2;
3097 2 50       10 $size = Msqrtint($n) if $size < Msqrtint($n);
3098              
3099 2         7 my @M = (0);
3100 2         26 push @M, $M[-1] + $_ for Mmoebius(1, $size);
3101              
3102 2         12 my %seen;
3103 2         28 return _rmertens($n, \@M, \%seen, $size);
3104             }
3105              
3106              
3107             sub ramanujan_sum {
3108 1     1 0 5 my($k,$n) = @_;
3109 1         7 validate_integer_nonneg($k);
3110 1         4 validate_integer_nonneg($n);
3111 1 50 33     8 return 0 if $k < 1 || $n < 1;
3112 1         9 my $g = $k / Mgcd($k,$n);
3113 1         8 my $m = Mmoebius($g);
3114 1 50 33     9 return $m if $m == 0 || $k == $g;
3115 1         7 $m * (Mtotient($k) / Mtotient($g));
3116             }
3117              
3118             sub liouville {
3119 4     4 0 4346 my($n) = @_;
3120 4         34 validate_integer_nonneg($n);
3121 4 100       137 return (scalar Mfactor($n)) & 1 ? -1 : 1;
3122             }
3123              
3124             sub sumliouville {
3125 1     1 0 4 my($n) = @_;
3126 1         15 validate_integer_nonneg($n);
3127 1 50       15 return (0,1,0,-1,0,-1,0,-1,-2,-1,0,-1,-2,-3,-2,-1)[$n] if $n < 16;
3128              
3129             # Build the Mertens lookup info once.
3130 1         8 my $sqrtn = Msqrtint($n);
3131 1         36 my $size = (Mrootint($n, 3)**2) >> 2;
3132 1 50       19 $size = $sqrtn if $size < $sqrtn;
3133 1         3 my %seen;
3134 1         4 my @M = (0);
3135 1         8 push @M, $M[-1] + $_ for Mmoebius(1, $size);
3136              
3137             # L(n) = sum[k=1..sqrt(n)](Mertens(n/(k^2)))
3138 1         18 my $L = 0;
3139 1         4 for my $k (1 .. $sqrtn) {
3140             #my $nk = Mdivint($n, Mmulint($k,$k));
3141 53         112 my $nk = int($n/($k*$k));
3142 53 100       167 return Mvecsum($L, $sqrtn, -$k, 1) if $nk == 1;
3143 52 100       175 $L = Maddint($L,($nk <= $size) ? $M[$nk] : _rmertens($nk,\@M,\%seen,$size));
3144             }
3145 0         0 return $L;
3146             }
3147              
3148             # Exponential of Mangoldt function (A014963).
3149             # Return p if n = p^m [p prime, m >= 1], 1 otherwise.
3150             sub exp_mangoldt {
3151 5     5 0 16 my($n) = @_;
3152 5         24 validate_integer_nonneg($n);
3153 5 50       15 return 1 if $n <= 1;
3154 5 100       39 if (Mis_prime_power($n, \my $p)) {
3155 3         40 return $p;
3156             }
3157 2         15 1;
3158             }
3159              
3160             sub carmichael_lambda {
3161 2     2 0 1095 my($n) = @_;
3162 2         11 validate_integer_nonneg($n);
3163 2 50       51 return Mtotient($n) if $n < 8; # = phi(n) for n < 8
3164 2 50       164 return $n >> 2 if ($n & ($n-1)) == 0; # = phi(n)/2 = n/4 for 2^k, k>2
3165              
3166 2         929 my @pe = Mfactor_exp($n);
3167 2 50 33     33 $pe[0]->[1]-- if $pe[0]->[0] == 2 && $pe[0]->[1] > 2;
3168              
3169 2         5 Mlcm( map { Mmulint(Mpowint($_->[0],$_->[1]-1),$_->[0]-1) } @pe );
  14         63  
3170             }
3171              
3172             sub is_cyclic {
3173 2     2 0 7 my($n) = @_;
3174 2         11 validate_integer($n);
3175              
3176 2 50       8 return 0+($n > 0) if $n < 4;
3177 2 50       7 return 0 if ($n % 2) == 0;
3178 2 50 66     23 return 0 if (!($n % 9) || !($n%25) || !($n%49) || !($n%121));
      33        
      33        
3179 1 50 33     41 return 0 if (!($n %21) || !($n%39) || !($n%55) || !($n%57) || !($n%93));
      33        
      33        
      33        
3180              
3181 1 50       10 return 1 if Mgcd($n,Mtotient($n)) == 1;
3182 0         0 0;
3183             }
3184              
3185             sub is_carmichael {
3186 8     8 0 69 my($n) = @_;
3187 8         84 validate_integer($n);
3188 8 50 33     43 return 0 if $n < 561 || ($n % 2) == 0;
3189              
3190             return reftyped($_[0], Math::Prime::Util::GMP::is_carmichael($n))
3191 8 50       2200 if $Math::Prime::Util::_GMPfunc{"is_carmichael"};
3192              
3193             # This works fine, but very slow
3194             # return !is_prime($n) && ($n % carmichael_lambda($n)) == 1;
3195              
3196 8 50 100     59 return 0 if (!($n % 9) || !($n % 25) || !($n%49) || !($n%121));
      66        
      33        
3197              
3198             # Check Korselt's criterion for small divisors
3199 6         3752 my $fn = $n;
3200 6         35 for my $a (5,7,11,13,17,19,23,29,31,37,41,43) {
3201 62 100       14406 if (($fn % $a) == 0) {
3202 17 100       6452 return 0 if (($n-1) % ($a-1)) != 0; # Korselt
3203 16         10452 $fn /= $a;
3204 16 50       5589 return 0 unless $fn % $a; # not square free
3205             }
3206             }
3207 5 100       1197 return 0 if Mpowmod(2, $n-1, $n) != 1;
3208              
3209             # After pre-tests, it's reasonably likely $n is a Carmichael number or prime
3210              
3211             # Use probabilistic test if too large to reasonably factor.
3212 4 50       287 if (length($fn) > 50) {
3213 0 0       0 return 0 if Mis_prime($n);
3214 0         0 for my $t (13 .. 150) {
3215 0         0 my $a = $_primes_small[$t];
3216 0         0 my $gcd = Mgcd($a, $fn);
3217 0 0       0 if ($gcd == 1) {
3218 0 0       0 return 0 if Mpowmod($a, $n-1, $n) != 1;
3219             } else {
3220 0 0       0 return 0 if $gcd != $a; # Not square free
3221 0 0       0 return 0 if (($n-1) % ($a-1)) != 0; # factor doesn't divide
3222 0         0 $fn /= $a;
3223             }
3224             }
3225 0         0 return 1;
3226             }
3227              
3228             # Verify with factoring.
3229 4         115 my @pe = Mfactor_exp($n);
3230 4 100       50 return 0 if scalar(@pe) < 3;
3231 3         10 for my $pe (@pe) {
3232 34 50 33     25210 return 0 if $pe->[1] > 1 || (($n-1) % ($pe->[0]-1)) != 0;
3233             }
3234 3         1720 1;
3235             }
3236              
3237             sub is_quasi_carmichael {
3238 3     3 0 10 my($n) = @_;
3239 3         16 validate_integer_nonneg($n);
3240              
3241 3 50       20 return 0 if $n < 35;
3242 3 50 33     38 return 0 if (!($n % 4) || !($n % 9) || !($n % 25) || !($n%49) || !($n%121));
      33        
      33        
      33        
3243              
3244 3         13 my @pe = Mfactor_exp($n);
3245             # Not quasi-Carmichael if prime
3246 3 50       37 return 0 if scalar(@pe) < 2;
3247             # Not quasi-Carmichael if not square free
3248 3         9 for my $pe (@pe) {
3249 7 50       32 return 0 if $pe->[1] > 1;
3250             }
3251 3         6 my @f = map { $_->[0] } @pe;
  7         25  
3252 3         16 my $nbases = 0;
3253 3 100       12 if ($n < 2000) {
3254             # In theory for performance, but mainly keeping to show direct method.
3255 1         5 my $lim = $f[-1];
3256 1         5 $lim = (($n-$lim*$lim) + $lim - 1) / $lim;
3257 1         4 for my $b (1 .. $f[0]-1) {
3258 36         44 my $nb = $n - $b;
3259 36 100   43   118 $nbases++ if Mvecall(sub { $nb % ($_-$b) == 0 }, @f);
  43         172  
3260             }
3261 1 50       5 if (scalar(@f) > 2) {
3262 0         0 for my $b (1 .. $lim-1) {
3263 0         0 my $nb = $n + $b;
3264 0 0   0   0 $nbases++ if Mvecall(sub { $nb % ($_+$b) == 0 }, @f);
  0         0  
3265             }
3266             }
3267             } else {
3268 2         8 my($spf,$lpf) = ($f[0], $f[-1]);
3269 2 100       22 if (scalar(@f) == 2) {
3270 1         10 foreach my $d (Mdivisors($n/$spf - 1)) {
3271 8         15 my $k = $spf - $d;
3272 8         30 my $p = $n - $k;
3273 8 100       18 last if $d >= $spf;
3274 7 50   14   45 $nbases++ if Mvecall(sub { my $j = $_-$k; $j && ($p % $j) == 0 }, @f);
  14 100       18  
  14         78  
3275             }
3276             } else {
3277 1         9 foreach my $d (Mdivisors($lpf * ($n/$lpf - 1))) {
3278 36         85 my $k = $lpf - $d;
3279 36         56 my $p = $n - $k;
3280 36 100 100     121 next if $k == 0 || $k >= $spf;
3281 23 50   27   99 $nbases++ if Mvecall(sub { my $j = $_-$k; $j && ($p % $j) == 0 }, @f);
  27 100       45  
  27         165  
3282             }
3283             }
3284             }
3285 3         67 $nbases;
3286             }
3287              
3288             sub is_pillai {
3289 1     1 0 5 my($p) = @_;
3290 1         5 validate_integer($p);
3291 1 50       5 return 0 if $p < 23;
3292 1 50 33     18 return 0 unless $p % 2 && $p % 3 && $p % 5 && $p % 7;
      33        
      33        
3293              
3294 1         3 my $pm1 = $p-1;
3295 1         4 my $nfac = 5040 % $p;
3296 1         6 for (my $n = 8; $n < $p; $n++) {
3297 11         37 $nfac = Mmulmod($nfac, $n, $p);
3298 11 100 66     62 return $n if $nfac == $pm1 && ($p % $n) != 1;
3299             }
3300 0         0 0;
3301             }
3302              
3303             sub is_fundamental {
3304 4     4 0 36 my($n) = @_;
3305 4         45 validate_integer($n);
3306 4         16 my $neg = ($n < 0);
3307 4 100       664 $n = -$n if $neg;
3308 4         203 my $r = $n & 15;
3309 4 50       1200 if ($r) {
3310 4         110 my $r4 = $r & 3;
3311 4 100       902 if (!$neg) {
3312 2 50       35 return (($r == 4) ? 0 : Mis_square_free($n >> 2)) if $r4 == 0;
    100          
3313 1 50       241 return Mis_square_free($n) if $r4 == 1;
3314             } else {
3315 2 50       21 return (($r == 12) ? 0 : Mis_square_free($n >> 2)) if $r4 == 0;
    100          
3316 1 50       235 return Mis_square_free($n) if $r4 == 3;
3317             }
3318             }
3319 0         0 0;
3320             }
3321              
3322             my @_ds_overflow = # We'll use BigInt math if the input is larger than this.
3323             (~0 > 4294967295)
3324             ? (124, 3000000000000000000, 3000000000, 2487240, 64260, 7026)
3325             : ( 50, 845404560, 52560, 1548, 252, 84);
3326             sub divisor_sum {
3327 930     930 0 80227 my($n, $k) = @_;
3328 930         2421 validate_integer_nonneg($n);
3329 930 50       2495 return 0 if $n == 0;
3330              
3331 930 100 100     5409 if (defined $k && ref($k) eq 'CODE') {
3332 916         1370 my $sum = $n-$n;
3333 916         1741 my $refn = ref($n);
3334 916         4020 foreach my $d (Mdivisors($n)) {
3335 3571 100       24305 $sum += $k->( $refn ? $refn->new("$d") : $d );
3336             }
3337 916         10565 return $sum;
3338             }
3339 14 50       43 return 1 if $n == 1;
3340              
3341 14 50 66     1001 croak "Second argument must be a code ref or number"
3342             unless !defined $k || validate_integer_nonneg($k);
3343 14 100       244 $k = 1 if !defined $k;
3344              
3345             return reftyped($_[0], Math::Prime::Util::GMP::sigma($n, $k))
3346 14 50       53 if $Math::Prime::Util::_GMPfunc{"sigma"};
3347              
3348 14         68 my @factors = Mfactor_exp($n);
3349              
3350 14 100       63 return Mvecprod(map { $_->[1]+1 } @factors) if $k == 0;
  102         324  
3351              
3352 11         32 my @prod;
3353              
3354 11 100       30 if ($k == 1) {
3355 4         11 foreach my $f (@factors) {
3356 49         109 my ($p, $e) = @$f;
3357 49 100 66     104 if ($e == 1) {
    100          
3358 38         79 push @prod, $p+1;
3359             } elsif ($e == 2 && $p < 65536) {
3360 5         12 push @prod, ($p+1) + $p * $p;
3361             } else {
3362 6         10 push @prod, Mvecsum($p+1, map { Mpowint($p,$_) } 2..$e);
  90         118  
3363             }
3364             }
3365             } else {
3366 7         17 foreach my $f (@factors) {
3367 51         81 my ($p, $e) = @$f;
3368 51         105 my $pk = Mpowint($p,$k);
3369 51 50       130 if ($e == 1) {
3370 51         129 push @prod, Madd1int($pk);
3371             } else {
3372 0         0 push @prod, Mvecsum(Madd1int($pk), map { Mpowint($pk,$_) } 2..$e);
  0         0  
3373             }
3374             }
3375             }
3376 11 50       33 return $prod[0] if @prod == 1;
3377 11 100 100     42 if ($k == 1 && $n < 845404560) { # divisor_sum(n) < 2^32
3378 2         14 my $r = 1;
3379 2         7 $r *= $_ for @prod;
3380 2         14 return $r;
3381             }
3382 9 50       468 return Mmulint($prod[0],$prod[1]) if @prod == 2;
3383 9         252 Mvecprod(@prod);
3384             }
3385              
3386             #############################################################################
3387             # Lehmer prime count
3388             #
3389             #my @_s0 = (0);
3390             #my @_s1 = (0,1);
3391             #my @_s2 = (0,1,1,1,1,2);
3392             #my @_s3 = (0,1,1,1,1,1,1,2,2,2,2,3,3,4,4,4,4,5,5,6,6,6,6,7,7,7,7,7,7,8);
3393             #my @_s4 = (0,1,1,1,1,1,1,1,1,1,1,2,2,3,3,3,3,4,4,5,5,5,5,6,6,6,6,6,6,7,7,8,8,8,8,8,8,9,9,9,9,10,10,11,11,11,11,12,12,12,12,12,12,13,13,13,13,13,13,14,14,15,15,15,15,15,15,16,16,16,16,17,17,18,18,18,18,18,18,19,19,19,19,20,20,20,20,20,20,21,21,21,21,21,21,21,21,22,22,22,22,23,23,24,24,24,24,25,25,26,26,26,26,27,27,27,27,27,27,27,27,28,28,28,28,28,28,29,29,29,29,30,30,30,30,30,30,31,31,32,32,32,32,33,33,33,33,33,33,34,34,35,35,35,35,35,35,36,36,36,36,36,36,37,37,37,37,38,38,39,39,39,39,40,40,40,40,40,40,41,41,42,42,42,42,42,42,43,43,43,43,44,44,45,45,45,45,46,46,47,47,47,47,47,47,47,47,47,47,48);
3394             my(@_s3,@_s4);
3395             my @_pred5 = (1,0,1,2,3,4,5,0,1,2,3,0,1,0,1,2,3,0,1,0,1,2,3,0,1,2,3,4,5,0);
3396              
3397             sub _tablephi {
3398 942     942   1239 my($x, $a) = @_;
3399 942 50       2454 if ($a == 0) { return $x; }
  0 50       0  
    50          
    100          
    100          
    100          
3400 0         0 elsif ($a == 1) { return $x-int($x/2); }
3401 0         0 elsif ($a == 2) { return $x-int($x/2) - int($x/3) + int($x/6); }
3402 4         38 elsif ($a == 3) { return 8 * int($x / 30) + $_s3[$x % 30]; }
3403 4         28 elsif ($a == 4) { return 48 * int($x / 210) + $_s4[$x % 210]; }
3404 2         13 elsif ($a == 5) { my $xp = int($x/11);
3405 2         26 return ( (48 * int($x / 210) + $_s4[$x % 210]) -
3406             (48 * int($xp / 210) + $_s4[$xp % 210]) ); }
3407 932         1572 else { my ($xp,$x2) = (int($x/11),int($x/13));
3408 932         1202 my $x2p = int($x2/11);
3409 932         3213 return ( (48 * int($x / 210) + $_s4[$x % 210]) -
3410             (48 * int($xp / 210) + $_s4[$xp % 210]) -
3411             (48 * int($x2 / 210) + $_s4[$x2 % 210]) +
3412             (48 * int($x2p / 210) + $_s4[$x2p % 210]) ); }
3413             }
3414              
3415             sub legendre_phi {
3416 29     29 0 100 my ($x, $a, $primes) = @_;
3417 29         131 validate_integer_nonneg($x);
3418 29         96 validate_integer_nonneg($a);
3419 29 100       137 if ($#_s3 == -1) {
3420 2         12 @_s3 = (0,1,1,1,1,1,1,2,2,2,2,3,3,4,4,4,4,5,5,6,6,6,6,7,7,7,7,7,7,8);
3421 2         42 @_s4 = (0,1,1,1,1,1,1,1,1,1,1,2,2,3,3,3,3,4,4,5,5,5,5,6,6,6,6,6,6,7,7,8,8,8,8,8,8,9,9,9,9,10,10,11,11,11,11,12,12,12,12,12,12,13,13,13,13,13,13,14,14,15,15,15,15,15,15,16,16,16,16,17,17,18,18,18,18,18,18,19,19,19,19,20,20,20,20,20,20,21,21,21,21,21,21,21,21,22,22,22,22,23,23,24,24,24,24,25,25,26,26,26,26,27,27,27,27,27,27,27,27,28,28,28,28,28,28,29,29,29,29,30,30,30,30,30,30,31,31,32,32,32,32,33,33,33,33,33,33,34,34,35,35,35,35,35,35,36,36,36,36,36,36,37,37,37,37,38,38,39,39,39,39,40,40,40,40,40,40,41,41,42,42,42,42,42,42,43,43,43,43,44,44,45,45,45,45,46,46,47,47,47,47,47,47,47,47,47,47,48);
3422             }
3423 29 100       186 return _tablephi($x,$a) if $a <= 6;
3424 15 100       81 $primes = Mprimes(Mnth_prime_upper($a+1)) unless defined $primes;
3425 15 0       99 return ($x > 0 ? 1 : 0) if $x < $primes->[$a];
    50          
3426              
3427 15         56 my $sum = 0;
3428 15         97 my %vals = ( $x => 1 );
3429 15         64 while ($a > 6) {
3430 83         148 my $primea = $primes->[$a-1];
3431 83         141 my %newvals;
3432 83         254 while (my($v,$c) = each %vals) {
3433 2016         2679 my $sval = int($v / $primea);
3434 2016         2382 $sval -= $_pred5[$sval % 30]; # Reduce sval to one with same phi.
3435 2016 100       2516 if ($sval < $primea) {
3436 777         1534 $sum -= $c;
3437             } else {
3438 1239         3493 $newvals{$sval} -= $c;
3439             }
3440             }
3441             # merge newvals into vals
3442 83         234 while (my($v,$c) = each %newvals) {
3443 1086         1570 $vals{$v} += $c;
3444 1086 50       2540 delete $vals{$v} if $vals{$v} == 0;
3445             }
3446 83         269 $a--;
3447             }
3448 15         61 while (my($v,$c) = each %vals) {
3449 928         1359 $sum += $c * _tablephi($v, $a);
3450             }
3451 15         382 return $sum;
3452             }
3453              
3454             sub _sieve_prime_count {
3455 1677     1677   3206 my($high) = @_;
3456 1677 100       2986 return (0,0,1,2,2,3,3)[$high] if $high < 7;
3457 1673 100       3250 $high-- unless ($high % 2);
3458 1673         2122 return 1 + ${_sieve_erat($high)} =~ tr/0//;
  1673         2908  
3459             }
3460              
3461             sub _count_with_sieve {
3462 9223     9223   14925 my ($sref, $low, $high) = @_;
3463 9223 100       16033 ($low, $high) = (2, $low) if !defined $high;
3464 9223         11378 my $count = 0;
3465 9223 100       12782 if ($low < 3) { $low = 3; $count++; }
  5884         6449  
  5884         6467  
3466 3339         4411 else { $low |= 1; }
3467 9223 100       14264 $high-- unless ($high % 2);
3468 9223 50       13577 return $count if $low > $high;
3469 9223         11378 my $sbeg = $low >> 1;
3470 9223         10732 my $send = $high >> 1;
3471              
3472 9223 100 66     22902 if ( !defined $sref || $send >= length($$sref) ) {
3473             # outside our range, so call the segment siever.
3474 597         1571 my $seg_ref = _sieve_segment($low, $high);
3475 597         3198 return $count + $$seg_ref =~ tr/0//;
3476             }
3477 8626         20571 return $count + substr($$sref, $sbeg, $send-$sbeg+1) =~ tr/0//;
3478             }
3479              
3480             sub _lehmer_pi {
3481 100     100   2088 my($x) = @_;
3482 100 100       323 return _sieve_prime_count($x) if $x < 1_000;
3483              
3484 27         313 my $z = Msqrtint($x);
3485 27         95 my $a = _lehmer_pi(Msqrtint($z));
3486 27         92 my $b = _lehmer_pi($z);
3487 27         212 my $c = _lehmer_pi(Mrootint($x,3));
3488              
3489             # Generate at least b primes.
3490 27 50       348 my $bth_prime_upper = ($b <= 10) ? 29 : int("$b"*(log("$b")+log(log("$b")))) + 1;
3491 27         246 my $primes = Mprimes( $bth_prime_upper );
3492              
3493 27         307 my $sum = Mmulint(Mvecsum($b,$a,-2),Mvecsum($b,-$a,1)) >> 1;
3494 27         192 $sum += legendre_phi($x, $a, $primes);
3495              
3496             # Get a big sieve for our primecounts. The C code compromises with either
3497             # b*10 or x^3/5, as that cuts out all the inner loop sieves and about half
3498             # of the big outer loop counts.
3499             # Our sieve count isn't nearly as optimized here, so error on the side of
3500             # more primes. This uses a lot more memory but saves a lot of time.
3501 27         183 my $sref = _sieve_erat( Mdivint(Mdivint($x,$primes->[$a]),5) );
3502              
3503 27         100 my ($lastw, $lastwpc) = (0,0);
3504 27         511 foreach my $i (reverse $a+1 .. $b) {
3505 3366         6294 my $w = int($x / $primes->[$i-1]);
3506 3366         5576 $lastwpc += _count_with_sieve($sref,$lastw+1, $w);
3507 3366         4770 $lastw = $w;
3508 3366         4397 $sum -= $lastwpc;
3509             #$sum -= _count_with_sieve($sref,$w);
3510 3366 100       6187 if ($i <= $c) {
3511 299         1201 my $bi = _count_with_sieve($sref,int(sqrt($w)+0.5));
3512 299         1075 foreach my $j ($i .. $bi) {
3513 5558         12976 $sum = $sum - _count_with_sieve($sref,int($w / $primes->[$j-1])) + $j - 1;
3514             }
3515             }
3516             }
3517 27         472 $sum;
3518             }
3519             #############################################################################
3520              
3521              
3522             sub prime_count {
3523 2559     2559 0 32988 my($low,$high) = @_;
3524 2559 100       4729 if (defined $high) { validate_integer_nonneg($low); }
  13         71  
3525 2546         5712 else { ($low,$high) = (2, $low); }
3526 2559         6698 validate_integer_nonneg($high);
3527              
3528 2559 100 100     8942 return 0 if $high < 2 || $low > $high;
3529              
3530             return reftyped($high, Math::Prime::Util::GMP::prime_count($low,$high))
3531 2557 0 0     6193 if $Math::Prime::Util::_GMPfunc{"prime_count"}
      33        
3532             && (ref($high) eq 'Math::BigInt' || ($high-$low) < int($low/1_000_000));
3533              
3534 2557         3846 my $count = 0;
3535 2557 100 66     10627 $count++ if ($low <= 2) && ($high >= 2); # Count 2
3536 2557 100       5571 $low = 3 if $low < 3;
3537 2557 100       5386 $low++ if ($low % 2) == 0; # Make low go to odd number.
3538 2557 100       5782 $high-- if ($high % 2) == 0; # Make high go to odd number.
3539 2557 100       6020 return $count if $low > $high;
3540              
3541 2382 100 66     14360 if ( ref($low) eq 'Math::BigInt' || ref($high) eq 'Math::BigInt'
      100        
      66        
3542             || ($high-$low) < 10
3543             || ($high-$low) < int($low/100_000_000_000) ) {
3544             # Trial primes seems best. Needs some tuning.
3545 763         3660 my $curprime = Mnext_prime($low-1);
3546 763         2313 while ($curprime <= $high) {
3547 1612         2490 $count++;
3548 1612         3075 $curprime = Mnext_prime($curprime);
3549             }
3550 763         2498 return $count;
3551             }
3552              
3553             # TODO: Needs tuning
3554 1619 100       3326 if ($high > 50_000) {
3555 15 100       87 if ( ($high / ($high-$low+1)) < 100 ) {
3556 10         49 $count += _lehmer_pi($high);
3557 10 100       68 $count -= ($low == 3) ? 1 : _lehmer_pi($low-1);
3558 10         121 return $count;
3559             }
3560             }
3561              
3562 1609 100       4218 return (_sieve_prime_count($high) - 1 + $count) if $low == 3;
3563              
3564 7         37 my $sieveref = _sieve_segment($low,$high);
3565 7         44 $count += $$sieveref =~ tr/0//;
3566 7         117 return $count;
3567             }
3568              
3569              
3570             sub nth_prime {
3571 37     37 0 18087 my($n) = @_;
3572 37         264 validate_integer_nonneg($n);
3573              
3574 37 100       403 return undef if $n <= 0; ## no critic qw(ProhibitExplicitReturnUndef)
3575 36 100       2378 return $_primes_small[$n] if $n <= 0+$#_primes_small;
3576              
3577 8 50 33     104 $n = _upgrade_to_float($n) if ref($n) || $n > MPU_MAXPRIMEIDX || $n > 2**45;
      33        
3578              
3579 8         19 my $prime = 0;
3580 8         18 my $count = 1;
3581 8         19 my $start = 3;
3582              
3583 8         90 my $logn = log($n);
3584 8         25 my $loglogn = log($logn);
3585 8 50       52 my $nth_prime_upper = ($n <= 10) ? 29 : int($n*($logn + $loglogn)) + 1;
3586 8 100       33 if ($nth_prime_upper > 100000) {
3587             # Use fast Lehmer prime count combined with lower bound to get close.
3588 4         35 my $nth_prime_lower = int($n * ($logn + $loglogn - 1.0 + (($loglogn-2.10)/$logn)));
3589 4 100       22 $nth_prime_lower-- unless $nth_prime_lower % 2;
3590 4         28 $count = _lehmer_pi($nth_prime_lower);
3591 4         20 $start = $nth_prime_lower + 2;
3592             }
3593              
3594             {
3595             # Make sure incr is an even number.
3596 8 100       19 my $incr = ($n < 1000) ? 1000 : ($n < 10000) ? 10000 : 100000;
  8 50       55  
3597 8         16 my $sieveref;
3598 8         21 while (1) {
3599 20         159 $sieveref = _sieve_segment($start, $start+$incr);
3600 20         398 my $segcount = $$sieveref =~ tr/0//;
3601 20 100       147 last if ($count + $segcount) >= $n;
3602 12         48 $count += $segcount;
3603 12         33 $start += $incr+2;
3604             }
3605             # Our count is somewhere in this segment. Need to look for it.
3606 8         24 $prime = $start - 2;
3607 8         32 while ($count < $n) {
3608 15786         21408 $prime += 2;
3609 15786 100       30894 $count++ if !substr($$sieveref, ($prime-$start)>>1, 1);
3610             }
3611             }
3612 8         9751 $prime;
3613             }
3614              
3615             # The nth prime will be less or equal to this number
3616             sub nth_prime_upper {
3617 34     34 0 142 my($n) = @_;
3618 34         103 validate_integer_nonneg($n);
3619              
3620 34 50       96 return undef if $n <= 0; ## no critic qw(ProhibitExplicitReturnUndef)
3621 34 100       163 return $_primes_small[$n] if $n <= 0+$#_primes_small;
3622              
3623 29 50 33     193 $n = _upgrade_to_float($n) if ref($n) || $n > MPU_MAXPRIMEIDX || $n > 2**45;
      33        
3624              
3625 29         91 my $flogn = log($n);
3626 29         55 my $flog2n = log($flogn); # Note distinction between log_2(n) and log^2(n)
3627              
3628 29         76 my $upper;
3629 29 50       154 if ($n >= 46254381) { # Axler 2017 Corollary 1.2
    50          
    100          
    50          
    100          
    50          
3630 0         0 $upper = $n * ( $flogn + $flog2n-1.0 + (($flog2n-2.00)/$flogn) - (($flog2n*$flog2n - 6*$flog2n + 10.667)/(2*$flogn*$flogn)) );
3631             } elsif ($n >= 8009824) { # Axler 2013 page viii Korollar G
3632 0         0 $upper = $n * ( $flogn + $flog2n-1.0 + (($flog2n-2.00)/$flogn) - (($flog2n*$flog2n - 6*$flog2n + 10.273)/(2*$flogn*$flogn)) );
3633             } elsif ($n >= 688383) { # Dusart 2010 page 2
3634 4         13 $upper = $n * ( $flogn + $flog2n - 1.0 + (($flog2n-2.00)/$flogn) );
3635             } elsif ($n >= 178974) { # Dusart 2010 page 7
3636 0         0 $upper = $n * ( $flogn + $flog2n - 1.0 + (($flog2n-1.95)/$flogn) );
3637             } elsif ($n >= 39017) { # Dusart 1999 page 14
3638 2         7 $upper = $n * ( $flogn + $flog2n - 0.9484 );
3639             } elsif ($n >= 6) { # Modified Robin 1983, for 6-39016 only
3640 23         70 $upper = $n * ( $flogn + 0.6000 * $flog2n );
3641             } else {
3642 0         0 $upper = $n * ( $flogn + $flog2n );
3643             }
3644              
3645 29         106 Mtoint($upper + 1.0);
3646             }
3647              
3648             # The nth prime will be greater than or equal to this number
3649             sub nth_prime_lower {
3650 29     29 0 509 my($n) = @_;
3651 29         99 validate_integer_nonneg($n);
3652              
3653 29 50       86 return undef if $n <= 0; ## no critic qw(ProhibitExplicitReturnUndef)
3654 29 50       113 return $_primes_small[$n] if $n <= 0+$#_primes_small;
3655              
3656 29 100 66     212 $n = _upgrade_to_float($n) if ref($n) || $n > MPU_MAXPRIMEIDX || $n > 2**45;
      66        
3657              
3658 29         389 my $flogn = log($n);
3659 29         127005 my $flog2n = log($flogn); # Note distinction between log_2(n) and log^2(n)
3660              
3661             # Dusart 1999 page 14, for all n >= 2
3662             #my $lower = $n * ($flogn + $flog2n - 1.0 + (($flog2n-2.25)/$flogn));
3663             # Dusart 2010 page 2, for all n >= 3
3664             #my $lower = $n * ($flogn + $flog2n - 1.0 + (($flog2n-2.10)/$flogn));
3665             # Axler 2013 page viii Korollar I, for all n >= 2
3666             #my $lower = $n * ($flogn + $flog2n-1.0 + (($flog2n-2.00)/$flogn) - (($flog2n*$flog2n - 6*$flog2n + 11.847)/(2*$flogn*$flogn)) );
3667             # Axler 2017 Corollary 1.4
3668 29         80667 my $lower = $n * ($flogn + $flog2n-1.0 + (($flog2n-2.00)/$flogn) - (($flog2n*$flog2n - 6*$flog2n + 11.508)/(2*$flogn*$flogn)) );
3669              
3670 29         14091 my $plower = Mtoint($lower + 0.999999999);
3671             # We clamp to the max UV representable.
3672 29         87 if (MPU_32BIT) {
3673             $plower = 4294967291 if $n >= 203280221 && $plower < 4294967291;
3674             } else {
3675 29 100 66     94 $plower = 18446744073709551557 if $n >= 425656284035217743 && $plower < 18446744073709551557;
3676             }
3677 29         793 $plower;
3678             }
3679              
3680             sub inverse_li_nv {
3681 2     2 0 7 my($n) = @_;
3682 2         8 $n = 0.0 + "$n";
3683 2         9 my $t = $n * log($n);
3684              
3685             # Iterate Halley's method until error term grows
3686 2         5 my $old_term = MPU_INFINITY;
3687 2         6 for my $iter (1 .. 10000) {
3688 6         27 my $dn = MLi($t) - $n;
3689 6 50       24 $dn = 0.0 + "$dn" if ref($dn);
3690 6         15 my $term = $dn * log($t) / (1.0 + $dn/(2*$t));
3691 6 50       18 last if abs($term) >= abs($old_term);
3692 6         13 $old_term = $term;
3693 6         9 $t -= $term;
3694 6 100       20 last if abs($term) < 1e-6;
3695             }
3696 2         47 $t;
3697             }
3698              
3699             sub inverse_li {
3700 1     1 0 4 my($n) = @_;
3701 1         6 validate_integer_nonneg($n);
3702              
3703 1 50       5 return (0,2,3,5,6,8)[$n] if $n <= 5;
3704 1         21 my $t = Math::Prime::Util::inverse_li_nv(0.0 + "$n");
3705              
3706 1         9 $t = Mtoint($t + 0.5);
3707              
3708             # Make it an exact answer
3709 1 50       19 my $inc = ($n > 4e16) ? 2048 : 128;
3710 1 50       7 if (int(MLi($t-1)) >= $n) {
    50          
3711 0         0 $t -= $inc while int(MLi($t-$inc)) >= $n;
3712 0         0 for ($inc = $inc >> 1; $inc > 0; $inc >>= 1) {
3713 0 0       0 $t -= $inc if int(MLi($t-$inc)) >= $n;
3714             }
3715             } elsif (int(MLi($t)) < $n) {
3716 0         0 $t += $inc while int(MLi($t+$inc-1)) < $n;
3717 0         0 for ($inc = $inc >> 1; $inc > 0; $inc >>= 1) {
3718 0 0       0 $t += $inc if int(MLi($t+$inc-1)) < $n;
3719             }
3720             }
3721              
3722 1         8 $t;
3723             }
3724             sub _inverse_R {
3725             # uncoverable subroutine
3726 0     0   0 my($n) = @_;
3727 0         0 validate_integer_nonneg($n);
3728              
3729 0 0       0 return (0,2,3,5,6,8)[$n] if $n <= 5;
3730 0 0 0     0 $n = _upgrade_to_float($n) if ref($n) || $n > MPU_MAXPRIMEIDX || $n > 2**45;
      0        
3731 0         0 my $t = $n * log($n);
3732              
3733             # Iterate Halley's method until error term grows
3734 0         0 my $old_term = MPU_INFINITY;
3735 0         0 for my $iter (1 .. 10000) {
3736 0         0 my $dn = Math::Prime::Util::RiemannR($t) - $n;
3737 0         0 my $term = $dn * log($t) / (1.0 + $dn/(2*$t));
3738 0 0       0 last if abs($term) >= abs($old_term);
3739 0         0 $old_term = $term;
3740 0         0 $t -= $term;
3741 0 0       0 last if abs($term) < 1e-6;
3742             }
3743 0 0       0 Mtoint( ref($t) ? $t->bceil->bstr : $t+0.99999 );
3744             }
3745              
3746             sub nth_prime_approx {
3747 2     2 0 1490 my($n) = @_;
3748 2         10 validate_integer_nonneg($n);
3749              
3750 2 50       6 return undef if $n <= 0; ## no critic qw(ProhibitExplicitReturnUndef)
3751 2 50       6 return $_primes_small[$n] if $n <= 0+$#_primes_small;
3752              
3753             # Once past 10^12 or so, inverse_li gives better results.
3754 2 50       4 return Math::Prime::Util::inverse_li($n) if $n > 1e12;
3755              
3756 2 50 33     10 $n = _upgrade_to_float($n) if ref($n) || $n >= MPU_MAXPRIMEIDX;
3757              
3758 2         6 my $flogn = log($n);
3759 2         5 my $flog2n = log($flogn);
3760              
3761             # Cipolla 1902:
3762             # m=0 fn * ( flogn + flog2n - 1 );
3763             # m=1 + ((flog2n - 2)/flogn) );
3764             # m=2 - (((flog2n*flog2n) - 6*flog2n + 11) / (2*flogn*flogn))
3765             # + O((flog2n/flogn)^3)
3766             #
3767             # Shown in Dusart 1999 page 12, as well as other sources such as:
3768             # http://www.emis.de/journals/JIPAM/images/153_02_JIPAM/153_02.pdf
3769             # where the main issue you run into is that you're doing polynomial
3770             # interpolation, so it oscillates like crazy with many high-order terms.
3771             # Hence I'm leaving it at m=2.
3772              
3773 2         8 my $approx = $n * ( $flogn + $flog2n - 1
3774             + (($flog2n - 2)/$flogn)
3775             - ((($flog2n*$flog2n) - 6*$flog2n + 11) / (2*$flogn*$flogn))
3776             );
3777              
3778             # Apply a correction to help keep values close.
3779 2         2 my $order = $flog2n/$flogn;
3780 2         4 $order = $order*$order*$order * $n;
3781              
3782 2 50       18 if ($n < 259) { $approx += 10.4 * $order; }
  0 50       0  
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
3783 0         0 elsif ($n < 775) { $approx += 6.3 * $order; }
3784 0         0 elsif ($n < 1271) { $approx += 5.3 * $order; }
3785 0         0 elsif ($n < 2000) { $approx += 4.7 * $order; }
3786 0         0 elsif ($n < 4000) { $approx += 3.9 * $order; }
3787 0         0 elsif ($n < 12000) { $approx += 2.8 * $order; }
3788 0         0 elsif ($n < 150000) { $approx += 1.2 * $order; }
3789 2         3 elsif ($n < 20000000) { $approx += 0.11 * $order; }
3790 0         0 elsif ($n < 100000000) { $approx += 0.008 * $order; }
3791 0         0 elsif ($n < 500000000) { $approx += -0.038 * $order; }
3792 0         0 elsif ($n < 2000000000) { $approx += -0.054 * $order; }
3793 0         0 else { $approx += -0.058 * $order; }
3794             # If we want the asymptotic approximation to be >= actual, use -0.010.
3795              
3796 2         8 Mtoint($approx + 0.5);
3797             }
3798              
3799             #############################################################################
3800              
3801             sub prime_count_approx {
3802 437     437 0 65687 my($x) = @_;
3803 437         931 validate_integer_nonneg($x);
3804             #return (0,0,1,2,2,3,3,4,4,4,4,5,5,6,6,6)[$x] if $x < 16;
3805 437 100       1193 return _tiny_prime_count($x) if $x < $_primes_small[-1];
3806              
3807             # Turn on high precision FP if needed (TODO assumes NV >= double prec)
3808 24 100       1809 $x = _upgrade_to_float($x) if $x > 10000000000000000;
3809 24         1502 my $floatx = ref($x) eq 'Math::BigFloat';
3810 24 50 66     77 $x = "$x" if ref($x) && !$floatx;
3811              
3812             # Method 10^10 %error 10^19 %error
3813             # ----------------- ------------ ------------
3814             # n/(log(n)-1) .22% .058%
3815             # n/(ln(n)-1-1/ln(n)) .032% .0041%
3816             # average bounds .0005% .0000002%
3817             # asymp .0006% .00000004%
3818             # li(n) .0007% .00000004%
3819             # li(n)-li(n^.5)/2 .0004% .00000001%
3820             # R(n) .0004% .00000001%
3821             #
3822             # Also consider: http://trac.sagemath.org/sage_trac/ticket/8135
3823              
3824             # Asymp:
3825             # my $l1 = log($x); my $l2 = $l1*$l1; my $l4 = $l2*$l2;
3826             # my $result = int( $x/$l1 + $x/$l2 + 2*$x/($l2*$l1) + 6*$x/($l4) + 24*$x/($l4*$l1) + 120*$x/($l4*$l2) + 720*$x/($l4*$l2*$l1) + 5040*$x/($l4*$l4) + 40320*$x/($l4*$l4*$l1) + 0.5 );
3827             # my $result = int( (prime_count_upper($x) + prime_count_lower($x)) / 2);
3828             # my $result = int( LogarithmicIntegral($x) );
3829             # my $result = int(LogarithmicIntegral($x) - LogarithmicIntegral(sqrt($x))/2);
3830             # my $result = RiemannR($x) + 0.5;
3831              
3832             # Make sure we get enough accuracy, and also not too much more than needed
3833 24 100       78 $x->accuracy(length($x->copy->as_int->bstr())+2) if $floatx;
3834              
3835 24         2541 my $result;
3836 24 100 66     157 if ($Math::Prime::Util::_GMPfunc{"riemannr"} || !ref($x)) {
3837             # Fast if we have our GMP backend, and ok for native.
3838 20         74 $result = Math::Prime::Util::PP::RiemannR($x);
3839             } else {
3840 4 50       30 $result = $floatx ? Math::BigFloat->bzero : 0;
3841 4 50       306 $result->accuracy($x->accuracy) if $floatx;
3842 4         372 $result += MLi($x);
3843 4         1708 $result -= MLi(sqrt($x))/2;
3844 4 50       8762 my $intx = $floatx ? tobigint($x->bfround(0)) : $x;
3845 4         18 for my $k (3 .. 1000) {
3846 88         88361 my $m = Mmoebius($k);
3847 88 100       262 next unless $m != 0;
3848             # With Math::BigFloat and the Calc backend, FP root is ungodly slow.
3849             # Use integer root instead. For more accuracy (not useful here):
3850             # my $v = Math::BigFloat->new( "" . Mrootint($x->as_int,$k) );
3851             # $v->accuracy(length($v)+5);
3852             # $v = $v - Math::BigFloat->new(($v**$k - $x))->bdiv($k * $v**($k-1));
3853             # my $term = LogarithmicIntegral($v)/$k;
3854 56         298 my $term = MLi(Mrootint($intx,$k)) / $k;
3855 56 100       223 last if $term < .25;
3856 52 100       122 if ($m == 1) { $result += $term; }
  22         111  
3857 30         142 else { $result -= $term; }
3858             }
3859             }
3860              
3861 24         107 Mtoint($result+0.5);
3862             }
3863              
3864             sub prime_count_lower {
3865 470     470 0 9704 my($x) = @_;
3866 470         1323 validate_integer_nonneg($x);
3867              
3868 470 100       2332 return _tiny_prime_count($x) if $x < $_primes_small[-1];
3869              
3870             return reftyped($_[0], Math::Prime::Util::GMP::prime_count_lower($x))
3871 34 50       2297 if $Math::Prime::Util::_GMPfunc{"prime_count_lower"};
3872              
3873 34 100       132 $x = _upgrade_to_float($x) if $x > 10000000000000000;
3874 34         4119 my $floatx = ref($x) eq 'Math::BigFloat';
3875 34 50 66     173 $x = "$x" if ref($x) && !$floatx;
3876              
3877 34         73 my($result,$a);
3878 34         147 my $fl1 = log($x);
3879 34         1376272 my $fl2 = $fl1*$fl1;
3880 34 100       3606 my $one = $floatx ? $x->copy->bone : 1.0;
3881              
3882             # Chebyshev 1*x/logx x >= 17
3883             # Rosser & Schoenfeld x/(logx-1/2) x >= 67
3884             # Dusart 1999 x/logx*(1+1/logx+1.8/logxlogx) x >= 32299
3885             # Dusart 2010 x/logx*(1+1/logx+2.0/logxlogx) x >= 88783
3886             # Axler 2014 (1.2) ""+... x >= 1332450001
3887             # Axler 2014 (1.2) x/(logx-1-1/logx-...) x >= 1332479531
3888             # Büthe 2015 (1.9) li(x)-(sqrtx/logx)*(...) x <= 10^19
3889             # Büthe 2014 Th 2 li(x)-logx*sqrtx/8Pi x > 2657, x <= 1.4 * 10^25
3890             # Johnston 2021 Cor3.3 li(x)-logx*sqrtx/8Pi x > 2657, x <= 1.101 * 10^26
3891              
3892             # Also see Dusart 2018: if RH and x >= 5639,
3893             # |pi(x)-li(x)|<= x * (logx-loglogx)/(8*Pi*sqrtx)
3894             # TODO: evaluate this
3895              
3896 34 50 33     1090 if ($x < 599) { # Decent for small numbers
    100          
    50          
3897 0         0 $result = $x / ($fl1 - 0.7);
3898             } elsif ($x < 52600000) { # Dusart 2010 tweaked
3899 25 50       270 if ($x < 2700) { $a = 0.30; }
  0 50       0  
    100          
    50          
    50          
    50          
    50          
    100          
    100          
3900 0         0 elsif ($x < 5500) { $a = 0.90; }
3901 4         10 elsif ($x < 19400) { $a = 1.30; }
3902 0         0 elsif ($x < 32299) { $a = 1.60; }
3903 0         0 elsif ($x < 88783) { $a = 1.83; }
3904 0         0 elsif ($x < 176000) { $a = 1.99; }
3905 0         0 elsif ($x < 315000) { $a = 2.11; }
3906 1         2 elsif ($x < 1100000) { $a = 2.19; }
3907 1         4 elsif ($x < 4500000) { $a = 2.31; }
3908 19         43 else { $a = 2.35; }
3909 25         71 $result = ($x/$fl1) * ($one + $one/$fl1 + $a/$fl2);
3910             } elsif ($x < 1.1e26 || getconfig()->{'assume_rh'}){
3911             # Büthe 2014/2015
3912 9         15468 my $lix = MLi($x);
3913 9         48 my $sqx = sqrt($x);
3914 9 100       32911 if ($x < 1e19) {
3915 1         5 $result = $lix - ($sqx/$fl1) * (1.94 + 3.88/$fl1 + 27.57/$fl2);
3916             } else {
3917 8 50       5239 if (ref($x) eq 'Math::BigFloat') {
3918 8         40 my $xdigits = _find_big_acc($x);
3919 8         57 $result = $lix - ($fl1*$sqx / (Math::BigFloat->bpi($xdigits)*8));
3920             } else {
3921 0         0 $result = $lix - ($fl1*$sqx / PI_TIMES_8);
3922             }
3923             }
3924             } else { # Axler 2014 1.4
3925 0         0 my($fl3,$fl4) = ($fl2*$fl1,$fl2*$fl2);
3926 0         0 my($fl5,$fl6) = ($fl4*$fl1,$fl4*$fl2);
3927 0         0 $result = $x / ($fl1 - $one - $one/$fl1 - 2.65/$fl2 - 13.35/$fl3 - 70.3/$fl4 - 455.6275/$fl5 - 3404.4225/$fl6);
3928             }
3929             # This will truncate bigfloat or floats to native int or bigint class.
3930 34         35836 Mtoint($result);
3931             }
3932              
3933             sub prime_count_upper {
3934 474     474 0 2330 my($x) = @_;
3935 474         1223 validate_integer_nonneg($x);
3936              
3937             # Give an exact answer for what we have in our little table.
3938 474 100       1844 return _tiny_prime_count($x) if $x < $_primes_small[-1];
3939              
3940             return reftyped($_[0], Math::Prime::Util::GMP::prime_count_upper($x))
3941 35 50       2075 if $Math::Prime::Util::_GMPfunc{"prime_count_upper"};
3942              
3943 35 100       147 $x = _upgrade_to_float($x) if $x > 10000000000000000;
3944 35         3315 my $floatx = ref($x) eq 'Math::BigFloat';
3945 35 50 66     193 $x = "$x" if ref($x) && !$floatx;
3946              
3947             # Chebyshev: 1.25506*x/logx x >= 17
3948             # Rosser & Schoenfeld: x/(logx-3/2) x >= 67
3949             # Panaitopol 1999: x/(logx-1.112) x >= 4
3950             # Dusart 1999: x/logx*(1+1/logx+2.51/logxlogx) x >= 355991
3951             # Dusart 2010: x/logx*(1+1/logx+2.334/logxlogx) x >= 2_953_652_287
3952             # Dusart 2018: x/lx*(1+1/lx+2/lxlx+7.59/lxlxlx) x > 1
3953             # Axler 2014: x/(logx-1-1/logx-3.35/logxlogx...) x >= e^3.804
3954             # Büthe 2014 7.4 Schoenfeld bounds hold to x <= 1.4e25
3955             # Axler 2017 Prop 2.2 Schoenfeld bounds hold to x <= 5.5e25
3956             # Johnston 2021 Cor 3.3 Schoenfeld bounds hold to x <= 1.0e26
3957             # Skewes li(x) x < 1e14
3958              
3959             # TODO: Also look at these from Dusart (2018) [paywalled].
3960             # 1 If RH and x >= 5639, |pi(x)-li(x)|<= x * (logx-loglogx)/(8*Pi*sqrtx)
3961             # 2 pi(x) <= li(x) for all 2 <= x <= 10^20
3962             # 3 [li(x) - 2sqrt(x)/log(x)] <= pi(x) for 1090877 <= x <= 10^20
3963             #
3964             # See https://arxiv.org/pdf/2404.17165 page 9 for Mossinghoff and Trudgian.
3965             # Page 26 also points out the Dusart 2018 improvement to Schoenfeld.
3966             # https://math.colgate.edu/~integers/y34/y34.pdf
3967             # Axler 2022:
3968             # https://arxiv.org/pdf/2203.05917
3969              
3970 35         80 my($result,$a);
3971 35         112 my $fl1 = log($x);
3972 35         1234342 my $fl2 = $fl1 * $fl1;
3973 35 100       3607 my $one = $floatx ? $x->copy->bone : 1.0;
3974              
3975 35 100 33     1114 if ($x < 15900) { # Tweaked Rosser-type
    100          
    50          
    50          
3976 5 50       20 $a = ($x < 1621) ? 1.048 : ($x < 5000) ? 1.071 : 1.098;
    50          
3977 5         13 $result = ($x / ($fl1 - $a)) + 1.0;
3978             } elsif ($x < 821800000) { # Tweaked Dusart 2010
3979 22 50       256 if ($x < 24000) { $a = 2.30; }
  0 50       0  
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
3980 0         0 elsif ($x < 59000) { $a = 2.48; }
3981 0         0 elsif ($x < 350000) { $a = 2.52; }
3982 0         0 elsif ($x < 355991) { $a = 2.54; }
3983 0         0 elsif ($x < 356000) { $a = 2.51; }
3984 2         6 elsif ($x < 3550000) { $a = 2.50; }
3985 0         0 elsif ($x < 3560000) { $a = 2.49; }
3986 0         0 elsif ($x < 5000000) { $a = 2.48; }
3987 0         0 elsif ($x < 8000000) { $a = 2.47; }
3988 0         0 elsif ($x < 13000000) { $a = 2.46; }
3989 19         58 elsif ($x < 18000000) { $a = 2.45; }
3990 0         0 elsif ($x < 31000000) { $a = 2.44; }
3991 0         0 elsif ($x < 41000000) { $a = 2.43; }
3992 0         0 elsif ($x < 48000000) { $a = 2.42; }
3993 0         0 elsif ($x < 119000000) { $a = 2.41; }
3994 0         0 elsif ($x < 182000000) { $a = 2.40; }
3995 0         0 elsif ($x < 192000000) { $a = 2.395; }
3996 0         0 elsif ($x < 213000000) { $a = 2.390; }
3997 0         0 elsif ($x < 271000000) { $a = 2.385; }
3998 0         0 elsif ($x < 322000000) { $a = 2.380; }
3999 0         0 elsif ($x < 400000000) { $a = 2.375; }
4000 1         2 elsif ($x < 510000000) { $a = 2.370; }
4001 0         0 elsif ($x < 682000000) { $a = 2.367; }
4002 0         0 elsif ($x < 2953652287) { $a = 2.362; }
4003 0         0 else { $a = 2.334; } # Dusart 2010, page 2
4004 22         75 $result = ($x/$fl1) * ($one + $one/$fl1 + $a/$fl2) + $one;
4005             } elsif ($x < 1e19) { # Skewes number lower limit
4006 0 0       0 $a = ($x < 110e7) ? 0.032 : ($x < 1001e7) ? 0.027 : ($x < 10126e7) ? 0.021 : 0.0;
    0          
    0          
4007 0         0 $result = MLi($x) - $a * $fl1*sqrt($x)/PI_TIMES_8;
4008             } elsif ($x < 1.1e26 || getconfig()->{'assume_rh'}) {
4009             # Schoenfeld / Büthe 2014 Th 7.4
4010 8         24920 my $lix = MLi($x);
4011 8         50 my $sqx = sqrt($x);
4012 8 50       37401 if (ref($x) eq 'Math::BigFloat') {
4013 8         50 my $xdigits = _find_big_acc($x);
4014 8         51 $result = $lix + ($fl1*$sqx / (Math::BigFloat->bpi($xdigits)*8));
4015             } else {
4016 0         0 $result = $lix + ($fl1*$sqx / PI_TIMES_8);
4017             }
4018             } else { # Axler 2014 1.3
4019 0         0 my($fl3,$fl4) = ($fl2*$fl1,$fl2*$fl2);
4020 0         0 my($fl5,$fl6) = ($fl4*$fl1,$fl4*$fl2);
4021 0         0 $result = $x / ($fl1 - $one - $one/$fl1 - 3.35/$fl2 - 12.65/$fl3 - 71.7/$fl4 - 466.1275/$fl5 - 3489.8225/$fl6);
4022             }
4023             # This will truncate bigfloat or floats to native int or bigint class.
4024 35         37534 Mtoint($result);
4025             }
4026              
4027             sub twin_prime_count {
4028 2     2 0 1419 my($low,$high) = @_;
4029 2 100       9 if (defined $high) { validate_integer_nonneg($low); }
  1         5  
4030 1         3 else { ($low,$high) = (2, $low); }
4031 2         10 validate_integer_nonneg($high);
4032 2         5 my $sum = 0;
4033 2         9 while ($low <= $high) {
4034 2         7 my $seghigh = ($high-$high) + $low + 1e7 - 1;
4035 2 50       6 $seghigh = $high if $seghigh > $high;
4036 2         4 $sum += scalar(@{Math::Prime::Util::twin_primes($low,$seghigh)});
  2         8  
4037 2         12 $low = $seghigh + 1;
4038             }
4039 2         24 $sum;
4040             }
4041             sub _semiprime_count {
4042 15     15   39 my($n) = @_;
4043 15         35 my($sum,$pc) = (0,0);
4044             Mforprimes( sub {
4045 291     291   1098 $sum += Mprime_count(int($n/$_))-$pc++;
4046 15         137 }, Msqrtint($n));
4047 15         140 $sum;
4048             }
4049             sub semiprime_count {
4050 15     15 0 1115 my($lo,$hi) = @_;
4051 15 100       38 if (defined $hi) { validate_integer_nonneg($lo); }
  1         6  
4052 14         58 else { ($lo,$hi) = (2, $lo); }
4053 15         67 validate_integer_nonneg($hi);
4054             # todo: threshold of fast count vs. walk
4055 15 50       67 if (($hi-$lo+1) < $hi / (sqrt($hi)/4)) {
4056 0         0 my $sum = 0;
4057 0         0 while ($lo <= $hi) {
4058 0 0       0 $sum++ if Mis_semiprime($lo);
4059 0         0 $lo++;
4060             }
4061 0         0 return $sum;
4062             }
4063 15 100       80 my $sum = _semiprime_count($hi) - (($lo < 4) ? 0 : semiprime_count($lo-1));
4064 15         60 $sum;
4065             }
4066              
4067             sub _kap_reduce_count { # returns new k and n
4068 351     351   719 my($k, $n) = @_;
4069              
4070 351         1264 my $pow3k = Mpowint(3, $k);
4071 351         2005 while ($n < $pow3k) {
4072 416         16002 $n = Mdivint($n, 2);
4073 416         917 $k--;
4074 416         1390 $pow3k = Mdivint($pow3k, 3);
4075             }
4076 351         2058 ($k, $n);
4077             }
4078             sub _kapc_final { # k = 2
4079 432     432   1028 my($n, $pdiv, $lo) = @_;
4080 432         1138 my($sum, $hi, $pc) = (0, Msqrtint(Mdivint($n,$pdiv)), Mprime_count($lo)-1);
4081 432         1227 my $nlim = int(INTMAX / $pdiv);
4082             Mforprimes( sub {
4083 1617 50   1617   4275 my $npp = ($_<=$nlim) ? int($n/($pdiv*$_)) : Mdivint($n,Mmulint($pdiv,$_));
4084 1617         3159 $sum += Mprime_count($npp)-$pc++;
4085 432         4958 }, $lo, $hi);
4086 432         3087 $sum;
4087             }
4088             sub _kapc_count {
4089 334     334   897 my($n, $pdiv, $lo, $k) = @_;
4090 334 50       676 return _kapc_final($n, $pdiv, $lo) if $k == 2;
4091 334         933 my($sum, $hi) = (0, Mrootint(Mdivint($n,$pdiv),$k));
4092             Mforprimes(
4093 432     432   1222 ($k == 3) ? sub { $sum += _kapc_final($n, Mmulint($pdiv,$_), $_); }
4094 233     233   802 : sub { $sum += _kapc_count($n, Mmulint($pdiv,$_), $_, $k-1); },
4095 334 100       3484 $lo, $hi
4096             );
4097 334         1547 $sum;
4098             }
4099             sub almost_prime_count {
4100 103     103 0 308 my($k,$n) = @_;
4101 103         326 validate_integer_nonneg($k);
4102 103         295 validate_integer_nonneg($n);
4103 103 50       292 return ($n >= 1) if $k == 0;
4104 103         174 my $ok = $k;
4105 103         288 ($k, $n) = _kap_reduce_count($k, $n);
4106 103 50       398 return $n if $k == 0;
4107             # If we reduced parameters, try again if XS might be able to do it.
4108 103 50 66     400 return Math::Prime::Util::almost_prime_count($k,$n) if $ok != $k && !ref($n) && getconfig()->{'xs'};
      66        
4109 103 100       289 return Mprime_count($n) if $k == 1;
4110 102 100       277 return Math::Prime::Util::semiprime_count($n) if $k == 2;
4111 101 50       298 return 0 if ($n >> $k) == 0;
4112              
4113 101         328 _kapc_count($n, 1, 2, $k);
4114             }
4115              
4116             sub _omega_prime_count_rec {
4117 32     32   104 my($k, $n, $m, $p, $s, $j) = @_;
4118 32 100       84 $s = Mrootint(Mdivint($n,$m),$k) unless defined $s;
4119 32 100       77 $j = 1 unless defined $j;
4120 32         58 my $count = 0;
4121              
4122 32 100       90 if ($k == 2) {
4123              
4124 12         33 for (; $p <= $s ; ++$j) {
4125 16         45 my $r = Mnext_prime($p);
4126 16         51 for (my $t = Mmulint($m, $p) ; $t <= $n ; $t = Mmulint($t, $p)) {
4127 27         71 my $w = Mdivint($n, $t);
4128 27 100       69 last if $r > $w;
4129 11         35 $count += Mprime_count($w) - $j;
4130 11         37 for (my $r2 = $r ; $r2 <= $w ; $r2 = Mnext_prime($r2)) {
4131 11         46 my $u = Mvecprod($t, $r2, $r2);
4132 11 50       51 last if $u > $n;
4133 0         0 for (; $u <= $n ; $u = Mmulint($u, $r2)) {
4134 0         0 ++$count;
4135             }
4136             }
4137             }
4138 16         67 $p = $r;
4139             }
4140              
4141             } else {
4142              
4143 20         69 for (; $p <= $s ; ++$j) {
4144 30         101 my $r = Mnext_prime($p);
4145 30         98 for (my $t = Mmulint($m, $p) ; $t <= $n ; $t = Mmulint($t, $p)) {
4146 58         182 my $s = Mrootint(Mdivint($n, $t), $k - 1);
4147 58 100       161 last if $r > $s;
4148 28         109 $count += _omega_prime_count_rec($k-1, $n, $t, $r, $s, $j+1);
4149             }
4150 30         87 $p = $r;
4151             }
4152              
4153             }
4154 32         130 $count;
4155             }
4156             sub omega_prime_count {
4157 5     5 0 26 my($k,$n) = @_;
4158 5         17 validate_integer_nonneg($k);
4159 5         40 validate_integer_nonneg($n);
4160              
4161 5 0       16 return ($n >= 1) ? 1 : 0 if $k == 0;
    50          
4162 5 100       19 return prime_power_count($n) if $k == 1;
4163             # find a simple formula for k=2.
4164              
4165             # Naive method
4166             # my ($sum, $low) = (0, Mpn_primorial($k));
4167             # for (my $i = $low; $i <= $n; $i++) {
4168             # $sum++ if Mprime_omega($i) == $k;
4169             # }
4170             # return $sum;
4171              
4172             # Recursive method from trizen
4173 4         17 return _omega_prime_count_rec($k, $n, 1, 2);
4174             }
4175             sub ramanujan_prime_count {
4176 1     1 0 21 my($low,$high) = @_;
4177 1 50       5 if (defined $high) { validate_integer_nonneg($low); }
  0         0  
4178 1         4 else { ($low,$high) = (2, $low); }
4179 1         4 validate_integer_nonneg($high);
4180 1         2 my $sum = 0;
4181 1         5 while ($low <= $high) {
4182 1         4 my $seghigh = ($high-$high) + $low + 1e9 - 1;
4183 1 50       5 $seghigh = $high if $seghigh > $high;
4184 1         2 $sum += scalar(@{Math::Prime::Util::ramanujan_primes($low,$seghigh)});
  1         5  
4185 1         43 $low = $seghigh + 1;
4186             }
4187 1         41 $sum;
4188             }
4189              
4190             sub twin_prime_count_approx {
4191 41     41 0 116 my($n) = @_;
4192 41         159 validate_integer_nonneg($n);
4193 41 50       105 return twin_prime_count(3,$n) if $n < 2000;
4194             # Remove bigint / bigfloat. Everything here will be done with native NV.
4195 41 100       339 $n = 0.0+"$n" if ref($n);
4196 41         208 my $logn = log($n);
4197 41         171 my $li2 = Math::Prime::Util::ExponentialIntegral($logn) + 2.8853900817779268147198494 - ($n/$logn);
4198              
4199             # Empirical correction factor
4200 41         84 my $fm;
4201 41 50       403 if ($n < 4000) { $fm = 0.2952; }
  0 50       0  
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
4202 0         0 elsif ($n < 8000) { $fm = 0.3151; }
4203 0         0 elsif ($n < 16000) { $fm = 0.3090; }
4204 0         0 elsif ($n < 32000) { $fm = 0.3096; }
4205 0         0 elsif ($n < 64000) { $fm = 0.3100; }
4206 0         0 elsif ($n < 128000) { $fm = 0.3089; }
4207 0         0 elsif ($n < 256000) { $fm = 0.3099; }
4208 0         0 elsif ($n < 600000) { my($x0, $x1, $y0, $y1) = (1e6, 6e5, .3091, .3059);
4209 0         0 $fm = $y0 + ($n - $x0) * ($y1-$y0) / ($x1 - $x0); }
4210 0         0 elsif ($n < 1000000) { my($x0, $x1, $y0, $y1) = (6e5, 1e6, .3062, .3042);
4211 0         0 $fm = $y0 + ($n - $x0) * ($y1-$y0) / ($x1 - $x0); }
4212 0         0 elsif ($n < 4000000) { my($x0, $x1, $y0, $y1) = (1e6, 4e6, .3067, .3041);
4213 0         0 $fm = $y0 + ($n - $x0) * ($y1-$y0) / ($x1 - $x0); }
4214 0         0 elsif ($n < 16000000) { my($x0, $x1, $y0, $y1) = (4e6, 16e6, .3033, .2983);
4215 0         0 $fm = $y0 + ($n - $x0) * ($y1-$y0) / ($x1 - $x0); }
4216 0         0 elsif ($n < 32000000) { my($x0, $x1, $y0, $y1) = (16e6, 32e6, .2980, .2965);
4217 0         0 $fm = $y0 + ($n - $x0) * ($y1-$y0) / ($x1 - $x0); }
4218 41 50       107 $li2 *= $fm * log(12+$logn) if defined $fm;
4219              
4220 41         255 return int(1.32032363169373914785562422 * $li2 + 0.5);
4221             }
4222              
4223             sub semiprime_count_approx {
4224 7     7 0 22 my($n) = @_;
4225 7         32 validate_integer_nonneg($n);
4226 7 50       152 return 0 if $n < 4;
4227 7         573 $n = "$n" + 0.00000001;
4228 7         139 my $l1 = log($n);
4229 7         15 my $l2 = log($l1);
4230             #my $est = $n * $l2 / $l1;
4231             #my $est = $n * ($l2 + 0.302) / $l1;
4232 7         36 my $est = ($n/$l1) * (0.11147910114 + 0.00223801350*$l1 + 0.44233207922*$l2 + 1.65236647896*log($l2));
4233 7         37 Mtoint($est + 0.5);
4234             }
4235              
4236             sub almost_prime_count_approx {
4237 37     37 0 714 my($k,$n) = @_;
4238 37         103 validate_integer_nonneg($k);
4239 37         116 validate_integer_nonneg($n);
4240 37 50       307 return ($n >= 1) if $k == 0;
4241 37 50       76 return Math::Prime::Util::prime_count_approx($n) if $k == 1;
4242 37 100       153 return Math::Prime::Util::semiprime_count_approx($n) if $k == 2;
4243 31 50       63 return 0 if ($n >> $k) == 0;
4244              
4245 31         3701 my $lo = Math::Prime::Util::almost_prime_count_lower($k, $n);
4246 31         102 my $hi = Math::Prime::Util::almost_prime_count_upper($k, $n);
4247              
4248 31 100       78 if ($k == 3) {
4249 4         54 my $x = 0.0 + "$n";
4250 4         129 my $l1 = log($x);
4251 4         12 my $l2 = log($l1);
4252 4         12 my($a,$s) = (1.0,2.0);
4253 4 50       95 if ($x <= 638) { $s = 1.554688; $a = 0.865814; }
  0 50       0  
  0 50       0  
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
4254 0         0 elsif ($x <= 1544) { $s = 1.050000; $a = 0.822256; }
  0         0  
4255 0         0 elsif ($x <= 1927) { $s = 0.625000; $a = 0.791747; }
  0         0  
4256 2         5 elsif ($x <= 486586) { $s = 2.865611; $a = 1.004090; }
  2         4  
4257 0         0 elsif ($x <= 1913680) { $s = 2.790963; $a = 0.999618; }
  0         0  
4258 0         0 elsif ($x <= 22347532) { $s = 2.719238; $a = 0.995635; }
  0         0  
4259 0         0 elsif ($x <= 2.95e8) { $s = 2.584473; $a = 0.988802; }
  0         0  
4260 0         0 elsif ($x <= 4.20e9) { $s = 2.457108; $a = 0.983098; }
  0         0  
4261 0         0 elsif ($x <= 7.07e10) { $s = 2.352818; $a = 0.978931; }
  0         0  
4262 0         0 elsif ($x <= 1.36e12) { $s = 2.269745; $a = 0.975953; }
  0         0  
4263 0         0 elsif ($x <= 4.1e13) { $s = 2.203002; $a = 0.973796; }
  0         0  
4264 0         0 elsif ($x <= 9.2e14) { $s = 2.148463; $a = 0.972213; }
  0         0  
4265 2         6 else { $s = 2.119279; $a = 0.971438; }
  2         5  
4266 4         18 my $est = 0.5*$a*$x*(($l2+0.26153)*($l2+0.26153)) / ($l1+$s) + 0.5;
4267 4 50       26 return $est < $lo ? $lo : $est > $hi ? $hi : Mtoint($est);
    50          
4268             }
4269              
4270             {
4271 27         34 my $mult = 0.5;
  27         37  
4272 27 100 66     112 if ($n < 2**32 && $k < 13) {
    100          
4273 24         29 $mult = 0.9;
4274             } elsif ($k > 11) {
4275 2         473 $mult = 0.20;
4276             } else {
4277 1         2 $mult = 0.76;
4278             }
4279 27 50 33     128 return Mtoint($lo + ($hi - $lo) * $mult + 0.5) unless ref($lo) || ref($hi);
4280              
4281 0         0 my $imult = int($mult * (1<<16));
4282 0         0 my $est = Maddint( Mlshiftint($lo,16), Mmulint(Msubint($hi,$lo),$imult) );
4283 0         0 return Mrshiftint($est,16);
4284             }
4285             }
4286              
4287             sub nth_twin_prime {
4288 1     1 0 3 my($n) = @_;
4289 1 50       5 return undef if $n < 0; ## no critic qw(ProhibitExplicitReturnUndef)
4290 1 50       5 return (undef,3,5,11,17,29,41)[$n] if $n <= 6;
4291              
4292 1         5 my $p = Math::Prime::Util::nth_twin_prime_approx($n+200);
4293 1         7 my $tp = Math::Prime::Util::twin_primes($p);
4294 1         8 while ($n > scalar(@$tp)) {
4295 0         0 $n -= scalar(@$tp);
4296 0         0 $tp = Math::Prime::Util::twin_primes($p+1,$p+1e5);
4297 0         0 $p += 1e5;
4298             }
4299 1         23 return $tp->[$n-1];
4300             }
4301              
4302             sub nth_twin_prime_approx {
4303 2     2 0 8 my($n) = @_;
4304 2         13 validate_integer_nonneg($n);
4305 2 50       7 return nth_twin_prime($n) if $n < 6;
4306 2 50 33     49 $n = _upgrade_to_float($n) if ref($n) || $n > 127e14; # TODO lower for 32-bit
4307 2         11 my $logn = log($n);
4308 2         7 my $nlogn2 = $n * $logn * $logn;
4309              
4310 2 100 66     21 return int(5.158 * $nlogn2/log(9+log($n*$n))) if $n > 59 && $n <= 1092;
4311              
4312 1         4 my $lo = int(0.7 * $nlogn2);
4313 1 50       9 my $hi = int( ($n > 1e16) ? 1.1 * $nlogn2
    50          
4314             : ($n > 480) ? 1.7 * $nlogn2
4315             : 2.3 * $nlogn2 + 3 );
4316              
4317             _binary_search($n, $lo, $hi,
4318 39     39   132 sub{Math::Prime::Util::twin_prime_count_approx(shift)},
4319 1     39   13 sub{ ($_[2]-$_[1])/$_[1] < 1e-15 } );
  39         186  
4320             }
4321              
4322             sub nth_semiprime {
4323 2     2 0 7 my($n) = @_;
4324 2         9 validate_integer_nonneg($n);
4325 2 50       7 return (undef,4,6,9,10,14,15,21,22)[$n] if $n <= 8;
4326 2         14 my $x = "$n" + 0.000000001; # Get rid of bigint so we can safely call log
4327 2         9 my $logx = log($x);
4328 2         6 my $loglogx = log($logx);
4329 2 50       12 my $a = ($n < 1000) ? 1.027 : ($n < 10000) ? 0.995 : 0.966;
    100          
4330 2         6 my $est = $a * $x * $logx / $loglogx;
4331 2 50       39 my $lo = ($n < 20000) ? int(0.97*$est)-1 : int(0.98*$est)-1;
4332 2 50       41 my $hi = ($n < 20000) ? int(1.07*$est)+1 : int(1.02*$est)+1;
4333 2     12   18 1+_binary_search($n,$lo,$hi, sub{Math::Prime::Util::semiprime_count(shift)});
  12         36  
4334             }
4335              
4336             sub nth_semiprime_approx {
4337 1     1 0 4 my($n) = @_;
4338 1         5 validate_integer_nonneg($n);
4339 1 50       4 return (undef,4,6,9,10,14,15,21,22)[$n] if $n <= 8;
4340 1         7 $n = "$n" + 0.00000001;
4341 1         4 my $l1 = log($n);
4342 1         4 my $l2 = log($l1);
4343 1         4 my $est = 0.966 * $n * $l1 / $l2;
4344 1         6 Mtoint($est+0.5);
4345             }
4346              
4347             sub _almost_prime_count_asymptotic {
4348             # uncoverable subroutine
4349 0     0   0 my($k, $n) = @_;
4350 0 0       0 return 0 if ($n >> $k) == 0;
4351 0 0       0 return ($n >= 1) if $k == 0;
4352              
4353 0         0 my $x;
4354 0 0 0     0 if (ref($n) || $n > ~0) {
4355 0         0 $x = _upgrade_to_float($n);
4356             } else {
4357 0         0 $x = 0.0 + "$n";
4358             }
4359 0         0 my $logx = log($x);
4360 0         0 my $loglogx = log($logx);
4361 0         0 my $est = $x / $logx;
4362 0 0       0 my $numk = $k - ( ($k<7) ? 1 : ($k<12) ? 2 : ($k-6)>>2 );
    0          
4363 0         0 $est *= ($loglogx/$_) for 1 .. $numk;
4364 0         0 $est; # Returns FP
4365             }
4366             sub _almost_prime_nth_asymptotic {
4367 14     14   47 my($k, $n) = @_;
4368 14 50 33     72 return 0 if $k == 0 || $n == 0;
4369 14 50       43 return Mpowint(2,$k) if $n == 1;
4370              
4371 14         25 my $x;
4372 14 50 33     82 if (ref($n) || $n > ~0) {
4373 0         0 require Math::BigFloat;
4374 0         0 Math::BigFloat->import();
4375 0         0 $x = Math::BigFloat->new($n);
4376             } else {
4377 14         63 $x = 0.0 + "$n";
4378             }
4379 14         53 my $logx = log($x);
4380 14         29 my $loglogx = log($logx);
4381 14         32 my $est = $x * $logx;
4382 14 0       53 my $numk = $k - ( ($k<7) ? 1 : ($k<12) ? 2 : ($k-6)>>2 );
    50          
4383 14         127 $est *= ($_/$loglogx) for 1 .. $numk;
4384 14         76 $est; # Returns FP
4385             }
4386              
4387             sub almost_prime_count_lower {
4388 83     83 0 928 my($k, $n) = @_;
4389 83         287 validate_integer_nonneg($k);
4390 83         154 validate_integer_nonneg($n);
4391              
4392              
4393 83 50       351 return 0 if ($n >> $k) == 0;
4394 83         3428 ($k, $n) = _kap_reduce_count($k, $n);
4395 83 50       257 return ($n >= 1) if $k == 0;
4396 83 50       146 return Math::Prime::Util::prime_count_lower($n) if $k == 1;
4397              
4398 83         118 my $bound = 0;
4399 83         224 my $x = 0.0 + "$n";
4400 83         354 my $logx = log($x);
4401 83         154 my $loglogx = log($logx);
4402 83         121 my $logplus = $loglogx + 0.26153;
4403              
4404 83         195 my @lower20 = (0,0, 0.8197, 0.8418, 0.5242, 0.5154,0.3053,0.1901,0.1253,0.0892,0.06551,0.05082,0.04101);
4405 83         181 my @lower32 = (0,0, 1.004, 0.7383, 0.6828, 0.5939,0.3594,0.2222,0.1438,0.09754,0.06981,0.05245,0.04151, 0.03461,0.03006,0.02709,0.02553,0.02502,0.02552,0.02697,0.02945);
4406 83         305 my @lower64 = (0,0,1.011,0.8093,0.7484,0.6465,0.3982,0.2463,0.1571,0.1048,0.07363,0.0545,0.0422, 0.0331,0.0270,0.0232,0.0208,0.0194,0.0190,0.0193,0.0203, 0.0222,0.0252,0.0295,0.0356,0.0444,0.0570,0.0753,0.102,0.14,0.20,0.297,0.44,0.68,1.07,1.71,2.8,4.7,8.0,13.89,23.98);
4407             # TODO: These are likely still too high
4408 83         550 my @lower = (0,0,1.011,0.8093,0.7484,0.6465,0.3982,0.2463,0.1571,0.1048,0.07363,0.0545,0.0422, 0.0331,0.0270,
4409             0.0230,0.0200,0.0187,0.018,0.018,0.019,0.020,0.020,0.027,0.032,0.040,0.051,0.068,0.090,0.12,0.18,0.26,0.355);
4410              
4411 83         99 my $multl;
4412 83         186 my $isn64bit = Mrshiftint($n,64) == 0;
4413 83 100       276 if ($n <= 1048575) { $multl = $lower20[$k]; }
  6 100       17  
    100          
4414 74         109 elsif ($n <= 4294967295) { $multl = $lower32[$k]; }
4415 1         3 elsif ($isn64bit) { $multl = $lower64[$k]; }
4416             else {
4417 2         1065 push @lower, 1.5 * $lower[$#lower] until defined $lower[$k];
4418 2         5 $multl = $lower[$k];
4419             }
4420              
4421 83 50       264 if ($k == 2) {
    100          
    100          
4422 0 0       0 if ($x <= 1e12) {
4423 0         0 $bound = $x * ($loglogx + 0.261536) / $logx;
4424             } else {
4425             # Bayless Theorem 5.2
4426 0         0 $bound = ($x * ($loglogx+0.1769)/$logx) * (1 + 0.4232/$logx);
4427 0         0 $multl = 1;
4428             }
4429             } elsif ($k == 3) {
4430             # Kinlaw Theorem 1, using custom multipliers for 64-bit n
4431 5         20 $bound = $x * $loglogx * $loglogx / (2*$logx);
4432 5 50       25 if ($n < 638) {
    50          
    100          
    50          
4433 0         0 $multl = 0.8418;
4434             } elsif ($n < 1927) {
4435 0         0 my $dist = ($x - 638) / (1926 - 638);
4436 0         0 $multl = (1.0-$dist) * 0.8939 + $dist * 0.9233;
4437             } elsif ($n < 500194) {
4438 3         9 my $dist = ($x - 1927) / (500194 - 1927);
4439 3         9 $multl = (1.0-$dist) * 0.9233 + $dist * 1.000;
4440             } elsif ($n <= 3184393786) {
4441 0         0 my $dist = ($x - 500194) / (3184393786 - 500194);
4442 0         0 $multl = (1.0-$dist) * 1.0000 + $dist * 1.039;
4443             } else {
4444 2 50       1996 $multl = $isn64bit ? 1.0004 : 1.0;
4445             }
4446             } elsif ($k == 4) {
4447 72         132 $bound = $x * $logplus*$logplus*$logplus / (6*$logx);
4448 72 50       132 $multl = 0.4999 if !$isn64bit;
4449             } else {
4450 6         16 $bound = $x / $logx;
4451 6         43 $logplus = $loglogx + (log("$k") * log(log("$k")) - 0.504377);
4452 6         41 $bound *= $logplus/$_ for 1 .. $k-1;
4453             }
4454 83         125 $bound *= $multl;
4455 83 50       168 $bound = 1 if $bound < 1; # We would have returned zero earlier
4456 83         168 Mtoint($bound)
4457             }
4458             sub almost_prime_count_upper {
4459 165     165 0 400 my($k, $n) = @_;
4460 165         426 validate_integer_nonneg($k);
4461 165         357 validate_integer_nonneg($n);
4462              
4463 165 50       620 return 0 if ($n >> $k) == 0;
4464 165         4148 ($k, $n) = _kap_reduce_count($k, $n);
4465 165 50       346 return ($n >= 1) if $k == 0;
4466 165 50       339 return Math::Prime::Util::prime_count_upper($n) if $k == 1;
4467              
4468             # In theory we might have reduced k/n to where XS can handle it.
4469             # We should consider handling that, especially for k >= 5.
4470              
4471 165         245 my $bound = 0;
4472 165         401 my $x = 0.0 + "$n";
4473 165         555 my $logx = log($x);
4474 165         319 my $loglogx = log($logx);
4475 165         295 my $logplus = $loglogx + 0.26153;
4476              
4477 165         500 my @upper20 = (0,0, 1.006,0.7385,0.6830,0.5940,0.3596,0.2227,0.1439, 0.09785,0.07016,0.05303,0.04202);
4478 165         485 my @upper32 = (0,0, 1.013,0.8094,0.7485, 0.6467,0.3984,0.2464,0.1572,0.1049,0.07364,0.05452,0.04266, 0.03542,0.03082,0.02798,0.02642,0.02585,0.02615,0.02808,0.03054);
4479 165         776 my @upper64 = (0,0, 1.028, 1.028, 1.3043,
4480             0.72208, 0.46609, 0.29340,0.18571,0.12063,0.0815,0.0575,0.0427,
4481             0.03490, 0.03007, 0.02710, 0.02554, 0.02504, 0.02554, 0.02699, 0.02954,
4482             0.03294, 0.03779, 0.04453, 0.05393, 0.06703, 0.08543, 0.1117, 0.1494,
4483             0.205,0.287,0.410,
4484             0.60,0.90,1.36,2.12,3.35,5.38,8.83,14.75,25.07);
4485              
4486             # TODO: These bounds are likely to not be accurate for large inputs
4487              
4488 165         241 my $multu;
4489 165         546 my $isn64bit = Mrshiftint($n,64) == 0;
4490 165 100       477 if ($n <= 1048575) { $multu = $upper20[$k]; }
  94 100       196  
4491 68         106 elsif ($n <= 4294967295) { $multu = $upper32[$k]; }
4492             else {
4493 3         1054 push @upper64, 2.1 * $upper64[$#upper64] until defined $upper64[$k];
4494 3         8 $multu = $upper64[$k];
4495             }
4496              
4497 165 50       486 if ($k == 2) {
    100          
    100          
4498             # Bayless Corollary 5.1
4499 0         0 $bound = 1.028 * $x * ($loglogx + 0.261536) / $logx;
4500             } elsif ($k == 3) {
4501             # Bayless Theorem 5.3
4502 21         68 $bound = $x * ($logplus * $logplus + 1.055852) / (2*$logx);
4503 21 50 66     102 $multu = 0.8711 if $n > 4294967295 && $isn64bit;
4504             } elsif ($k == 4) {
4505             # Bayless Theorem 5.4 part 1, multu = 1.3043
4506 138         299 $bound = $x * $logplus*$logplus*$logplus / (6*$logx);
4507 138 50       287 if ($x >= 1e12) { # part 2
4508 0         0 $bound += + 0.511977 * $x * (log(log($x/4)) + 0.261536) / $logx;
4509 0         0 $multu = 1.028;
4510             }
4511 138 50       260 if ($isn64bit) {
4512 138 50       252 $multu = 0.780 if $n > 4294967295;
4513 138 50       256 $multu = 0.6921 if $x > 1e12;
4514             }
4515             } else {
4516             # We could use Bayless (2018) Theorem 3.5:
4517             # # First we have Pi_k(x) -- the upper bound for the square free kaps.
4518             # $bound = 1.028 * $x / $logx;
4519             # $bound *= ($logplus/$_) for 1..$k-1;
4520             # # Second, turn into Tau_k(x) using the paragraph before Theorem 5.4.
4521             # my $sigmalim = Msqrtint(Mdivint($n, Mpowint(2,$k-2)));
4522             # my $ix = Math::BigInt->new("$x");
4523             # Mforprimes( sub {
4524             # $bound += almost_prime_count_upper($k-2, Mdivint($ix,Mmulint($_,$_)));
4525             # }, 2, $sigmalim);
4526             # # This is incredibly slow. )
4527             #
4528             # Or use theorem 1 from:
4529             # ErdÅ‘s & Sárközy, "On the number of prime factors of integers", 1980.
4530             #
4531             # Or Hildebrand & Tenenbaum 1988:
4532             # https://www.researchgate.net/publication/38333551_On_the_number_of_prime_factors_of_an_integer
4533             # Section 1 has lots of info. Corollary 2 (page 476) is what we want.
4534              
4535 6         13 $bound = $x / $logx;
4536 6         42 $logplus = $loglogx + (log("$k") * log(log("$k")) - 0.504377);
4537 6         38 $bound *= $logplus/$_ for 1 .. $k-1;
4538             }
4539              
4540 165         838 $bound *= $multu;
4541 165 50       367 $bound = 1 if $bound < 1; # We would have returned zero earlier
4542 165         436 Mtoint($bound + 1)
4543             }
4544              
4545             sub _kap_reduce_nth { # returns reduction amount r
4546 35     35   78 my($k, $n) = @_;
4547 35 50       94 return 0 if $k <= 1;
4548              
4549             # We could calculate new values as needed.
4550 35         401 my @A078843 = (1, 2, 3, 5, 8, 14, 23, 39, 64, 103, 169, 269, 427, 676, 1065, 1669, 2628, 4104, 6414, 10023, 15608, 24281, 37733, 58503, 90616, 140187, 216625, 334527, 516126, 795632, 1225641, 1886570, 2901796, 4460359, 6851532, 10518476, 16138642, 24748319, 37932129, 58110457, 88981343, 136192537, 208364721, 318653143, 487128905, 744398307, 1137129971, 1736461477, 2650785552, 4045250962, 6171386419, 9412197641, 14350773978, 21874583987, 33334053149, 50783701654, 77348521640, 117780873397, 179306456282, 272909472119, 415284741506);
4551 35         80 my $r = 0;
4552 35 100       125 if ($k > $#A078843) {
4553 2 50       6 return 0 if $n >= $A078843[-1];
4554 2         7 $r = $k - $#A078843;
4555             }
4556 35         194 $r++ while $n < $A078843[$k-$r];
4557 35         153 $r;
4558             }
4559             sub _fast_small_nth_almost_prime {
4560 1     1   4 my($k,$n) = @_;
4561 1 50 33     9 croak "Internal kap out of range error" if $n >= 8 || $k < 2;
4562 1 50       4 return (0, 4, 6, 9, 10, 14, 15, 21)[$n] if $k == 2;
4563 1         179 return Mmulint((0, 8, 12, 18, 20, 27, 28, 30)[$n], Mlshiftint(1,$k-3));
4564             }
4565              
4566             sub nth_almost_prime_upper {
4567 2     2 0 6 my($k, $n) = @_;
4568 2 50       8 return undef if $n == 0;
4569 2 0       7 return (($n == 1) ? 1 : 0) if $k == 0;
    50          
4570 2 50       8 return Mnth_prime_upper($n) if $k == 1;
4571 2 50       6 return _fast_small_nth_almost_prime($k,$n) if $n < 8;
4572              
4573 2         41 my $r = _kap_reduce_nth($k,$n);
4574 2 50       8 if ($r > 0) {
4575 0         0 my $nth = Math::Prime::Util::nth_almost_prime_upper($k-$r, $n);
4576 0         0 return Mlshiftint($nth, $r);
4577             }
4578              
4579 2         8 my $lo = Mlshiftint(5,$k); # $k >= 1, $n >= 8
4580 2         7 my $hi = Mtoint(1 + _almost_prime_nth_asymptotic($k, $n));
4581             # We just guessed at hi, so bump it up until it's in range
4582 2         8 my $rhi = almost_prime_count_lower($k, $hi);
4583 2         8 while ($rhi < $n) {
4584 2         7 $lo = Madd1int($hi);
4585 2         16 $hi = Mvecsum($hi, int(1.02 * ("$hi"/"$rhi") * ("$n"-"$rhi")), 100);
4586 2         6 $rhi = almost_prime_count_lower($k, $hi);
4587             }
4588 2         8 while ($lo < $hi) {
4589 46         64 my $mid = $lo + (($hi-$lo) >> 1);
4590 46 100       82 if (almost_prime_count_lower($k,$mid) < $n) { $lo = $mid+1; }
  28         90  
4591 18         44 else { $hi = $mid; }
4592             }
4593 2         13 $lo;
4594             }
4595             sub nth_almost_prime_lower {
4596 12     12 0 40 my($k, $n) = @_;
4597 12 50       44 return undef if $n == 0;
4598 12 0       34 return (($n == 1) ? 1 : 0) if $k == 0;
    50          
4599 12 50       51 return Math::Prime::Util::nth_prime_lower($n) if $k == 1;
4600 12 50       37 return _fast_small_nth_almost_prime($k,$n) if $n < 8;
4601              
4602 12         33 my $r = _kap_reduce_nth($k,$n);
4603 12 50       62 if ($r > 0) {
4604 0         0 my $nth = Math::Prime::Util::nth_almost_prime_lower($k-$r, $n);
4605 0         0 return Mlshiftint($nth, $r);
4606             }
4607              
4608 12         91 my $lo = Mlshiftint(5,$k); # $k >= 1, $n >= 8
4609 12         66 my $hi = Mtoint(1 + _almost_prime_nth_asymptotic($k, $n));
4610             # We just guessed at hi, so bump it up until it's in range
4611 12         86 my $rhi = almost_prime_count_upper($k, $hi);
4612 12         100 while ($rhi < $n) {
4613 2         8 $lo = Madd1int($hi);
4614 2         17 $hi = Mvecsum($hi, int(1.02 * ("$hi"/"$rhi") * ("$n"-"$rhi")), 100);
4615 2         7 $rhi = almost_prime_count_upper($k, $hi);
4616             }
4617 12         79 while ($lo < $hi) {
4618 118         252 my $mid = $lo + (($hi-$lo) >> 1);
4619 118 100       233 if (almost_prime_count_upper($k,$mid) < $n) { $lo = $mid+1; }
  28         113  
4620 90         295 else { $hi = $mid; }
4621             }
4622 12         42 $lo;
4623             }
4624              
4625             sub nth_almost_prime_approx {
4626 3     3 0 15641 my($k, $n) = @_;
4627 3 50       15 return undef if $n == 0;
4628 3 50       10 return Mlshiftint(1,$k) if $n == 1;
4629 3 50       10 return undef if $k == 0; # n==1 already returned
4630 3 50       12 return Math::Prime::Util::nth_prime_approx($n) if $k == 1;
4631 3 50       10 return Math::Prime::Util::nth_semiprime_approx($n) if $k == 2;
4632 3 50       12 return _fast_small_nth_almost_prime($k,$n) if $n < 8;
4633              
4634 3         12 my $r = _kap_reduce_nth($k,$n);
4635 3 100       10 if ($r > 0) {
4636 2         56 my $nth = Math::Prime::Util::nth_almost_prime_approx($k-$r, $n);
4637 2         139 return Mmulint($nth, Mpowint(2,$r));
4638             }
4639              
4640 1         4 my $lo = Math::Prime::Util::nth_almost_prime_lower($k, $n);
4641 1         6 my $hi = Math::Prime::Util::nth_almost_prime_upper($k, $n);
4642              
4643             # TODO: Add interpolation speedup steps
4644              
4645 1         7 while ($lo < $hi) {
4646 22         43 my $mid = $lo + (($hi-$lo) >> 1);
4647 22 100       38 if (almost_prime_count_approx($k,$mid) < $n) { $lo = $mid+1; }
  11         27  
4648 11         22 else { $hi = $mid; }
4649             }
4650 1         20 $lo;
4651             }
4652              
4653             sub _interp_linear {
4654 10     10   39 my($n, $rlo, $rhi, $lo, $hi) = @_;
4655             #return int( ($n-$rlo) * ($hi-$lo) / ($rhi-$rlo) );
4656 10         54 my $num = Mmulint( Msubint($n,$rlo), Msubint($hi,$lo) );
4657 10         38 my $den = Msubint($rhi, $rlo);
4658 10         81 return Mdivint(Maddint($num,$den>>1), $den);
4659             #return divint($num, $den);
4660             }
4661             sub _inverse_interpolate {
4662 10     10   57 my($lo, $hi, $n, $k, $callback) = @_;
4663 10         25 my($mid, $rmid, $rlo, $rhi);
4664              
4665 10         31 $rlo = $callback->($k, $lo);
4666 10 50       38 croak "interp: bad lower bound" if $rlo > $n;
4667 10 50       32 return $lo if $rlo == $n; # If lo wasn't small enough, this could be wrong.
4668              
4669             # We have the exact value (rlo) at lo.
4670             #print "1 $lo $hi ",$hi-$lo,"\n";
4671              
4672 10 50       76 $rhi = $callback->($k, $hi) if $hi != 0;
4673              
4674 10         33 while ($hi == 0) {
4675             # Use lo/rlo to make an estimate
4676              
4677             # Make an estimate of where we will end up
4678 10 50       60 my $estf = ($rlo == 0) ? 1 : Mdivint(Mlshiftint($n,8),$rlo) - 1; # slightly lower
4679 10 50       34 $estf = 1+(1<<8) if $estf <= (1<<8);
4680 10 50       34 $estf = (8<<8) if $estf > (8<<8);
4681 10         41 $mid = Mrshiftint(Mmulint($estf,$lo),8);
4682             # rmid is the exact count at this estimate
4683 10         39 $rmid = $callback->($k, $mid);
4684              
4685             # Either we have a hi value, or we pull in lo and do it again.
4686 10 50       36 if ($rmid >= $n) { $hi = $mid; $rhi = $rmid; }
  10         28  
  10         35  
4687 0         0 else { $lo = $mid; $rlo = $rmid; }
  0         0  
4688             #print "2 $lo $hi ",$hi-$lo,"\n";
4689             }
4690 10 50 33     78 croak "interp bad initial" unless $rlo <= $n && $rhi >= $n;
4691 10 50       44 return $lo if $rlo == $n;
4692 10 0 0     44 return (($rlo==$n || ($rlo<$n && $rhi>$n)) ? $lo : $hi) if $hi-$lo <= 1;
    50          
4693              
4694             # Step 1. Linear interpolation while it centers.
4695              
4696 10 50       85 $mid = ($n == $rhi) ? $hi-1
4697             : Maddint($lo, _interp_linear($n,$rlo,$rhi,$lo,$hi));
4698 10 50       53 if ($mid == $lo) { $mid++; } elsif ($mid == $hi) { $mid--; }
  0 50       0  
  0         0  
4699              
4700 10   33     108 while ($rhi > $n && ($hi-$lo) > 1) {
4701 19 50 33     82 croak "interp: need 3 unique points" unless $lo < $mid && $mid < $hi;
4702             #print "I $lo $hi ",$hi-$lo,"\n";
4703 19         57 $rmid = $callback->($k, $mid);
4704 19 50       59 if ($rmid >= $n) { ($hi,$rhi) = ($mid,$rmid); }
  19         50  
4705 0         0 else { ($lo,$rlo) = ($mid,$rmid); }
4706 19 100       58 last if $rhi == $n;
4707              
4708 9         46 my $num = Mmulint(Msubint($n,$rmid),Msubint($hi,$lo));
4709 9         32 my $den = Msubint($rhi,$rlo);
4710 9         34 $mid = Maddint($mid, Mdivint($num, $den));
4711             # Fairly crude way of pulling in opposite side so we bracket.
4712 9 50       41 if ($mid <= $lo) { $mid = Maddint($lo, Mdivint(Msubint($hi,$lo),100)); }
  0 50       0  
4713 0         0 elsif ($mid >= $hi) { $mid = Msubint($hi, Mdivint(Msubint($hi,$lo),100)); }
4714 9 50       82 if ($mid == $lo) { $mid++; } elsif ($mid == $hi) { $mid--; }
  0 50       0  
  0         0  
4715 9 50 33     86 croak "interp: range error" unless $lo <= $mid && $mid <= $hi;
4716             }
4717              
4718 10 50       33 return $lo if $rlo == $n;
4719 10 0 0     63 return (($rlo==$n || ($rlo<$n && $rhi>$n)) ? $lo : $hi) if $hi-$lo <= 1;
    50          
4720              
4721 10 50 33     60 croak "interp: bad step 1 interpolation" unless $rlo < $n && $rhi == $n;
4722              
4723             # Step 2. Ridder's method until we're very close.
4724              
4725 10 50 33     49 croak "interp: Ridder initial assumption error" unless $rlo<$n && $rhi>=$n;
4726             #print "F $lo $hi ",$hi-$lo,"\n";
4727              
4728 10   66     60 while (($hi-$lo > 8) && ($hi-$lo) > 1) {
4729 10         49 my($x0, $x2, $x1) = ($lo, $hi, Maddint($lo, Msubint($hi,$lo)>>1));
4730 10         37 my($rx1) = $callback->($k, $x1);
4731 10         75 my($fx0, $fx1, $fx2) = (Msubint($rlo,$n), Msubint($rx1,$n), Msubint($rhi,$n)+1);
4732              
4733             # Calculate new point using false position method
4734             #my $pos = (($x1-$x0) * "$fx1") / sqrt( "$fx1"*"$fx1" - "$fx0"*"$fx2" );
4735             #my $x3 = $x1 - int($pos+0.5);
4736             # Rather convoluted so it's all in integer.
4737 10         35 my $num = Mmulint($fx1, Msubint($x1,$x0));
4738 10         35 my $d1 = Msubint(Mmulint($fx1,$fx1),Mmulint($fx0,$fx2));
4739 10         59 my $den = Msqrtint(Mlshiftint($d1,64));
4740 10         63 $num = Mlshiftint($num, 32);
4741 10         57 my $pos = Mdivint(Maddint($num,$den>>1), $den);
4742 10         39 my $x3 = Msubint($x1, $pos);
4743              
4744             # print " Ridder mid = $x1 - $pos = $x3\n";
4745             # print " $lo $x1 $x3 $hi\n";
4746              
4747 10 50 33     77 if ($x3 >= $hi || $x3 <= $lo || $x3 == $x1) {
      33        
4748              
4749             # The new point hasn't given us anything. Just bisect.
4750 0 0       0 if ($rx1 >= $n) { $hi = $x1; $rhi = $rx1; }
  0         0  
  0         0  
4751 0         0 else { $lo = $x1; $rlo = $rx1; }
  0         0  
4752              
4753             } else {
4754              
4755 10         35 my $rx3 = $callback->($k,$x3);
4756 10 50       39 if ($rx1 > $rx3) { ($x1,$x3,$rx1,$rx3) = ($x3,$x1,$rx3,$rx1); }
  0         0  
4757 10 50       53 if ($rx1 >= $n) { $hi = $x1; $rhi = $rx1; }
  0 100       0  
  0         0  
4758 1         2 elsif ($rx3 >= $n) { $lo = $x1; $rlo = $rx1; $hi = $x3; $rhi = $rx3; }
  1         2  
  1         2  
  1         2  
4759 9         20 else { $lo = $x3; $rlo = $rx3; }
  9         50  
4760              
4761             }
4762             #print "R $lo $hi ",$hi-$lo,"\n";
4763 10 50 33     115 croak "interp: Ridder step error" unless $rlo < $n && $rhi >= $n;
4764             }
4765              
4766             # Step 3. Binary search. Invariant: f(lo) < n, f(hi) >= n
4767              
4768 10         39 while ($hi-$lo > 1) {
4769 30         68 $mid = $lo + (($hi-$lo) >> 1);
4770 30         91 $rmid = $callback->($k, $mid);
4771 30 100       108 if ($rmid < $n) { $lo = $mid; }
  11         36  
4772 19         59 else { $hi = $mid; }
4773             #print "B $lo $hi ",$hi-$lo,"\n";
4774             }
4775 10         94 $hi;
4776             }
4777              
4778             sub nth_almost_prime {
4779 21     21 0 58 my($k, $n) = @_;
4780 21 50       74 return undef if $n == 0;
4781 21 50       61 return Mlshiftint(1,$k) if $n == 1;
4782 21 50       80 return undef if $k == 0; # n==1 already returned
4783 21 100       66 return Math::Prime::Util::nth_prime($n) if $k == 1;
4784 20 100       72 return Math::Prime::Util::nth_semiprime($n) if $k == 2;
4785 19 100       70 return _fast_small_nth_almost_prime($k,$n) if $n < 8;
4786              
4787 18         92 my $r = _kap_reduce_nth($k,$n);
4788 18 100       66 if ($r > 0) {
4789 8         44 my $nth = Math::Prime::Util::nth_almost_prime($k-$r, $n);
4790 8         39 return Mmulint($nth, Mpowint(2,$r));
4791             }
4792              
4793 10         52 my $lo = Math::Prime::Util::nth_almost_prime_lower($k, $n);
4794              
4795 10     89   118 return _inverse_interpolate($lo, 0, $n, $k, sub { Math::Prime::Util::almost_prime_count($_[0],$_[1]); });
  89         339  
4796             #my $ncalls = 0;
4797             #my $res = _inverse_interpolate($lo, 0, $n, $k, sub { $ncalls++; Math::Prime::Util::almost_prime_count($_[0],$_[1]); });
4798             #print "ncalls: $ncalls\n";
4799             #return $ncalls;
4800             #return $res;
4801             }
4802              
4803             sub nth_omega_prime {
4804 5     5 0 16 my($k, $n) = @_;
4805 5 50       16 return undef if $n == 0;
4806 5 50       15 return Mpn_primorial($k) if $n == 1;
4807 5 50       18 return undef if $k == 0; # n==1 already returned
4808              
4809             # Very inefficient algorithm.
4810 5         24 my $i = Mpn_primorial($k);
4811 5         29 while (1) {
4812 30         146 $i++ while Mprime_omega($i) != $k;
4813 30 100       128 return $i if --$n == 0;
4814 25         47 $i++;
4815             }
4816             }
4817              
4818             sub nth_ramanujan_prime_upper {
4819 23     23 0 50 my($n) = @_;
4820 23         69 validate_integer_nonneg($n);
4821 23 50       61 return (0,2,11)[$n] if $n <= 2;
4822              
4823 23 50       56 if ($n < 50) {
4824 0 0       0 return Mnth_prime_upper(int(2.6*$n)) if $n <= 20;
4825 0         0 return 33+((310*Mnth_prime_upper(2*$n))>>8);
4826             }
4827              
4828 23         69 my $nth = Mnth_prime_upper(Mmulint($n,3));
4829              
4830 23 100       106 return 115+((727*$nth) >> 10) if $n < 647;
4831              
4832             # TODO: Ideally these would all be adjusted to make smooth transitions.
4833              
4834 2 0       14 my($add,$mul) = $n < 16000 ? ( 271,358)
    0          
    0          
    50          
    50          
4835             : $n < 1200000 ? (9450,350)
4836             : $n < 7000000 ? (5000,349)
4837             : $n < 90000000 ? ( 0,348)
4838             : $n < 3100000000 ? ( 0,347)
4839             : ( 0,346);
4840              
4841 2         8 my $ret = Mrshiftint(Mmulint($mul,$nth),9);
4842 2 50       14 $ret = Maddint($ret,$add) if $add != 0;
4843 2         10 $ret;
4844             }
4845             sub nth_ramanujan_prime_lower {
4846 23     23 0 72 my($n) = @_;
4847 23         68 validate_integer_nonneg($n);
4848 23 50       74 return (0,2,11)[$n] if $n <= 2;
4849 23         70 my $nth = Math::Prime::Util::nth_prime_lower(Mmulint($n,2));
4850 23 100       121 return Mdivint(Mmulint(275,$nth),256) if $n < 10000;
4851 2 50       13 return Mdivint(Mmulint(262,$nth),256) if $n < 1e10;
4852 0         0 $nth;
4853             }
4854             sub nth_ramanujan_prime_approx {
4855 6     6 0 17 my($n) = @_;
4856 6         22 validate_integer_nonneg($n);
4857 6 50       19 return (0,2,11)[$n] if $n <= 2;
4858 6         19 my($lo,$hi) = (nth_ramanujan_prime_lower($n),nth_ramanujan_prime_upper($n));
4859 6         28 $lo + (($hi-$lo)>>1);
4860             }
4861             sub ramanujan_prime_count_upper {
4862 2     2 0 15 my($n) = @_;
4863 2         8 validate_integer_nonneg($n);
4864 2 0       6 return (($n < 2) ? 0 : 1) if $n < 11;
    50          
4865 2         7 my $lo = Mdivint(prime_count_lower($n),3);
4866 2         7 my $hi = Mrshiftint(prime_count_upper($n));
4867             1+_binary_search($n, $lo, $hi,
4868 2     16   18 sub{Math::Prime::Util::nth_ramanujan_prime_lower(shift)});
  16         39  
4869             }
4870             sub ramanujan_prime_count_lower {
4871 2     2 0 4 my($n) = @_;
4872 2         10 validate_integer_nonneg($n);
4873 2 0       6 return (($n < 2) ? 0 : 1) if $n < 11;
    50          
4874 2         9 my $lo = int(prime_count_lower($n) / 3);
4875 2         9 my $hi = prime_count_upper($n) >> 1;
4876             _binary_search($n, $lo, $hi,
4877 2     16   18 sub{Math::Prime::Util::nth_ramanujan_prime_upper(shift)});
  16         45  
4878             }
4879             sub ramanujan_prime_count_approx {
4880 1     1 0 13 my($n) = @_;
4881 1         8 validate_integer_nonneg($n);
4882 1 0       6 return (($n < 2) ? 0 : 1) if $n < 11;
    50          
4883             #$n = _upgrade_to_float($n) if ref($n) || $n > 2e16;
4884 1         6 my $lo = ramanujan_prime_count_lower($n);
4885 1         10 my $hi = ramanujan_prime_count_upper($n);
4886             _binary_search($n, $lo, $hi,
4887 5     5   14 sub{Math::Prime::Util::nth_ramanujan_prime_approx(shift)},
4888 1     5   33 sub{ ($_[2]-$_[1])/$_[1] < 1e-15 } );
  5         25  
4889             }
4890              
4891             sub _sum_primes_n {
4892 3     3   11 my($n) = @_;
4893 3 50       18 return (0,0,2,5,5)[$n] if $n < 5;
4894 3         32 my $r = Msqrtint($n);
4895 3         30 my $r2 = $r + Mdivint($n, $r+1);
4896 3         9 my(@V,@S);
4897 3         12 for my $k (0 .. $r2) {
4898 9184 100       36065 my $v = ($k <= $r) ? $k : Mdivint($n,($r2-$k+1));
4899 9184         15480 $V[$k] = $v;
4900 9184         20508 $S[$k] = Maddint(
4901             Mrshiftint(Mmulint($v, $v-1)),
4902             $v-1);
4903             }
4904 3         15 for my $p (2 .. $r) {
4905 4589 100       12734 next unless $S[$p] > $S[$p-1];
4906 724         1515 my $sp = $S[$p-1];
4907 724         1890 my $p2 = Mmulint($p,$p);
4908 724         11231 for my $v (reverse @V) {
4909 134363 100       283717 last if $v < $p2;
4910 133639         243467 my($a,$b) = ($v,Mdivint($v,$p));
4911 133639 100       298524 $a = $r2 - Mdivint($n,$a) + 1 if $a > $r;
4912 133639 100       262422 $b = $r2 - Mdivint($n,$b) + 1 if $b > $r;
4913 133639         384671 $S[$a] -= Mmulint($p, $S[$b]-$sp);
4914             #$S[$a] = Msubint($S[$a], Mmulint($p, Msubint($S[$b],$sp)));
4915             }
4916             }
4917 3         1733 $S[$r2];
4918             }
4919             sub sum_primes {
4920 3     3 0 15 my($low,$high) = @_;
4921 3 100       21 if (defined $high) { validate_integer_nonneg($low); }
  1         15  
4922 2         8 else { ($low,$high) = (2, $low); }
4923 3         15 validate_integer_nonneg($high);
4924 3         24 my $sum = 0;
4925              
4926 3 50       26 return $sum if $high < $low;
4927              
4928             # It's very possible we're here because they've counted too high. Skip fwd.
4929 3 50 66     31 if ($low <= 2 && $high >= 29505444491) {
4930 0         0 ($low, $sum) = (29505444503, tobigint("18446744087046669523"));
4931             }
4932              
4933 3 50       23 return $sum if $low > $high;
4934              
4935             # Easy, not unreasonable, but seems slower than the windowed sum.
4936             # return _sum_primes_n($high) if $low <= 2;
4937              
4938             # Performance decision, which to use.
4939 3 50 66     65 if ( $high <= ~0 &&
      66        
      66        
4940             $high > (MPU_64BIT ? 2000000 : 320000) &&
4941             ($high-$low) > $high/50 &&
4942             !getconfig()->{'xs'}) {
4943 2         45 my $hsum = _sum_primes_n($high);
4944 2 100       31 my $lsum = ($low <= 2) ? 0 : _sum_primes_n($low - 1);
4945 2         103 return $hsum - $lsum;
4946             }
4947              
4948             # Sum in windows.
4949             # TODO: consider some skipping forward with small tables.
4950 1   33     25 my $xssum = (MPU_64BIT && $high < 6e14 && getconfig()->{'xs'});
4951 1 50 33     10 my $step = ($xssum && $high > 5e13) ? 1_000_000 : 11_000_000;
4952 1         9 Math::Prime::Util::prime_precalc(Msqrtint($high));
4953 1         5 while ($low <= $high) {
4954 1         6 my $next = Maddint($low, $step) - 1;
4955 1 50       7 $next = $high if $next > $high;
4956             $sum = Maddint($sum,
4957             ($xssum) ? Math::Prime::Util::sum_primes($low,$next)
4958 1 50       5 : Mvecsum( @{Mprimes($low,$next)} ));
  1         9  
4959 1 50       35 last if $next == $high;
4960 0         0 $low = Madd1int($next);
4961             }
4962 1         14 $sum;
4963             }
4964              
4965             sub print_primes {
4966 0     0 0 0 my($low,$high,$fd) = @_;
4967 0 0       0 if (defined $high) { validate_integer_nonneg($low); }
  0         0  
4968 0         0 else { ($low,$high) = (2, $low); }
4969 0         0 validate_integer_nonneg($high);
4970              
4971 0 0       0 $fd = fileno(STDOUT) unless defined $fd;
4972 0         0 open(my $fh, ">>&=", $fd); # TODO .... or die
4973              
4974 0 0       0 if ($high >= $low) {
4975 0         0 my $p1 = $low;
4976 0         0 while ($p1 <= $high) {
4977 0         0 my $p2 = $p1 + 15_000_000 - 1;
4978 0 0       0 $p2 = $high if $p2 > $high;
4979 0 0       0 if ($Math::Prime::Util::_GMPfunc{"sieve_primes"}) {
4980 0         0 print $fh "$_\n" for Math::Prime::Util::GMP::sieve_primes($p1,$p2,0);
4981             } else {
4982 0         0 print $fh "$_\n" for @{Mprimes($p1,$p2)};
  0         0  
4983             }
4984 0         0 $p1 = $p2+1;
4985             }
4986             }
4987 0         0 close($fh);
4988             }
4989              
4990              
4991             #############################################################################
4992              
4993             sub _mulmod {
4994 13578     13578   28058 my($x, $y, $n) = @_;
4995 13578 100       77886 return (($x * $y) % $n) if ($x|$y) < MPU_HALFWORD;
4996             #return (($x * $y) % $n) if ($x|$y) < MPU_HALFWORD || $y == 0 || $x < int(~0/$y);
4997 13578         10592 my $r = 0;
4998 13578 50       13889 $x %= $n if $x >= $n;
4999 13578 50       14588 $y %= $n if $y >= $n;
5000 13578 100       15377 ($x,$y) = ($y,$x) if $x < $y;
5001 13578 100       13701 if ($n <= (~0 >> 1)) {
5002 5882         12162 while ($y > 1) {
5003 261173 100       474494 if ($y & 1) { $r += $x; $r -= $n if $r >= $n; }
  126810 100       173384  
  126810         228803  
5004 261173         354140 $y >>= 1;
5005 261173 100       350111 $x += $x; $x -= $n if $x >= $n;
  261173         590102  
5006             }
5007 5882 100       12486 if ($y & 1) { $r += $x; $r -= $n if $r >= $n; }
  5882 50       8585  
  5882         12466  
5008             } else {
5009 7696         2237 while ($y > 1) {
5010 65241 100       123061 if ($y & 1) { $r = $n-$r; $r = ($x >= $r) ? $x-$r : $n-$r+$x; }
  32609 100       46754  
  32609         59974  
5011 65241         90819 $y >>= 1;
5012 65241 100       150376 $x = ($x > ($n - $x)) ? ($x - $n) + $x : $x + $x;
5013             }
5014 7696 100       2600 if ($y & 1) { $r = $n-$r; $r = ($x >= $r) ? $x-$r : $n-$r+$x; }
  1088 50       1600  
  1088         2191  
5015             }
5016 13578         23959 $r;
5017             }
5018             sub _addmod {
5019 3436     3436   6995 my($x, $y, $n) = @_;
5020 3436 50       6714 $x %= $n if $x >= $n;
5021 3436 50       6634 $y %= $n if $y >= $n;
5022 3436 100       7451 if (($n-$x) <= $y) {
5023 1393 100       3671 ($x,$y) = ($y,$x) if $y > $x;
5024 1393         2295 $x -= $n;
5025             }
5026 3436         10543 $x + $y;
5027             }
5028              
5029             # Note that Perl 5.6.2 with largish 64-bit numbers will break. As usual.
5030             sub _native_powmod {
5031 3607     3607   6136 my($n, $power, $m) = @_;
5032 3607         4622 my $t = 1;
5033 3607         4687 $n = $n % $m;
5034 3607         6348 while ($power) {
5035 67036 100       115557 $t = ($t * $n) % $m if ($power & 1);
5036 67036         80146 $power >>= 1;
5037 67036 100       130827 $n = ($n * $n) % $m if $power;
5038             }
5039 3607         7561 $t;
5040             }
5041              
5042             sub _powmod {
5043 83     83   290 my($n, $power, $m) = @_;
5044 83         184 my $t = 1;
5045              
5046 83 50       279 $n %= $m if $n >= $m;
5047 83 50       288 if ($m < MPU_HALFWORD) {
5048 0         0 while ($power) {
5049 0 0       0 $t = ($t * $n) % $m if ($power & 1);
5050 0         0 $power >>= 1;
5051 0 0       0 $n = ($n * $n) % $m if $power;
5052             }
5053             } else {
5054 83         301 while ($power) {
5055 3794 100       9765 $t = _mulmod($t, $n, $m) if ($power & 1);
5056 3794         6181 $power >>= 1;
5057 3794 100       9824 $n = _mulmod($n, $n, $m) if $power;
5058             }
5059             }
5060 83         359 $t;
5061             }
5062              
5063             sub powint {
5064 8688     8688 0 54563 my($a, $b) = @_;
5065 8688         32611 validate_integer($a);
5066 8688         46846 validate_integer($b);
5067             return reftyped($_[0], Math::Prime::Util::GMP::powint($a,$b))
5068 8688 50       29084 if $Math::Prime::Util::_GMPfunc{"powint"};
5069 8688 50       26598 croak "powint: exponent must be >= 0" if $b < 0;
5070              
5071             # Special cases for small a and b
5072 8688 100 100     41754 if ($a >= -1 && $a <= 4) {
5073 1599 0       3346 return ($b == 0) ? 1 : 0 if $a == 0;
    50          
5074 1599 100       3636 return 1 if $a == 1;
5075 1555 0       3209 return ($b % 2) ? -1 : 1 if $a == -1;
    50          
5076 1555 100       3105 if ($a == 2) {
5077 589 100       14518 return ($b < MPU_MAXBITS) ? 1<<$b : Mlshiftint(1,$b);
5078             }
5079 966 100       2091 if ($a == 4) {
5080 151 100       590 return 1 << (2*$b) if $b < MPU_MAXBITS/2;
5081 107 50       7497 return Mlshiftint(1,2*$b) if $b < 4000000000;
5082             }
5083             }
5084              
5085 7904 100       206780 return 1 if $b == 0;
5086 7885 100       18453 return $a if $b == 1;
5087 7855 100       18533 if ($b == 2) {
5088 1462 100       6714 return int("$a")*int("$a") if abs($a) < MPU_HALFWORD;
5089 484         123813 return Mmulint($a,$a);
5090             }
5091              
5092 6393 100 66     40036 if (!ref($a) && !ref($b) && $b < MPU_MAXBITS) {
      100        
5093 3871 100       9033 if ($b == 3) {
5094 723 100       2574 return int($a*$a*$a) if $a <= 99999;
5095 187 100       4088 return Mmulint(int($a*$a), $a) if $a <= 31622776;
5096             } else {
5097             # Check if inside limit of int on 32-bit
5098 3148         10974 my $r = $a ** $b;
5099 3148 100 100     10600 return int($r) if $r < 1000000000000000 && $r > -1000000000000000;
5100             # Try to complete using a single mulint if we can
5101 2629         8222 $r = $a ** (($b+1)>>1);
5102 2629 100 66     10588 if ($r < 1000000000000000 && $r > -1000000000000000) {
5103 1400 100       92385 return Mmulint(int($r), $b&1 ? int($a**($b>>1)) : int($r));
5104             }
5105             }
5106             # Fall through
5107             }
5108              
5109 3886 100       20449 return Mmulint(Mmulint($a,$a),$a) if $b == 3;
5110              
5111 3654         15209 my $r = tobigint($a) ** tobigint($b);
5112 3654 50 33     3697850 return $r <= INTMAX && $r >= INTMIN ? _bigint_to_int($r) : $r;
5113             }
5114              
5115             sub mulint {
5116 206222     206222 0 7175365 my($a, $b) = @_;
5117 206222         587099 validate_integer($a);
5118 206222         876870 validate_integer($b);
5119 206222 100 100     2949859 return 0 if $a == 0 || $b == 0;
5120             return reftyped($_[0], Math::Prime::Util::GMP::mulint($a,$b))
5121 205005 50       8036804 if $Math::Prime::Util::_GMPfunc{"mulint"};
5122              
5123 205005         420677 my $r = $a * $b;
5124              
5125 205005 100       12549269 if (!ref($r)) {
5126 172178 100 100     782794 return $r if $r < INTMAX && $r > INTMIN;
5127 6831         29085 $r = tobigint($a) * $b;
5128             }
5129 39658 100 100     2606005 return $r <= INTMAX && $r >= INTMIN ? _bigint_to_int($r) : $r;
5130             }
5131             sub addint {
5132 53916     53916 0 6426125 my($a, $b) = @_;
5133 53916         245078 validate_integer($a);
5134 53916         2744697 validate_integer($b);
5135             return reftyped($_[0], Math::Prime::Util::GMP::addint($a,$b))
5136 53916 50       2371866 if $Math::Prime::Util::_GMPfunc{"addint"};
5137              
5138 53916         148254 my $r = $a + $b;
5139              
5140 53916 100       7223247 if (!ref($r)) {
5141 21033 100 100     95539 return $r if $r < INTMAX && $r > INTMIN;
5142 85         377 $r = tobigint($a) + $b;
5143             }
5144 32968 100 100     149003 return $r <= INTMAX && $r >= INTMIN ? _bigint_to_int($r) : $r;
5145             }
5146             sub subint {
5147 2913     2913 0 61013 my($a, $b) = @_;
5148 2913         9891 validate_integer($a);
5149 2913         39129 validate_integer($b);
5150             return reftyped($_[0], Math::Prime::Util::GMP::subint($a,$b))
5151 2913 50       13577 if $Math::Prime::Util::_GMPfunc{"subint"};
5152              
5153 2913         6470 my $r = $a - $b;
5154              
5155 2913 100       261501 if (!ref($r)) {
5156 2149 100 100     10660 return $r if $r < INTMAX && $r > INTMIN;
5157 21         86 $r = tobigint($a) - $b;
5158             }
5159 785 100 100     11552 return $r <= INTMAX && $r >= INTMIN ? _bigint_to_int($r) : $r;
5160             }
5161             sub add1int {
5162 1475     1475 0 13160 my($a) = @_;
5163 1475         8663 validate_integer($a);
5164 1475         60638 my $r = $a+1;
5165 1475 100       392132 if (!ref($r)) {
5166 329 100       1277 return $r if $r < INTMAX;
5167 3         11 $r = tobigint($a) + 1;
5168             }
5169 1149 50 33     5297 return $r <= INTMAX && $r >= INTMIN ? _bigint_to_int($r) : $r;
5170             }
5171             sub sub1int {
5172 818     818 0 8184 my($a) = @_;
5173 818         6344 validate_integer($a);
5174 818         30266 my $r = $a-1;
5175 818 100       198412 if (!ref($r)) {
5176 285 50       979 return $r if $r < INTMAX;
5177 0         0 $r = tobigint($a) - 1;
5178             }
5179 533 100 66     2131 return $r <= INTMAX && $r >= INTMIN ? _bigint_to_int($r) : $r;
5180             }
5181              
5182             # For division / modulo, see:
5183             #
5184             # https://www.researchgate.net/publication/234829884_The_Euclidean_definition_of_the_functions_div_and_mod
5185             #
5186             # https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf
5187              
5188             sub _tquotient {
5189 21103     21103   45657 my($a,$b) = @_;
5190 21103 100       55323 return $a if $b == 1;
5191              
5192 21070 100 100     1807228 $a = tobigint($a) if ($a >= SINTMAX || $a <= INTMIN) && !ref($a);
      100        
5193 21070 100 66     4905889 $b = tobigint($b) if ($b >= SINTMAX || $b <= INTMIN) && !ref($b);
      100        
5194 21070         1966710 my($refa,$refb) = (ref($a),ref($b));
5195              
5196 21070 100 100     61507 if (!$refa && !$refb) {
5197             # Both numbers are in signed range, so we can negate them.
5198 77     77   2424641 use integer; # This is >>> SIGNED <<< integer.
  77         237  
  77         1088  
5199             # Signed division is implementation defined in C89.
5200 19 50 33     183 return -(-$a / $b) if $a < 0 && $b > 0;
5201 0 0 0     0 return -( $a / -$b) if $b < 0 && $a > 0;
5202 0 0 0     0 return (-$a / -$b) if $a < 0 && $b < 0;
5203 0         0 return ( $a / $b);
5204             }
5205              
5206 21051         35602 my $q; # set this, turn into int and return at end
5207 21051 50 33     158147 if ($refa eq 'Math::GMPz' || $refb eq 'Math::GMPz') {
    50 33        
    50 33        
5208 0         0 $q = Math::GMPz->new();
5209 0 0       0 $a = Math::GMPz->new($a) unless $refa eq 'Math::GMPz';
5210 0 0       0 $b = Math::GMPz->new($b) unless $refb eq 'Math::GMPz';
5211 0         0 Math::GMPz::Rmpz_tdiv_q($q,$a,$b);
5212             } elsif ($refa eq 'Math::GMP' || $refb eq 'Math::GMP') {
5213 0 0       0 $a = Math::GMP->new($a) unless $refa eq 'Math::GMP';
5214 0 0       0 $b = Math::GMP->new($b) unless $refb eq 'Math::GMP';
5215             # op_div => mpz_div function (obsolete!). bdiv => tdiv_qr
5216 0         0 ($q) = $a->bdiv($b);
5217             } elsif ($refa eq 'Math::Pari' || $refb eq 'Math::Pari') {
5218 0 0       0 $a = Math::Pari->new("$a") unless $refa eq 'Math::Pari';
5219 0 0       0 $b = Math::Pari->new("$b") unless $refb eq 'Math::Pari';
5220 0         0 $q = Math::Pari::gdivent(abs($a),abs($b));
5221 0 0       0 $q = Math::Pari::gneg($q) if ($a < 0) != ($b < 0);
5222             } else {
5223             # Force no upgrade so 'use bignum' won't screw us over.
5224 21051         75480 my $A = Math::BigInt->new("$a")->upgrade(undef);
5225 21051         3688029 my $B = Math::BigInt->new("$b")->upgrade(undef);
5226 21051         2869756 $q = abs($a) / abs($b);
5227 21051 100       13266955 $q = -$q if ($a < 0) != ($b < 0);
5228 21051 50 66     6495513 $q = $refa->new("$q") if $refa ne 'Math::BigInt' && $refb ne 'Math::BigInt';
5229             }
5230 21051         65635 $q;
5231             #return $q <= INTMAX && $q >= INTMIN ? _bigint_to_int($q) : $q;
5232             }
5233              
5234             # Truncated Division
5235             sub tdivrem {
5236 216     216 0 4063 my($a,$b) = @_;
5237 216         6421 validate_integer($a);
5238 216         9223 validate_integer($b);
5239 216 50       6843 croak "tdivrem: divide by zero" if $b == 0;
5240 216         41172 my($q,$r);
5241 216 100 66     1486 if (!ref($a) && !ref($b) && $a>=0 && $b>=0 && $a
      66        
      66        
      33        
      33        
5242 77     77   44765 { use integer; $q = $a / $b; }
  77         649  
  77         796  
  70         112  
  70         115  
5243 70         118 $r = $a - $b * $q;
5244             } else {
5245 146         586 $q = _tquotient($a, $b);
5246 146         614 $r = $a - $b * $q;
5247 146 100 66     63762 $q = _bigint_to_int($q) if ref($q) && $q <= INTMAX && $q >= INTMIN;
      100        
5248 146 100 66     9448 $r = _bigint_to_int($r) if ref($r) && $r <= INTMAX && $r >= INTMIN;
      66        
5249             }
5250 216         46767 ($q,$r);
5251             }
5252             # Floored Division
5253             sub fdivrem {
5254 73     73 0 5542 my($a,$b) = @_;
5255 73         501 validate_integer($a);
5256 73         14135 validate_integer($b);
5257 73 50       938 croak "fdivrem: divide by zero" if $b == 0;
5258 73         5087 my($q,$r);
5259 73 100 100     646 if (!ref($a) && !ref($b) && $a>=0 && $b>=0 && $a
      100        
      100        
      66        
      66        
5260 77     77   21749 use integer; $q = $a / $b;
  77         493  
  77         665  
  1         3  
5261             } else {
5262 72         267 $q = _tquotient($a, $b);
5263             }
5264 73         329 $r = $a - $b * $q;
5265             # qe = qt-I re = rt+I*d I = (rt >= 0) ? 0 : (b>0) ? 1 : -1;
5266             # qf = qt-I rf = rt+I*d I = (signum(rt) = -signum(b)) 1 : 0
5267 73 100 100     28295 if ( ($r < 0 && $b > 0) || ($r > 0 && $b < 0) )
      100        
      100        
5268 51         9637 { $q--; $r += $b; }
  51         2955  
5269 73 100 100     17777 $q = _bigint_to_int($q) if ref($q) && $q <= INTMAX && $q >= INTMIN;
      100        
5270 73 100 100     13478 $r = _bigint_to_int($r) if ref($r) && $r <= INTMAX && $r >= INTMIN;
      66        
5271 73         4668 ($q,$r);
5272             }
5273             # Ceiling Division
5274             sub cdivrem {
5275 14     14 0 10768 my($a,$b) = @_;
5276 14         124 validate_integer($a);
5277 14         146 validate_integer($b);
5278 14 50       219 croak "cdivrem: divide by zero" if $b == 0;
5279 14         33 my($q,$r);
5280 14 100 66     127 if (!ref($a) && !ref($b) && $a>=0 && $b>=0 && $a
      66        
      66        
      33        
      66        
5281 77     77   22579 use integer; $q = $a / $b;
  77         165  
  77         484  
  1         4  
5282             } else {
5283 13         46 $q = _tquotient($a, $b);
5284             }
5285 14         63 $r = $a - $b * $q;
5286 14 100 66     8031 if ($r != 0 && (($a >= 0) == ($b >= 0)))
5287 7         2820 { $q++; $r -= $b; }
  7         591  
5288 14 100 100     5211 $q = _bigint_to_int($q) if ref($q) && $q <= INTMAX && $q >= INTMIN;
      100        
5289 14 100 66     3992 $r = _bigint_to_int($r) if ref($r) && $r <= INTMAX && $r >= INTMIN;
      100        
5290 14         3179 ($q,$r);
5291             }
5292             # Euclidean Division
5293             sub divrem {
5294 339     339 0 13310 my($a,$b) = @_;
5295 339         1015 validate_integer($a);
5296 339         3297 validate_integer($b);
5297 339 50       2374 croak "divrem: divide by zero" if $b == 0;
5298 339         11205 my($q,$r);
5299 339 100 66     2532 if (!ref($a) && !ref($b) && $a>=0 && $b>=0 && $a
      66        
      66        
      33        
      33        
5300 77     77   18666 use integer; $q = $a / $b;
  77         212  
  77         445  
  283         430  
5301             } else {
5302 56         206 $q = _tquotient($a, $b);
5303             }
5304 339         726 $r = $a - $b * $q;
5305 339 100       26352 if ($r <0) {
5306 5 100       1197 if ($b > 0) { $q--; $r += $b; }
  4         20  
  4         374  
5307 1         6 else { $q++; $r -= $b; }
  1         97  
5308             }
5309 339 100 100     14247 $q = _bigint_to_int($q) if ref($q) && $q <= INTMAX && $q >= INTMIN;
      100        
5310 339 100 100     7166 $r = _bigint_to_int($r) if ref($r) && $r <= INTMAX && $r >= INTMIN;
      66        
5311 339         15766 ($q,$r);
5312             }
5313              
5314             sub divint {
5315 282933 100 100 282933 0 993070 if (!OLD_PERL_VERSION && $_[1] > 0 && $_[0] >= 0) {
5316             # Simple no-error all positive case
5317 282889         6914872 my($a,$b) = @_;
5318 282889         388276 my $q;
5319 282889 100 66     1359765 if (!ref($a) && !ref($b) && $a
      100        
      100        
5320 77     77   19128 use integer; $q = $a / $b;
  77         244  
  77         548  
  262086         392679  
5321             } else {
5322 20803         67622 $q = _tquotient($a, $b);
5323 20803 100 100     91959 $q = _bigint_to_int($q) if ref($q) && $q <= INTMAX;
5324             }
5325 282889         1794954 return $q;
5326             }
5327 44         3667 (fdivrem(@_))[0];
5328             }
5329             sub _posmodint { # Simple no-error all positive case
5330             #croak "Invalid call to _posmodint(@_)" unless $_[1] > 0 && $_[0] >= 0;
5331 1831     1831   4994 my($a,$b) = @_;
5332 1831         10159 validate_integer($a);
5333 1831         79275 validate_integer($b);
5334 1831         8756 my $r;
5335 1831 100 100     11473 if (ref($b) || ref($a)) {
    50 33        
5336 1592         5129 $r = $a % $b;
5337 1592 100       705720 $r = _bigint_to_int($r) if $r <= INTMAX;
5338             } elsif ($b < INTMAX && $a < INTMAX) {
5339 239         452 $r = $a % $b;
5340             } else {
5341 0         0 $r = tobigint($a) % tobigint($b);
5342 0 0       0 $r = _bigint_to_int($r) if $r <= INTMAX;
5343             }
5344 1831         92292 $r;
5345             }
5346             sub modint {
5347             # Fast processing for simple cases
5348 1847 100 100 1847 0 25807 if ($_[1] > 0 && $_[0] >= 0) {
    100 100        
    100 66        
    50 33        
5349 1821         393233 return _posmodint(@_);
5350             } elsif ($_[1] < 0 && $_[0] >= 0) {
5351 2 50 33     15 if ($_[0] < INTMAX && -$_[1] < INTMAX) {
5352 0         0 my $r = _posmodint($_[0],-$_[1]);
5353 0 0       0 return $r == 0 ? 0 : $_[1]+$r;
5354             }
5355             } elsif ($_[1] > 0 && $_[0] <= 0) {
5356 22 100 100     7181 if (-$_[0] < INTMAX && $_[1] < INTMAX) {
5357 10         37 my $r = _posmodint(-$_[0],$_[1]);
5358 10 50       42 return $r == 0 ? 0 : $_[1]-$r;
5359             }
5360             } elsif ($_[1] < 0 && $_[0] <= 0) {
5361 2 50 33     15 if (-$_[0] < INTMAX && -$_[1] < INTMAX) {
5362 0         0 my $r = _posmodint(-$_[0],-$_[1]);
5363 0 0       0 return $r == 0 ? 0 : -$r;
5364             }
5365             }
5366 16         2526 (fdivrem(@_))[1];
5367             }
5368             sub cdivint {
5369 484 100 100 484 0 6486 if ($_[1] > 0 && $_[0] >= 0) { # Simple no-error all positive case
5370 480         4647 my($a,$b) = @_;
5371 480         1428 validate_integer($a);
5372 480         1834 validate_integer($b);
5373 480         846 my $q;
5374 480 100 66     3343 if (!ref($a) && !ref($b) && $a
      66        
      66        
5375 77     77   47971 use integer; $q = $a / $b;
  77         174  
  77         458  
  467         848  
5376 467 100       1203 $q++ if $a != $b*$q;
5377             } else {
5378 13         60 $q = _tquotient($a, $b);
5379 13 100       63 $q++ if $a != $b*$q;
5380 13 100 66     6568 $q = _bigint_to_int($q) if ref($q) && $q <= INTMAX;
5381             }
5382 480         2812 return $q;
5383             }
5384 4         501 (cdivrem(@_))[0];
5385             }
5386              
5387             sub absint {
5388 201     201 0 11910 my($n) = @_;
5389 201         654 validate_integer_abs($n);
5390 201         9573 reftyped($_[0], $n);
5391             }
5392             sub negint {
5393 1669     1669 0 65498 my($n) = @_;
5394 1669         9889 validate_integer($n);
5395 1669 50       107882 return 0 if $n == 0; # Perl 5.6 has to have this: if $n=0 => -$n = -0
5396 1669 100 100     367540 return -$n if ref($n) || $n < SINTMAX;
5397 25 50       124 if ($n > 0) { $n = "-$n"; }
  25         117  
5398 0         0 else { $n =~ s/^-//; }
5399 25         167 reftyped($_[0], $n);
5400             }
5401             sub signint {
5402 5     5 0 9 my($n) = @_;
5403 5         8 validate_integer($n);
5404             # -1,0,1 Native ints, Math::BigInt, Math::GMP, Math::GMPz 0.68+
5405             # neg,0,pos Math::GMPz 0.67 and earlier
5406             # -1 or 4294967295, 0, 1 Math::Pari
5407 5         6 my $r = $n <=> 0;
5408 5 50 33     8 $r = -1 if $r == 4294967295 && ref($n) eq 'Math::Pari';
5409 5 100       14 return $r < 0 ? -1 : $r > 0 ? 1 : 0;
    100          
5410             }
5411             sub cmpint {
5412 15     15 0 2632 my($a, $b) = @_;
5413 15         72 validate_integer($a);
5414 15         59 validate_integer($b);
5415 15         698 my $r = $a <=> $b;
5416 15 0 0     661 $r = -1 if $r == 4294967295 && (ref($a) eq 'Math::Pari' || ref($b) eq 'Math::Pari');
      33        
5417 15 100       172 return $r < 0 ? -1 : $r > 0 ? 1 : 0;
    100          
5418             }
5419              
5420             sub lshiftint {
5421 1365     1365 0 22964 my($n, $k) = @_;
5422 1365         6962 validate_integer($n);
5423 1365 100       21786 if (!defined $k) { $k = 1; } else { validate_integer($k); }
  374         1002  
  991         2870  
5424              
5425 1365 50       4704 return rshiftint($n, Mnegint($k)) if $k < 0;
5426 1365 100       3971 return Mnegint(lshiftint(Mnegint($n),$k)) if $n < 0;
5427              
5428 1343 100       90912 if (!ref($n)) {
5429 959 100 100     40900 return $n << $k if $n < INTMAX && $k < MPU_MAXBITS && $n == ($n<<$k)>>$k;
      100        
5430 918         4451 $n = tobigint($n);
5431             }
5432 1302         5695 $n = $n << $k;
5433 1302 100       736447 return $n <= INTMAX ? _bigint_to_int($n) : $n;
5434              
5435             #my $k2 = (!defined $k) ? 2 : ($k < MPU_MAXBITS) ? (1<<$k) : Mpowint(2,$k);
5436             #Mmulint($n, $k2);
5437             }
5438             sub rshiftint {
5439 12724     12724 0 53625 my($n, $k) = @_;
5440 12724         40864 validate_integer($n);
5441 12724 100       166293 if (!defined $k) { $k = 1; } else { validate_integer($k); }
  11849         20395  
  875         2583  
5442              
5443 12724 100       29277 return lshiftint($n, Mnegint($k)) if $k < 0;
5444 12720 100       27432 return Mnegint(rshiftint(Mnegint($n),$k)) if $n < 0;
5445              
5446 12713 100       638245 if (!ref($n)) {
5447             # Pre 5.24.0, large right shifts were undefined.
5448 10248 100       40968 return $k < MPU_MAXBITS ? $n >> $k : 0 if $n < INTMAX;
    50          
5449 0         0 $n = tobigint($n);
5450             }
5451 2465         9448 $n = $n >> $k;
5452 2465 100       1139137 return $n <= INTMAX ? _bigint_to_int($n) : $n;
5453              
5454             #my $k2 = (!defined $k) ? 2 : ($k < MPU_MAXBITS) ? (1<<$k) : Mpowint(2,$k);
5455             #(Mtdivrem($n, $k2))[0];
5456             }
5457              
5458             sub rashiftint {
5459 23     23 0 11148 my($n, $k) = @_;
5460 23         210 validate_integer($n);
5461 23 50       187 if (!defined $k) { $k = 1; } else { validate_integer($k); }
  0         0  
  23         71  
5462 23 100       133 return lshiftint($n, Mnegint($k)) if $k < 0;
5463 19 100       459 my $k2 = $k < MPU_MAXBITS ? (1<<$k) : Mpowint(2,$k);
5464 19         4126 Mdivint($n, $k2);
5465             }
5466              
5467             sub powersum {
5468 73     73 0 40891 my($n, $k) = @_;
5469 73         217 validate_integer_nonneg($n);
5470 73         159 validate_integer_nonneg($k);
5471              
5472 73 100 66     316 return $n if $n <= 1 || $k == 0;
5473              
5474 45 100       646 return Mdivint(Mvecprod($n, Madd1int($n), Madd1int(Mmulint($n,2))),6) if $k==2;
5475 34 100       189 return Mdivint(Mvecprod(
5476             $n, Madd1int($n), Madd1int(Mmulint($n,2)),
5477             Mvecsum( Mmulint(3,Mpowint($n,2)), Mmulint(3,$n), -1 )
5478             ),30) if $k==4;
5479              
5480 27         1257 my $a = Mrshiftint(Mmulint($n,Madd1int($n)));
5481 27 100       367 return $a if $k == 1;
5482 26 100       184 return Mmulint($a,$a) if $k == 3;
5483 18 100       53 return Mdivint(Msubint(Mmulint(4,Mpowint($a,3)),Mmulint($a,$a)),3) if $k == 5;
5484              
5485 14         51 my @v;
5486 14 100       46 if ($k < $n) {
5487 10         213 for my $j (1..$k) {
5488 90         4621 my $F = Mfactorial($j);
5489 90         1951 my $B = Mbinomial($n+1,$j+1);
5490 90         9975 my $S = Mstirling($k,$j,2);
5491 90         2326 push @v, Mvecprod($F,$B,$S);
5492             }
5493             } else {
5494 4         18 @v = map { Mpowint($_,$k) } 1..$n;
  39         10688  
5495             }
5496 14         389 Mvecsum(@v);
5497             }
5498              
5499             # Make sure to work around RT71548, Math::BigInt::Lite,
5500             # and use correct lcm semantics.
5501             sub gcd {
5502 6385     6385 0 25004 my $REF = undef;
5503 6385         20194 for my $n (@_) {
5504 8002         19801 my $refn = ref($n);
5505 8002 100       25346 if ($refn) { $REF = $refn; last; }
  5305         10712  
  5305         12985  
5506             }
5507              
5508             # Try all-native if all inputs are native ints.
5509 6385 100       19663 if (!$REF) {
5510 1080   100     2963 my($x,$y) = (shift || 0, 0);
5511 1080 100       2632 $x = -$x if $x < 0;
5512 1080         2440 while (@_) {
5513 1082         1750 $y = shift;
5514 1082         2376 while ($y) { ($x,$y) = ($y, $x % $y); }
  6576         14676  
5515 1082 100       2844 $x = -$x if $x < 0;
5516             }
5517 1080         3812 return $x;
5518             }
5519              
5520 5305 100       15097 my @N = map { ref($_) eq $REF ? $_ : $REF->new("$_") } @_;
  10611         112454  
5521 5305         488379 my $gcd;
5522              
5523 5305 50       17374 if ($REF eq 'Math::BigInt') {
    0          
    0          
5524 5305         26554 $gcd = Math::BigInt::bgcd(@N);
5525             } elsif ($REF eq 'Math::GMPz') {
5526 0         0 $gcd = Math::GMPz->new(shift(@N));
5527 0         0 Math::GMPz::Rmpz_gcd($gcd,$gcd,$_) for @N;
5528             } elsif ($REF eq 'Math::GMP') {
5529 0         0 $gcd = Math::GMP->new(shift(@N));
5530 0         0 $gcd = Math::GMP::gcd($gcd,$_) for @N;
5531             } else {
5532 0         0 $gcd = Math::BigInt::bgcd(map { Math::BigInt->new("$_") } @N);
  0         0  
5533 0         0 $gcd = tobigint($gcd);
5534             }
5535 5305 100       6346188 $gcd = _bigint_to_int($gcd) if $gcd <= INTMAX;
5536 5305         265934 $gcd;
5537             }
5538             sub lcm {
5539 19     19 0 3629 my(@v) = @_;
5540 19 50       74 return 1 unless @v > 0;
5541 19         36 my $lcm;
5542 19         82 for my $y (@v) {
5543 56         1941 validate_integer($y);
5544 56 0       1014 if ($y <= 0) { return 0 if $y == 0; $y = Mabsint($y); }
  0 50       0  
  0         0  
5545 56 100       3084 $lcm = defined $lcm ? Mmulint($lcm, Mdivint($y, Mgcd($lcm,$y))) : $y;
5546             }
5547 19         2082 return $lcm;
5548             }
5549             sub gcdext {
5550 4     4 0 12268 my($x,$y) = @_;
5551 4         30 validate_integer($x);
5552 4         83 validate_integer($y);
5553 4 50       79 if ($x == 0) { return (0, (-1,0,1)[($y>=0)+($y>0)], abs($y)); }
  0         0  
5554 4 50       329 if ($y == 0) { return ((-1,0,1)[($x>=0)+($x>0)], 0, abs($x)); }
  0         0  
5555              
5556 4 50       286 if ($Math::Prime::Util::_GMPfunc{"gcdext"}) {
5557 0         0 my($a,$b,$g) = Math::Prime::Util::GMP::gcdext($x,$y);
5558 0         0 $a = reftyped($_[0], $a);
5559 0         0 $b = reftyped($_[0], $b);
5560 0         0 $g = reftyped($_[0], $g);
5561 0         0 return ($a,$b,$g);
5562             }
5563              
5564 4         21 my($a,$b,$g,$u,$v,$w);
5565 4 100 66     27 if (abs($x) < (~0>>1) && abs($y) < (~0>>1)) {
5566 2 50       7 $x = _bigint_to_int($x) if ref($x);
5567 2 50       9 $y = _bigint_to_int($y) if ref($y);
5568 2         16 ($a,$b,$g,$u,$v,$w) = (1,0,$x,0,1,$y);
5569 2         8 while ($w != 0) {
5570 14         26 my $r = $g % $w;
5571 14         32 my $q = int(($g-$r)/$w);
5572 14         46 ($a,$b,$g,$u,$v,$w) = ($u,$v,$w,$a-$q*$u,$b-$q*$v,$r);
5573             }
5574             } else {
5575 2         469 ($a,$b,$g,$u,$v,$w) = (1,0,$x,0,1,$y);
5576 2         10 while ($w != 0) {
5577 109         22741 my($q,$r) = Mdivrem($g,$w);
5578 109         1203 ($a,$b,$g,$u,$v,$w) = ($u, $v, $w,
5579             Msubint($a,Mmulint($q,$u)),
5580             Msubint($b,Mmulint($q,$v)), $r);
5581             }
5582             }
5583 4 50       700 if ($g < 0) { ($a,$b,$g) = (-$a,-$b,-$g); }
  0         0  
5584 4         42 return ($a,$b,$g);
5585             }
5586              
5587             sub chinese2 {
5588 94 50   94 0 2077 return (0,0) unless scalar @_;
5589 94         166 my($lcm, $sum);
5590              
5591 94 50 33     263 if ($Math::Prime::Util::_GMPfunc{"chinese2"} && $Math::Prime::Util::GMP::VERSION >= 0.53) {
5592 0         0 return maybetobigintall(
5593             Math::Prime::Util::GMP::chinese2(@_)
5594             );
5595             }
5596              
5597             # Validate, copy, and do abs on the inputs.
5598 94         153 my @items;
5599 94         174 foreach my $aref (@_) {
5600 194 50 33     755 die "chinese arguments are two-element array references"
5601             unless ref($aref) eq 'ARRAY' && scalar @$aref == 2;
5602 194         370 my($a,$n) = @$aref;
5603 194         438 validate_integer($a);
5604 194         619 validate_integer($n);
5605 194 50       442 return (undef,undef) if $n == 0;
5606 194         449 $n = Mabsint($n);
5607 194         416 $a = Mmodint($a,$n);
5608 194         238 if (OLD_PERL_VERSION) { ($a,$n) = ("$a","$n"); }
5609 194         593 push @items, [$a,$n];
5610             }
5611 94 50       199 return @{$items[0]} if scalar @items == 1;
  0         0  
5612 94         384 @items = sort { $b->[1] <=> $a->[1] } @items;
  103         312  
5613              
5614 94         119 ($sum, $lcm) = @{shift @items};
  94         229  
5615              
5616 94         186 foreach my $aref (@items) {
5617 100         517 my($ai, $ni) = @$aref;
5618             # gcdext
5619 100         222 my($u,$v,$g,$s,$t,$w) = (1,0,$lcm,0,1,$ni);
5620 100         211 while ($w != 0) {
5621 571         1791 my($q,$r) = Mdivrem($g,$w);
5622 571         2220 ($u,$v,$g,$s,$t,$w) = ($s, $t, $w,
5623             Msubint($u,Mmulint($q,$s)),
5624             Msubint($v,Mmulint($q,$t)), $r);
5625             }
5626             #($u,$v,$g) = (-$u,-$v,-$g) if $g < 0;
5627 100 50       604 ($u,$v,$g) = map { Mnegint($_) } ($u,$v,$g) if $g < 0;
  0         0  
5628 100 50 66     241 return (undef,undef) if $g != 1 && ($sum % $g) != ($ai % $g); # Not co-prime
5629 100 100       388 $s = Mnegint($s) if "$s" < 0;
5630 100 100       301 $t = Mnegint($t) if "$t" < 0;
5631 100         1322 $lcm = Mmulint($lcm, $s);
5632 100 100       3455 $u = Maddint($u, $lcm) if "$u" < 0;
5633 100 100       1147 $v = Maddint($v, $lcm) if "$v" < 0;
5634 100         2523 my $vs = Mmulmod($v,$s,$lcm);
5635 100         3525 my $ut = Mmulmod($u,$t,$lcm);
5636 100         3194 my $m1 = Mmulmod($sum,$vs,$lcm);
5637 100         3428 my $m2 = Mmulmod($ut,$ai,$lcm);
5638 100         3440 $sum = Maddmod($m1, $m2, $lcm);
5639             }
5640 94         3348 ($sum,$lcm);
5641             }
5642              
5643             sub chinese {
5644 88     88 0 2146 (chinese2(@_))[0];
5645             }
5646              
5647             sub _from_128 {
5648 0     0   0 my($hi, $lo) = @_;
5649 0 0 0     0 return 0 unless defined $hi && defined $lo;
5650 0         0 Maddint(Mlshiftint($hi,MPU_MAXBITS), $lo);
5651             }
5652              
5653             sub vecsum {
5654 852 50   852 0 3916 return reftyped($_[0], @_ ? $_[0] : 0) if @_ <= 1;
    100          
5655              
5656             return reftyped($_[0], Math::Prime::Util::GMP::vecsum(@_))
5657 808 50       2523 if $Math::Prime::Util::_GMPfunc{"vecsum"};
5658 808         1520 my $sum = 0;
5659 808         1437 if (OLD_PERL_VERSION) { $_="$_" for @_ };
5660 808         2013 foreach my $v (@_) {
5661 18433         28054 $sum += $v;
5662 18433 100 100     102715 if ($sum > (INTMAX-250) || $sum < (INTMIN+250)) {
5663             # Sum again from the start using bigint sum
5664 122         41429 $sum = tobigint(0);
5665 122 50       737 if (ref($sum) eq 'Math::Pari') { $sum += "$_" for @_; }
  0         0  
5666 122         715 else { $sum += $_ for @_; }
5667 122 100 66     20383692 $sum = _bigint_to_int($sum) if $sum <= INTMAX && $sum >= INTMIN;
5668 122         35618 return $sum;
5669             }
5670             }
5671 686         6597 $sum;
5672             }
5673              
5674             sub _product_mulint {
5675 0     0   0 my($a, $b, $r) = @_;
5676 0 0       0 return $r->[$a] if $b <= $a;
5677 0 0       0 return Mmulint($r->[$a], $r->[$b]) if $b == $a+1;
5678 0 0       0 return Mmulint(Mmulint($r->[$a], $r->[$a+1]), $r->[$a+2]) if $b == $a+2;
5679 0         0 my $c = $a + (($b-$a+1)>>1);
5680 0         0 Mmulint( _product_mulint($a, $c-1, $r), _product_mulint($c, $b, $r) );
5681             }
5682             sub _product_mult {
5683 1375     1375   151797 my($a, $b, $r) = @_;
5684 1375 50       3978 return $r->[$a] if $b <= $a;
5685 1375 100       3411 return $r->[$a] * $r->[$a+1] if $b == $a+1;
5686 1044 100       3288 return $r->[$a] * $r->[$a+1] * $r->[$a+2] if $b == $a+2;
5687 543         1016 my $c = $a + (($b-$a+1)>>1);
5688 543         1288 _product_mult($a, $c-1, $r) * _product_mult($c, $b, $r);
5689             }
5690              
5691             sub vecprod {
5692 816 50   816 0 15399 return 1 unless @_;
5693             return reftyped($_[0], Math::Prime::Util::GMP::vecprod(@_))
5694 816 50       2276 if $Math::Prime::Util::_GMPfunc{"vecprod"};
5695              
5696 816 100       2131 return $_[0] if @_ == 1;
5697              
5698             # Argh, Perl 5.6.2.
5699 698         1016 if (OLD_PERL_VERSION) {
5700             my $prod = _product_mult(0, $#_, [map { tobigint($_) } @_]);
5701             $prod = _bigint_to_int($prod) if ref($prod) && $prod <= INTMAX && $prod >= INTMIN;
5702             return $prod;
5703             }
5704              
5705             # Try native for non-negative/non-zero inputs
5706 698 100 100     4003 if ($_[0] > 0 && $_[0] <= INTMAX && $_[1] > 0 && $_[1] <= INTMAX) {
      100        
      100        
5707 318         667 my $prod = shift @_;
5708 318   66     7926 $prod *= shift @_
      100        
      100        
5709             while @_ && $_[0] > 0 && $_[0] <= INTMAX && int(INTMAX/$prod) > $_[0];
5710 318 100       2103 return $prod if @_ == 0;
5711 242 50       941 unshift @_, $prod if $prod > 1;
5712             }
5713              
5714 622 100       46224 return mulint($_[0], $_[1]) if @_ == 2;
5715              
5716             # Product tree
5717             # my $prod = _product_mulint(0, $#_, \@_);
5718 289         1327 my $prod = _product_mult(0, $#_, [map { tobigint($_) } @_]);
  2165         5047  
5719              
5720 289 100 66     173384 $prod = _bigint_to_int($prod) if ref($prod) && $prod <= INTMAX && $prod >= INTMIN;
      100        
5721 289         72242 $prod;
5722             }
5723              
5724             sub vecmin {
5725 6 50   6 0 45 return unless @_;
5726 6         22 my $min = shift;
5727 6 100       18 for (@_) { $min = $_ if $_ < $min; }
  13         53  
5728 6         210 $min;
5729             }
5730             sub vecmax {
5731 96 50   96 0 281 return unless @_;
5732 96         235 my $max = shift;
5733 96 100       241 for (@_) { $max = $_ if $_ > $max; }
  106         317  
5734 96         755 $max;
5735             }
5736              
5737             sub vecextract {
5738 1     1 0 4 my($aref, $mask) = @_;
5739              
5740 1 50       15 return @$aref[@$mask] if ref($mask) eq 'ARRAY';
5741              
5742             # This is concise but very slow.
5743             # map { $aref->[$_] } grep { $mask & (1 << $_) } 0 .. $#$aref;
5744              
5745 0         0 my($i, @v) = (0);
5746 0         0 while ($mask) {
5747 0 0       0 push @v, $i if $mask & 1;
5748 0         0 $mask >>= 1;
5749 0         0 $i++;
5750             }
5751 0         0 @$aref[@v];
5752             }
5753              
5754             sub vecequal {
5755 2     2 0 8 my($aref, $bref) = @_;
5756 2 50 33     20 croak "vecequal element not scalar or array reference"
5757             unless ref($aref) eq 'ARRAY' && ref($bref) eq 'ARRAY';
5758 2 50       9 return 0 unless $#$aref == $#$bref;
5759 2         25 my $i = 0;
5760 2         8 for my $av (@$aref) {
5761 4         19 my $bv = $bref->[$i++];
5762 4 0 33     12 next if !defined $av && !defined $bv;
5763 4 50 33     21 return 0 if !defined $av || !defined $bv;
5764 4 0 33     14 if (ref($av) && ref($bv) &&
      0        
      33        
5765             (ref($av) =~ /^(ARRAY|HASH|CODE|FORMAT|IO|REGEXP)$/i ||
5766             ref($bv) =~ /^(ARRAY|HASH|CODE|FORMAT|IO|REGEXP)$/i) ) {
5767 0 0 0     0 next if (ref($av) eq ref($bv)) && vecequal($av, $bv);
5768 0         0 return 0;
5769             }
5770             # About 7x faster if we skip the validates.
5771             # validate_integer($av);
5772             # validate_integer($bv);
5773 4 100       27 return 0 unless "$av" eq "$bv";
5774             }
5775 1         8 1;
5776             }
5777              
5778             sub vecmex {
5779 1     1 0 5 my $items = scalar(@_);
5780 1         4 my @seen;
5781 1         15 for (@_) {
5782 4 100       26 $seen[$_] = 0 if $_ < $items;
5783             }
5784 1         5 for (0 .. $items-1) {
5785 4 100       21 return $_ unless defined $seen[$_];
5786             }
5787 0         0 return $items;
5788             }
5789              
5790             sub vecpmex {
5791 1     1 0 4 my $items = scalar(@_);
5792 1         3 my @seen;
5793 1         3 for (@_) {
5794 4 100       13 $seen[$_] = 0 if $_ <= $items;
5795             }
5796 1         5 for (1 .. $items) {
5797 3 100       14 return $_ unless defined $seen[$_];
5798             }
5799 0         0 return $items+1;
5800             }
5801              
5802             sub sumdigits {
5803 4     4 0 1669 my($n,$base) = @_;
5804 4         10 my $sum = 0;
5805 4 100 100     68 $base = 2 if !defined $base && $n =~ s/^0b//;
5806 4 50 66     42 $base = 16 if !defined $base && $n =~ s/^0x//;
5807 4 100 66     31 if (!defined $base || $base == 10) {
5808 1         3 $n =~ tr/0123456789//cd;
5809 1         9 $sum += $_ for (split(//,$n));
5810             } else {
5811 3 50       25 croak "sumdigits: invalid base $base" if $base < 2;
5812 3         11 my $cmap = substr("0123456789abcdefghijklmnopqrstuvwxyz",0,$base);
5813 3         25 for my $c (split(//,lc($n))) {
5814 21         45 my $p = index($cmap,$c);
5815 21 100       52 $sum += $p if $p > 0;
5816             }
5817             }
5818 4         39 $sum;
5819             }
5820              
5821             sub is_happy {
5822 4     4 0 1417 my($n, $base, $k) = @_;
5823 4         18 validate_integer_nonneg($n);
5824              
5825 4         9 my $h = 1;
5826              
5827 4 50 66     31 if (!defined $base && !defined $k) { # default base 10 exponent 2
5828 1   66     11 while ($n > 1 && $n != 4) {
5829 6         10 my $sum = 0;
5830 6         26 $sum += $_*$_ for (split(//,$n));
5831 6         10 $n = $sum;
5832 6         22 $h++;
5833             }
5834 1 50       13 return ($n == 1) ? $h : 0;
5835             }
5836              
5837 3 50       26 if (defined $base) {
5838 3         12 validate_integer_nonneg($base);
5839 3 50 33     19 croak "is_happy: invalid base $base" if $base < 2 || $base > 36;
5840             } else {
5841 0         0 $base = 10;
5842             }
5843 3 100       22 if (defined $k) {
5844 1         6 validate_integer_nonneg($k);
5845 1 50       19 croak "is_happy: invalid exponent $k" if $k > 10;
5846             } else {
5847 2         5 $k = 2;
5848             }
5849              
5850 3         14 my %seen;
5851 3   66     24 while ($n > 1 && !exists $seen{$n}) {
5852 7         35 $seen{$n} = undef;
5853 7 50       18 if ($base == 10) {
5854 0         0 my $sum = 0;
5855 0         0 $sum += $_ ** $k for (split(//,$n));
5856 0         0 $n = $sum;
5857             } else {
5858 7         14 my @d;
5859 7         22 while ($n >= 1) {
5860 21         33 my $rem = $n % $base;
5861 21 50       72 push @d, ($k <= 6) ? int($rem ** $k) : Mpowint($rem,$k);
5862             #push @d, Mpowint($rem,$k);
5863 21         56 $n = ($n-$rem)/$base; # Always an exact division
5864             }
5865 7         29 $n = Mvecsum(@d);
5866             }
5867 7         32 $h++;
5868             }
5869 3 50       45 return ($n == 1) ? $h : 0;
5870             }
5871              
5872              
5873              
5874             # Tonelli-Shanks
5875             sub _sqrtmod_prime {
5876 47     47   352 my($a, $p) = @_;
5877 47         110 my($x, $q, $e, $t, $z, $r, $m, $b);
5878 47         179 my $Q = Msub1int($p);
5879              
5880 47 100       1095 if (($p % 4) == 3) {
5881 24         1072 $r = Mpowmod($a, Mrshiftint(Madd1int($p),2), $p);
5882 24 100       914 return undef unless Mmulmod($r,$r,$p) == $a;
5883 18         937 return $r;
5884             }
5885 23 100       1086 if (($p % 8) == 5) {
5886 17         1092 $m = Maddmod($a,$a,$p);
5887 17         638 $t = Mpowmod($m, Mrshiftint(Msubint($p,5),3), $p);
5888 17         270 $z = Mmulmod($m, Mmulmod($t,$t,$p), $p);
5889 17         521 $r = Mmulmod($t, Mmulmod($a, Msubmod($z,1,$p), $p), $p);
5890 17 100       511 return undef unless Mmulmod($r,$r,$p) == $a;
5891 13         738 return $r;
5892             }
5893              
5894             # Verify Euler's criterion for odd p
5895 6 100 66     48 return undef if $p != 2 && Mpowmod($a, Mrshiftint($Q), $p) != 1;
5896              
5897             # Cohen Algorithm 1.5.1. Tonelli-Shanks.
5898 4         169 $e = Mvaluation($Q, 2);
5899 4         40 $q = Mdivint($Q, Mpowint(2,$e));
5900 4         28 $t = 3;
5901 4         25 while (Mkronecker($t,$p) != -1) {
5902 2         5 $t += 2;
5903 2 50 33     10 return undef if $t == 201 && !Mis_prime($p);
5904             }
5905 4         24 $z = Mpowmod($t, $q, $p);
5906 4         64 $b = Mpowmod($a, $q, $p);
5907 4         52 $r = $e;
5908 4         13 $q = ($q+1) >> 1;
5909 4         20 $x = Mpowmod($a, $q, $p);
5910 4         68 while ($b != 1) {
5911 6         13 $t = $b;
5912 6   66     37 for ($m = 0; $m < $r && $t != 1; $m++) {
5913 12         49 $t = Mmulmod($t, $t, $p);
5914             }
5915 6         31 $t = Mpowmod($z, Mlshiftint(1, $r-$m-1), $p);
5916 6         38 $x = Mmulmod($x, $t, $p);
5917 6         19 $z = Mmulmod($t, $t, $p);
5918 6         21 $b = Mmulmod($b, $z, $p);
5919 6         20 $r = $m;
5920             }
5921             # Expected to always be true.
5922 4 50       31 return undef unless Mmulmod($x,$x,$p) == $a;
5923 4         16 return $x;
5924             }
5925              
5926             sub _sqrtmod_prime_power {
5927 97     97   204 my($a,$p,$e) = @_;
5928 97         153 my($r,$s);
5929              
5930 97 100       202 if ($e == 1) {
5931 47 100       128 $a %= $p if $a >= $p;
5932 47 100 100     3801 return $a if $p == 2 || $a == 0;
5933 39         1426 $r = _sqrtmod_prime($a,$p);
5934 39 100 66     277 return (defined $r && (Mmulmod($r,$r,$p) == $a) ? $r : undef);
5935             }
5936              
5937 50         134 my $n = Mpowint($p,$e);
5938 50         155 my $pk = Mmulint($p,$p);
5939              
5940 50 50       170 return 0 if ($a % $n) == 0;
5941              
5942 50 100       1713 if (($a % $pk) == 0) {
5943 1         8 my $apk = Mdivint($a, $pk);
5944 1         7 $s = _sqrtmod_prime_power($apk, $p, $e-2);
5945 1 50       7 return undef unless defined $s;
5946 1         5 return Mmulint($s,$p);
5947             }
5948              
5949 49 50       1106 return undef if ($a % $p) == 0;
5950              
5951 49 50 66     1282 my $ered = ($p > 2 || $e < 5) ? ($e+1) >> 1 : ($e+3) >> 1;
5952 49         128 $s = _sqrtmod_prime_power($a,$p,$ered);
5953 49 100       301 return undef unless defined $s;
5954              
5955 33 100       97 my $np = ($p == 2) ? Mmulint($n,$p) : $n;
5956 33         122 my $t1 = Msubmod($a, Mmulmod($s,$s,$np), $np);
5957 33         241 my $t2 = Maddmod($s, $s, $np);
5958 33         352 my $gcd = Mgcd($t1, $t2);
5959 33         146 $r = Maddmod($s, Mdivmod(Mdivint($t1,$gcd),Mdivint($t2,$gcd),$n), $n);
5960 33 100       195 return ((Mmulmod($r,$r,$n) == ($a % $n)) ? $r : undef);
5961             }
5962              
5963             sub _sqrtmod_composite {
5964 2     2   426 my($a,$n) = @_;
5965              
5966 2 50       8 return undef if $n <= 0;
5967 2 50       247 $a %= $n if $a >= $n;
5968 2 50 33     65 return $a if $n <= 2 || $a <= 1;
5969 2 50       453 return Msqrtint($a) if _is_perfect_square($a);
5970              
5971 2         5 my $N = 1;
5972 2         5 my $r = 0;
5973 2         168 foreach my $F (Mfactor_exp($n)) {
5974 6         21 my($f,$e) = @$F;
5975 6         22 my $fe = Mpowint($f, $e);
5976 6         35 my $s = _sqrtmod_prime_power($a, $f, $e);
5977 6 50       827 return undef unless defined $s;
5978 6         52 my $inv = Minvmod($N, $fe);
5979 6         27 my $t = Mmulmod($inv, Msubmod($s % $fe, $r % $fe, $fe), $fe);
5980 6         707 $r = Mmuladdmod($N, $t, $r, $n);
5981 6         340 $N = Mmulint($N, $fe);
5982             }
5983             #croak "Bad _sqrtmod_composite root $a,$n" unless Mmulmod($r,$r,$n) == $a;
5984 2         147 $r;
5985             }
5986              
5987             sub sqrtmod {
5988 6     6 0 2015 my($a,$n) = @_;
5989 6         41 validate_integer($a);
5990 6         135 validate_integer_abs($n);
5991 6 50       731 return (undef,0)[$n] if $n <= 1;
5992             #return Mmodint(Msqrtint($a),$n) if _is_perfect_square($a);
5993 6         634 $a = Mmodint($a,$n);
5994 6 50       21 return $a if $a <= 1;
5995              
5996 6 100       753 my $r = Mis_prime($n) ? _sqrtmod_prime($a,$n) : _sqrtmod_composite($a,$n);
5997 6 100       84 if (defined $r) {
5998 5 100       16 $r = $n-$r if $n-$r < $r;
5999 5 100 100     1209 $r = _bigint_to_int($r) if ref($r) && $r <= INTMAX;
6000             }
6001             #croak "Bad _sqrtmod_composite root $a,$n" unless Mmulmod($r,$r,$n) == $a;
6002 6         286 $r;
6003             }
6004              
6005              
6006              
6007              
6008             # helper function for allsqrtmod() - return list of all square roots of
6009             # a (mod p^k), assuming a integer, p prime, k positive integer.
6010             sub _allsqrtmodpk {
6011 62     62   488 my($a,$p,$k) = @_;
6012 62         145 my $pk = Mpowint($p,$k);
6013 62 100       196 unless ($a % $p) {
6014 27 100       66 unless ($a % ($pk)) {
6015             # if p^k divides a, we need the square roots of zero, satisfied by
6016             # ip^j with 0 <= i < p^{floor(k/2)}, j = p^{ceil(k/2)}
6017 26         84 my $low = Mpowint($p,$k >> 1);
6018 26 50       120 my $high = ($k % 2) ? Mmulint($low, $p) : $low;
6019 26         105 return map Mmulint($high, $_), 0 .. $low - 1;
6020             }
6021             # p divides a, p^2 does not
6022 1         3 my $a2 = Mdivint($a,$p);
6023 1 50       17 return () if $a2 % $p;
6024 1         3 my $pj = Mdivint($pk, $p);
6025             return map {
6026 1         3 my $qp = Mmulint($_,$p);
  1         2  
6027 1         4 map Maddint($qp,Mmulint($_,$pj)), 0 .. $p - 1;
6028             } _allsqrtmodpk(Mdivint($a2,$p), $p, $k - 2);
6029             }
6030 35         578 my $q = _sqrtmod_prime_power($a,$p,$k);
6031 35 100       648 return () unless defined $q;
6032 25 100       73 return ($q, $pk - $q) if $p != 2;
6033 1 50       3 return ($q) if $k == 1;
6034 0 0       0 return ($q, $pk - $q) if $k == 2;
6035 0         0 my $pj = Mdivint($pk,$p);
6036 0         0 my $q2 = ($q * ($pj - 1)) % $pk;
6037 0         0 return ($q, $pk - $q, $q2, $pk - $q2);
6038             }
6039              
6040             # helper function for allsqrtmod() - return list of all square roots of
6041             # a (mod p^k), assuming a integer, n positive integer > 1, f arrayref
6042             # of [ p, k ] pairs representing factorization of n. Destroys f.
6043             sub _allsqrtmodfact {
6044 59     59   113 my($a,$n,$f) = @_;
6045 59         83 my($p,$k) = @{ shift @$f };
  59         148  
6046 59         134 my @q = _allsqrtmodpk($a, $p, $k);
6047 59 100       166 return @q unless @$f;
6048 43         96 my $pk = Mpowint($p, $k);
6049 43         105 my $n2 = Mdivint($n, $pk);
6050             return map {
6051 43         118 my $q2 = $_;
  61         94  
6052 61         230 map Mchinese([ $q2, $n2 ], [ $_, $pk ]), @q;
6053             } _allsqrtmodfact($a, $n2, $f);
6054             }
6055              
6056             sub allsqrtmod {
6057 5     5 0 2318 my($A,$n) = @_;
6058 5         31 validate_integer($A);
6059 5         76 validate_integer_abs($n);
6060 5 0       415 return $n ? (0) : () if $n <= 1;
    50          
6061 5         385 $A = Mmodint($A,$n);
6062 5 100       24 my @R = Mis_prime($n) ? _allsqrtmodpk($A,$n,1)
6063             : _allsqrtmodfact($A, $n, [Mfactor_exp($n)]);
6064 5         833 Mvecsort(@R);
6065             }
6066              
6067              
6068             ###############################################################################
6069             # Tonelli-Shanks kth roots
6070             ###############################################################################
6071              
6072             # Algorithm 3.3, step 2 "Find generator"
6073             sub _find_ts_generator {
6074 1     1   3 my ($a, $k, $p) = @_;
6075             # Assume: k > 2, 1 < a < p, p > 2, k prime, p prime
6076              
6077 1         17 my($e,$r) = (0, $p-1);
6078 1         423 while (!($r % $k)) {
6079 2         1326 $e++;
6080 2         9 $r /= $k;
6081             }
6082 1         917 my $ke1 = Mpowint($k, $e-1);
6083 1         3 my($x,$m,$y) = (2,1);
6084 1         5 while ($m == 1) {
6085 1         8 $y = Mpowmod($x, $r, $p);
6086 1 50       363 $m = Mpowmod($y, $ke1, $p) if $y != 1;
6087 1 50       305 croak "bad T-S input" if $x >= $p;
6088 1         168 $x++;
6089             }
6090 1         233 ($y, $m);
6091             }
6092              
6093             sub _ts_rootmod {
6094 1     1   5 my($a, $k, $p, $y, $m) = @_;
6095              
6096 1         5 my($e,$r) = (0, $p-1);
6097 1         458 while (!($r % $k)) {
6098 2         2093 $e++;
6099 2         8 $r /= $k;
6100             }
6101             # p-1 = r * k^e
6102 1         900 my $x = Mpowmod($a, Minvmod($k % $r, $r), $p);
6103 1 50       387 my $A = ($a == 0) ? 0 : Mmulmod(Mpowmod($x,$k,$p), Minvmod($a,$p), $p);
6104              
6105 1 50 33     392 ($y,$m) = _find_ts_generator($a,$k,$p) if $y == 0 && $A != 1;
6106              
6107 1         269 while ($A != 1) {
6108 1         232 my ($l,$T,$z) = (1,$A);
6109 1         5 while ($T != 1) {
6110 1 50       248 return 0 if $l >= $e;
6111 1         4 $z = $T;
6112 1         8 $T = Mpowmod($T, $k, $p);
6113 1         60 $l++;
6114             }
6115             # We want a znlog that takes gorder as well (k=znorder(m,p))
6116 1         9 my $kz = _negmod(znlog($z, $m, $p), $k);
6117 1         8 $m = Mpowmod($m, $kz, $p);
6118 1         16 $T = Mpowmod($y, Mmulint($kz,Mpowint($k,$e-$l)), $p);
6119             # In the loop we always end with l < e, so e always gets smaller
6120 1         37 $e = $l-1;
6121 1         12 $x = Mmulmod($x, $T, $p);
6122 1         297 $y = Mpowmod($T, $k, $p);
6123 1 50       274 return 0 if $y <= 1; # In theory this will never be hit.
6124 1         259 $A = Mmulmod($A, $y, $p);
6125             }
6126 1         66 $x;
6127             }
6128              
6129             sub _compute_generator {
6130             # uncoverable subroutine
6131 0     0   0 my($l, $e, $r, $p) = @_;
6132 0         0 my($m, $lem1, $y) = (1, Mpowint($l, $e-1));
6133 0         0 for (my $x = 2; $m == 1; $x++) {
6134 0         0 $y = Mpowmod($x, $r, $p);
6135 0 0       0 next if $y == 1;
6136 0         0 $m = Mpowmod($y, $lem1, $p);
6137             }
6138 0         0 $y;
6139             }
6140              
6141             sub _rootmod_prime_splitk {
6142 8     8   33 my($a, $k, $p, $refzeta) = @_;
6143              
6144 8 50       32 $$refzeta = 1 if defined $refzeta;
6145 8 50       31 $a = Mmodint($a, $p) if $a >= $p;
6146 8 100 66     1203 return $a if $a == 0 || ($a == 1 && !defined $refzeta);
      66        
6147 7         1523 my $p1 = Msub1int($p);
6148              
6149 7 50       587 if ($k == 2) {
6150 0         0 my $r = _sqrtmod_prime($a,$p);
6151 0 0       0 $$refzeta = (defined $r) ? $p1 : 0 if defined $refzeta;
    0          
6152 0         0 return $r;
6153             }
6154              
6155             # See Algorithm 2.1 of van de Woestijne (2006), or Lindhurst (1997).
6156             # The latter's proposition 7 generalizes to composite p.
6157              
6158 7         62 my $g = Mgcd($k, $p1);
6159 7         22 my $r = $a;
6160              
6161 7 100       27 if ($g != 1) {
6162 1         47 foreach my $fac (Mfactor_exp($g)) {
6163 1         5 my($F,$E) = @$fac;
6164 1 50       6 last if $r == 0;
6165             # uncoverable branch true
6166 1 50       7 if (defined $refzeta) {
6167 0         0 my $V = Mvaluation($p1, $F);
6168 0         0 my $REM = Mdivint($p1, Mpowint($F,$V));
6169 0         0 my $Y = _compute_generator($F, $V, $REM, $p);
6170 0         0 $$refzeta = Mmulmod($$refzeta, Mpowmod($Y, Mpowint($F, $V-$E), $p), $p);
6171             }
6172 1         6 my ($y,$m) = _find_ts_generator($r, $F, $p);
6173 1         7 while ($E-- > 0) {
6174 1         7 $r = _ts_rootmod($r, $F, $p, $y, $m);
6175             }
6176             }
6177             }
6178 7 100       42 if ($g != $k) {
6179 6         31 my($kg, $pg) = (Mdivint($k,$g), Mdivint($p1,$g));
6180 6         39 $r = Mpowmod($r, Minvmod($kg % $pg, $pg), $p);
6181             }
6182 7 50       1194 return $r if Mpowmod($r, $k, $p) == $a;
6183 0 0       0 $$refzeta = 0 if defined $refzeta;
6184 0         0 undef;
6185             }
6186              
6187             sub _rootmod_composite1 {
6188 6     6   25 my($a,$k,$n) = @_;
6189 6         13 my $r;
6190              
6191 6 50 33     62 croak "_rootmod_composite1 bad parameters" if $a < 1 || $k < 2 || $n < 2;
      33        
6192              
6193 6 50       1366 if (Mis_power($a, $k, \$r)) {
6194 0         0 return $r;
6195             }
6196              
6197 6 100       269 if (Mis_prime($n)) {
6198 3         786 return _rootmod_prime_splitk($a,$k,$n,undef);
6199             }
6200              
6201             # We should do this iteratively using cprod
6202 3         424 my @rootmap;
6203 3         20 foreach my $fac (Mfactor_exp($n)) {
6204 10         38 my($F,$E) = @$fac;
6205 10         44 my $FE = Mpowint($F,$E);
6206 10         41 my $A = $a % $FE;
6207 10 100       1965 if ($E == 1) {
6208 5         26 $r = _rootmod_prime_splitk($A,$k,$F,undef)
6209             } else {
6210             # TODO: Fix this. We should do this directly.
6211 5         79 $r = (allrootmod($A, $k, $FE))[0];
6212             }
6213 10 50 33     1250 return undef unless defined $r && Mpowmod($r, $k, $FE) == $A;
6214 10         1512 push @rootmap, [ $r, $FE ];
6215             }
6216 3 50       66 $r = Mchinese(@rootmap) if @rootmap > 1;
6217              
6218             #return (defined $r && Mpowmod($r, $k, $n) == ($a % $n)) ? $r : undef;
6219 3 50 33     58 croak "Bad _rootmod_composite1 root $a,$k,$n" unless defined $r && Mpowmod($r,$k,$n) == ($a % $n);
6220 3         676 $r;
6221             }
6222              
6223             ###############################################################################
6224             # Tonelli-Shanks kth roots alternate version
6225             ###############################################################################
6226              
6227             sub _ts_prime {
6228 2     2   7 my($a, $k, $p, $refzeta) = @_;
6229              
6230 2         7 my($e,$r) = (0, $p-1);
6231 2         426 while (!($r % $k)) {
6232 4         1423 $e++;
6233 4         12 $r /= $k;
6234             }
6235 2         777 my $ke = Mdivint($p-1, $r);
6236              
6237 2         10 my $x = Mpowmod($a, Minvmod($k % $r, $r), $p);
6238 2         382 my $B = Mmulmod(Mpowmod($x, $k, $p), Minvmod($a, $p), $p);
6239              
6240 2         171 my($T,$y,$t,$A) = (2,1);
6241 2         6 while ($y == 1) {
6242 3         9 $t = Mpowmod($T, $r, $p);
6243 3         388 $y = Mpowmod($t, Mdivint($ke,$k), $p);
6244 3         284 $T++;
6245             }
6246 2         256 while ($ke != $k) {
6247 2         10 $ke = Mdivint($ke, $k);
6248 2         5 $T = $t;
6249 2         11 $t = Mpowmod($t, $k, $p);
6250 2         297 $A = Mpowmod($B, Mdivint($ke,$k), $p);
6251 2         16 while ($A != 1) {
6252 4         271 $x = Mmulmod($x, $T, $p);
6253 4         268 $B = Mmulmod($B, $t, $p);
6254 4         52 $A = Mmulmod($A, $y, $p);
6255             }
6256             }
6257 2 50       57 $$refzeta = $t if defined $refzeta;
6258 2         11 $x;
6259             }
6260              
6261             sub _rootmod_prime {
6262             # uncoverable subroutine
6263 0     0   0 my($a, $k, $p) = @_;
6264              
6265             # p must be a prime, k must be a prime. Otherwise UNDEFINED.
6266 0 0       0 $a %= $p if $a >= $p;
6267              
6268 0 0 0     0 return $a if $p == 2 || $a == 0;
6269 0 0       0 return _sqrtmod_prime($a, $p) if $k == 2;
6270              
6271             # If co-prime, there is exactly one root.
6272 0         0 my $g = Mgcd($k, $p-1);
6273 0 0       0 return Mpowmod($a, Minvmod($k % ($p-1), $p-1), $p) if $g == 1;
6274             # Check generalized Euler's criterion
6275 0 0       0 return undef if Mpowmod($a, Mdivint($p-1, $g), $p) != 1;
6276              
6277 0         0 _ts_prime($a, $k, $p);
6278             }
6279              
6280             sub _rootmod_prime_power {
6281             # uncoverable subroutine
6282 0     0   0 my($a,$k,$p,$e) = @_; # prime k, prime p
6283              
6284 0 0       0 return _sqrtmod_prime_power($a, $p, $e) if $k == 2;
6285 0 0       0 return _rootmod_prime($a, $k, $p) if $e == 1;
6286              
6287 0         0 my $n = Mpowint($p,$e);
6288 0         0 my $pk = Mpowint($p,$k);
6289              
6290 0 0       0 return 0 if ($a % $n) == 0;
6291              
6292 0 0       0 if (($a % $pk) == 0) {
6293 0         0 my $apk = Mdivint($a, $pk);
6294 0         0 my $s = _rootmod_prime_power($apk, $k, $p, $e-$k);
6295 0 0       0 return (defined $s) ? Mmulint($s,$p) : undef;
6296             }
6297              
6298 0 0       0 return undef if ($a % $p) == 0;
6299              
6300 0 0 0     0 my $ered = ($p > 2 || $e < 5) ? ($e+1) >> 1 : ($e+3) >> 1;
6301 0         0 my $s = _rootmod_prime_power($a, $k, $p, $ered);
6302 0 0       0 return undef if !defined $s;
6303              
6304 0 0       0 my $np = ($p == $k) ? Mmulint($n,$p) : $n;
6305 0         0 my $t = Mpowmod($s, $k-1, $np);
6306 0         0 my $t1 = Msubmod($a, Mmulmod($t,$s,$np), $np);
6307 0         0 my $t2 = Mmulmod($k, $t, $np);
6308 0         0 my $gcd = Mgcd($t1, $t2);
6309 0         0 my $r = Maddmod($s,Mdivmod(Mdivint($t1,$gcd),Mdivint($t2,$gcd),$n),$n);
6310 0 0       0 return ((Mpowmod($r,$k,$n) == ($a % $n)) ? $r : undef);
6311             }
6312              
6313             sub _rootmod_kprime {
6314             # uncoverable subroutine
6315 0     0   0 my($a,$k,$n,@nf) = @_; # k prime, n factored into f^e,f^e,...
6316              
6317 0         0 my($N,$r) = (1,0);
6318 0         0 foreach my $F (@nf) {
6319 0         0 my($f,$e) = @$F;
6320 0         0 my $fe = Mpowint($f, $e);
6321 0         0 my $s = _rootmod_prime_power($a, $k, $f, $e);
6322 0 0       0 return undef unless defined $s;
6323 0         0 my $inv = Minvmod($N, $fe);
6324 0         0 my $t = Mmulmod($inv, Msubmod($s % $fe, $r % $fe, $fe), $fe);
6325 0         0 $r = Mmuladdmod($N, $t, $r, $n);
6326 0         0 $N = Mmulint($N, $fe);
6327             }
6328 0         0 $r;
6329             }
6330              
6331             sub _rootmod_composite2 {
6332             # uncoverable subroutine
6333 0     0   0 my($a,$k,$n) = @_;
6334              
6335 0 0 0     0 croak "_rootmod_composite2 bad parameters" if $a < 1 || $k < 2 || $n < 2;
      0        
6336              
6337 0         0 my @nf = Mfactor_exp($n);
6338              
6339 0 0       0 return _rootmod_kprime($a, $k, $n, @nf) if Mis_prime($k);
6340              
6341 0         0 my $r = $a;
6342 0         0 foreach my $kf (Mfactor($k)) {
6343 0         0 $r = _rootmod_kprime($r, $kf, $n, @nf);
6344 0 0       0 if (!defined $r) {
6345             # Choose one. The former is faster but makes more intertwined code.
6346 0         0 return _rootmod_composite1($a,$k,$n);
6347             #return (allrootmod($a,$k,$n))[0];
6348             }
6349             }
6350 0 0 0     0 croak "Bad _rootmod_composite2 root $a,$k,$n" unless defined $r && Mpowmod($r,$k,$n) == ($a % $n);
6351 0         0 $r;
6352             }
6353              
6354              
6355             ###############################################################################
6356             # Modular k-th root
6357             ###############################################################################
6358              
6359             sub rootmod {
6360 8     8 0 66007 my($a,$k,$n) = @_;
6361 8         48 validate_integer($a);
6362 8         135 validate_integer($k);
6363 8         220 validate_integer_abs($n);
6364 8 50       888 return (undef,0)[$n] if $n <= 1;
6365 8         825 $a = Mmodint($a,$n);
6366              
6367             # Be careful with zeros, as we can't divide or invert them.
6368 8 100       32 if ($a == 0) {
6369 1 50       10 return ($k <= 0) ? undef : 0;
6370             }
6371 7 100       564 if ($k < 0) {
6372 1         7 $a = Minvmod($a, $n);
6373 1 50 33     9 return undef unless defined $a && $a > 0;
6374 1         2 $k = -$k;
6375             }
6376 7 100 66     36 return undef if $k == 0 && $a != 1;
6377 6 50 33     47 return 1 if $k == 0 || $a == 1;
6378 6 50       530 return $a if $k == 1;
6379              
6380             # Choose either one based on performance.
6381 6         28 my $r = _rootmod_composite1($a, $k, $n);
6382             #my $r = _rootmod_composite2($a, $k, $n);
6383 6 50 33     646 $r = $n-$r if defined $r && $k == 2 && ($n-$r) < $r; # Select smallest root
      33        
6384 6         56 $r;
6385             }
6386              
6387             ###############################################################################
6388             # All modular k-th roots
6389             ###############################################################################
6390              
6391             sub _allrootmod_cprod {
6392 102     102   320 my($aroots1, $p1, $aroots2, $p2) = @_;
6393 102         259 my($t, $n, $inv);
6394              
6395 102         421 $n = mulint($p1, $p2);
6396 102         733 $inv = Minvmod($p1, $p2);
6397 102 50       272 croak("CRT has undefined inverse") unless defined $inv;
6398              
6399 102         177 my @roots;
6400 102         253 for my $q1 (@$aroots1) {
6401 236         444 for my $q2 (@$aroots2) {
6402 306         870 $t = Mmulmod($inv, Msubmod($q2, $q1, $p2), $p2);
6403 306         852 $t = Mmuladdmod($p1, $t, $q1, $n);
6404 306         1956 push @roots, $t;
6405             }
6406             }
6407 102         444 return @roots;
6408             }
6409              
6410             sub _allrootmod_prime {
6411 144     144   320 my($a,$k,$p) = @_; # prime k, prime p
6412 144 100       407 $a %= $p if $a >= $p; #$a = Mmodint($a,$p) if $a >= $p;
6413              
6414 144 100 100     2483 return ($a) if $p == 2 || $a == 0;
6415              
6416             # If co-prime, there is exactly one root.
6417 78         1060 my $g = Mgcd($k, $p-1);
6418 78 100       250 if ($g == 1) {
6419 76         354 my $r = Mpowmod($a, Minvmod($k % ($p-1), $p-1), $p);
6420 76         486 return ($r);
6421             }
6422              
6423             # Check generalized Euler's criterion
6424 2 50       10 return () if Mpowmod($a, Mdivint($p-1, $g), $p) != 1;
6425              
6426             # Special case for p=3 for performance
6427 2 50       135 return (1,2) if $p == 3;
6428              
6429             # A trivial brute force search:
6430             # return grep { Mpowmod($_,$k,$p) == $a } 0 .. $p-1;
6431              
6432             # Call one of the general TS solvers that also allow us to get all the roots.
6433 2         245 my $z;
6434             #my $r = _rootmod_prime_splitk($a, $k, $p, \$z);
6435 2         11 my $r = _ts_prime($a, $k, $p, \$z);
6436 2 50 33     8 croak "allrootmod: failed to find root" if $z==0 || Mpowmod($r,$k,$p) != $a;
6437 2         57 my @roots = ($r);
6438 2         10 my $r2 = Mmulmod($r,$z,$p);
6439 2   66     307 while ($r2 != $r && @roots < $k) {
6440 6         448 push @roots, $r2;
6441 6         18 $r2 = Mmulmod($r2, $z, $p);
6442             }
6443 2 50       332 croak "allrootmod: excess roots found" if $r2 != $r;
6444 2         65 return @roots;
6445             }
6446              
6447             sub _allrootmod_prime_power {
6448 178     178   472 my($a,$k,$p,$e) = @_; # prime k, prime p
6449              
6450 178 100       591 return _allrootmod_prime($a, $k, $p) if $e == 1;
6451              
6452 106 50 33     631 my $n = ($e<=13 && $p<=13)||($e<=5 && $p<=1000) ?int($p**$e):Mpowint($p,$e);
6453 106 50 33     511 my $pk = ($k<=13 && $p<=13)||($k<=5 && $p<=1000) ?int($p**$k):Mpowint($p,$k);
6454 106         180 my @roots;
6455              
6456 106 50       289 if (($a % $n) == 0) {
6457 0         0 my $t = Mdivint($e-1, $k) + 1;
6458 0         0 my $nt = Mpowint($p, $t);
6459 0         0 my $nr = Mpowint($p, $e-$t);
6460 0         0 @roots = map { Mmulmod($_, $nt, $n) } 0 .. $nr-1;
  0         0  
6461 0         0 return @roots;
6462             }
6463              
6464 106 50       737 if (($a % $pk) == 0) {
6465 0         0 my $apk = Mdivint($a, $pk);
6466 0         0 my $pe1 = Mpowint($p, $k-1);
6467 0         0 my $pek = Mpowint($p, $e-$k+1);
6468 0         0 my @roots2 = _allrootmod_prime_power($apk, $k, $p, $e-$k);
6469 0         0 for my $r (@roots2) {
6470 0         0 my $rp = Mmulmod($r, $p, $n);
6471 0         0 push @roots, Mmuladdmod($_, $pek, $rp, $n) for 0 .. $pe1-1;
6472             }
6473 0         0 return @roots;
6474             }
6475              
6476 106 50       602 return () if ($a % $p) == 0;
6477              
6478 106         628 my $np = Mmulint($n,$p);
6479 106 50 33     450 my $ered = ($p > 2 || $e < 5) ? ($e+1) >> 1 : ($e+3) >> 1;
6480 106         369 my @roots2 = _allrootmod_prime_power($a, $k, $p, $ered);
6481              
6482 106 100       324 if ($k != $p) {
6483 40         113 for my $s (@roots2) {
6484 40         205 my $t = Mpowmod($s, $k-1, $n);
6485 40         421 my $t1 = Msubmod($a, Mmulmod($t,$s,$n), $n);
6486 40         151 my $t2 = Mmulmod($k, $t, $n);
6487 40         142 my $gcd = Mgcd($t1, $t2);
6488 40         282 my $r = Maddmod($s,Mdivmod(Mdivint($t1,$gcd),Mdivint($t2,$gcd),$n),$n);
6489 40         177 push @roots, $r;
6490             }
6491             } else {
6492 66         156 my @rootst;
6493 66         200 for my $s (@roots2) {
6494 130         467 my $t = Mpowmod($s, $k-1, $np);
6495 130         375 my $t1 = Msubmod($a, Mmulmod($t,$s,$np), $np);
6496 130         421 my $t2 = Mmulmod($k, $t, $np);
6497 130         429 my $gcd = Mgcd($t1, $t2);
6498 130         523 my $r = Maddmod($s,Mdivmod(Mdivint($t1,$gcd), Mdivint($t2,$gcd),$n),$n);
6499 130 50       468 push @rootst, $r if Mpowmod($r, $k, $n) == ($a % $n);
6500             }
6501 66         220 my $ndivp = Mdivint($n,$p);
6502 66         226 my $rset = [];
6503 66         171 for my $r (@rootst) {
6504             Msetinsert($rset, Mmulmod($r, Mmuladdmod($_, $ndivp, 1, $n), $n))
6505 130         773 for 0 .. $k-1;
6506             }
6507 66         264 @roots = @$rset;
6508             }
6509 106         477 return @roots;
6510             }
6511              
6512             sub _allrootmod_kprime {
6513 55     55   217 my($a,$k,$n,@nf) = @_; # k prime, n factored into f^e,f^e,...
6514              
6515 55 100       192 return _allsqrtmodfact($a, $n, \@nf) if $k == 2;
6516              
6517 42         80 my $N = 1;
6518 42         76 my @roots;
6519 42         90 foreach my $F (@nf) {
6520 144         545 my($f,$e) = @$F;
6521 144 100       666 my @roots2 = ($e==1) ? _allrootmod_prime($a, $k, $f)
6522             : _allrootmod_prime_power($a, $k, $f, $e);
6523 144 50       445 return () unless @roots2;
6524 144 100 66     786 my $fe = ($e <= 13 && $f <= 13) ? int($f**$e) : Mpowint($f, $e);
6525 144 100       422 if (scalar(@roots) == 0) {
6526 42         108 @roots = @roots2;
6527             } else {
6528 102         493 @roots = _allrootmod_cprod(\@roots, $N, \@roots2, $fe);
6529             }
6530 144         843 $N = Mmulint($N, $fe);
6531             }
6532              
6533 42         968 return @roots;
6534             }
6535              
6536             sub allrootmod {
6537 9     9 0 2499 my($A,$k,$n) = @_;
6538 9         39 validate_integer($A);
6539 9         139 validate_integer($k);
6540 9         79 validate_integer_abs($n);
6541              
6542 9 50       417 return () if $n == 0;
6543 9         461 $A = Mmodint($A,$n);
6544              
6545 9 50 33     56 return () if $k <= 0 && $A == 0;
6546              
6547 9 50       33 if ($k < 0) {
6548 0         0 $A = Minvmod($A, $n);
6549 0 0 0     0 return () unless defined $A && $A > 0;
6550 0         0 $k = -$k;
6551             }
6552              
6553             # TODO: For testing
6554             #my @roots = sort { $a <=> $b }
6555             # grep { Mpowmod($_,$k,$n) == $A } 0 .. $n-1;
6556             #return @roots;
6557              
6558 9 50 33     47 return ($A) if $n <= 2 || $k == 1;
6559 9 0       429 return ($A == 1) ? (0..$n-1) : () if $k == 0;
    50          
6560              
6561 9         19 my @roots;
6562 9 100       54 my @nf = Mis_prime($n) ? ([$n,1]) : Mfactor_exp($n);
6563              
6564 9 100       392 if (Mis_prime($k)) {
6565 6         24 @roots = _allrootmod_kprime($A, $k, $n, @nf);
6566             } else {
6567 3         9 @roots = ($A);
6568 3         31 for my $primek (Mfactor($k)) {
6569 9         21 my @rootsnew = ();
6570 9         20 for my $r (@roots) {
6571 49         254 push @rootsnew, _allrootmod_kprime($r, $primek, $n, @nf);
6572             }
6573 9         74 @roots = @rootsnew;
6574             }
6575             }
6576              
6577 9         62 Mvecsort(@roots);
6578             }
6579              
6580             ################################################################################
6581             ################################################################################
6582              
6583             sub _modabsint {
6584 516     516   2080 my($a, $n) = @_;
6585 516 50       1307 if ($n <= 1) {
6586 0 0 0     0 if ($n < 0) { $n = tobigint($n) if $n <= INTMIN && !ref($n); $n = -$n; }
  0 0       0  
  0         0  
6587 0 0       0 return (undef,0)[$n] if $n <= 1;
6588             }
6589 516 100 66     3488 if ($n < INTMAX && $a < INTMAX && $a > INTMIN) {
      100        
6590 512 50       1298 $a = $n - ((-$a) % $n) if $a < 0;
6591 512 100       1403 $a %= $n if $a >= $n;
6592             } else {
6593 4         837 $a = tobigint($a) % $n;
6594 4 100       1310 $a = _bigint_to_int($a) if $a <= INTMAX;
6595             }
6596 516         2408 $a;
6597             }
6598              
6599             sub addmod {
6600 1454     1454 0 7409 my($a, $b, $n) = @_;
6601 1454 100       3928 if ($n <= 1) {
6602 1 50 33     3 if ($n < 0) { $n = tobigint($n) if $n <= INTMIN && !ref($n); $n = -$n; }
  1 50       8  
  1         4  
6603 1 50       78 return (undef,0)[$n] if $n <= 1;
6604             }
6605 1454 100 100     108053 if ($n <= INTMAX && $a <= INTMAX && $b <= INTMAX && $a >= INTMIN && $b >= INTMIN) {
      66        
      66        
      66        
6606 987 50       1761 $a = $n - ((-$a) % $n) if $a < 0;
6607 987 50       2122 $b = $n - ((-$b) % $n) if $b < 0;
6608 987 100       2142 $a %= $n if $a >= $n;
6609 987 100       1780 $b %= $n if $b >= $n;
6610 987 100       3137 return $n-$a > $b ? $a+$b
    100          
6611             : $a > $b ? ($a-$n)+$b
6612             : ($b-$n)+$a;
6613             }
6614             # Impl 1. Make $a a bigint and let things promote. Fastest.
6615 467         103155 $a = tobigint($a);
6616 467 50       1973 if (ref($a) eq 'Math::Pari') { $b = tobigint($b); $n = tobigint($n); }
  0         0  
  0         0  
6617 467         2001 my $r = ($a + $b) % $n;
6618 467 100       208374 return $r <= INTMAX ? _bigint_to_int($r) : $r;
6619              
6620             # Impl 2. Use Maddint but mod with a $n as a bigint.
6621             #my $r = Maddint($a,$b) % tobigint($n);
6622             #return $r <= INTMAX ? _bigint_to_int($r) : $r;
6623              
6624             # Impl 3. Prefered, but slowest. Probably fine when we use amagic in XS.
6625             #Mmodint(Maddint($a,$b),$n);
6626             }
6627             sub submod {
6628 731     731 0 5396 my($a, $b, $n) = @_;
6629 731 100       1902 if ($n <= 1) {
6630 1 50 33     4 if ($n < 0) { $n = tobigint($n) if $n <= INTMIN && !ref($n); $n = -$n; }
  1 50       8  
  1         4  
6631 1 50       72 return (undef,0)[$n] if $n <= 1;
6632             }
6633 731 100 100     28533 if ($n <= INTMAX && $a <= INTMAX && $b <= INTMAX && $a >= INTMIN && $b >= INTMIN) {
      66        
      66        
      66        
6634 614 50       1262 $a = $n - ((-$a) % $n) if $a < 0;
6635 614 50       1100 $b = $n - ((-$b) % $n) if $b < 0;
6636 614 100       1213 $a %= $n if $a >= $n;
6637 614 100       1226 $b %= $n if $b >= $n;
6638 614         1077 $b = $n-$b; # negate b then we add as above
6639 614 100       2614 return $n-$a > $b ? $a+$b
    100          
6640             : $a > $b ? ($a-$n)+$b
6641             : ($b-$n)+$a;
6642             }
6643 117         26374 $a = tobigint($a);
6644 117 50       609 if (ref($a) eq 'Math::Pari') { $b = tobigint($b); $n = tobigint($n); }
  0         0  
  0         0  
6645 117         536 my $r = ($a - $b) % $n;
6646 117 100       49622 return $r <= INTMAX ? _bigint_to_int($r) : $r;
6647             }
6648              
6649             sub mulmod {
6650 16364     16364 0 62776 my($a, $b, $n) = @_;
6651             #if ($n <= 1) { # ABS(n) and handle mod 0 | mod 1.
6652             # if ($n < 0) { $n = tobigint($n) if $n <= INTMIN && !ref($n); $n = -$n; }
6653             # return (undef,0)[$n] if $n <= 1;
6654             #}
6655 16364 100       58119 if ($n <= 1) {
6656 1 50       4 return (undef,0)[$n] if $n >= 0;
6657 1 50 33     8 $n = tobigint($n) if $n <= INTMIN && !ref($n);
6658 1         4 $n = -$n;
6659 1 50       70 return 0 if $n == 1;
6660             }
6661              
6662             # If n is a native int, we can reduce a and b then do everything native
6663 16364 100       2766242 if ($n < INTMAX) {
6664 4156 100 33     25720 if ($a >= INTMAX || $a < 0 || $b >= INTMAX || $b < 0) {
      33        
      66        
6665 1 50 33     7 $a = _bigint_to_int(tobigint($a) % $n) if $a >= INTMAX || $a < 0;
6666 1 50 33     12 $b = _bigint_to_int(tobigint($b) % $n) if $b >= INTMAX || $b < 0;
6667             }
6668 4156         9551 return _mulmod($a,$b,$n);
6669             }
6670              
6671             # Try GMP
6672             return reftyped($_[0], Math::Prime::Util::GMP::mulmod($a,$b,$n))
6673 12208 50       2849987 if $Math::Prime::Util::_GMPfunc{"mulmod"};
6674              
6675 12208         29051 my $refn = ref($n);
6676 12208 100       33159 if (!$refn) {
6677 2         10 $n = tobigint($n);
6678 2         6 $refn = ref($n);
6679             }
6680 12208 100       51426 $a = $refn->new("$a") unless ref($a) eq $refn;
6681 12208 100       798089 $b = $refn->new("$b") unless ref($b) eq $refn;
6682 12208         644361 my $r = ($a * $b) % $n;
6683 12208 100       6736522 return $r <= INTMAX ? _bigint_to_int($r) : $r;
6684             }
6685              
6686             sub _bi_powmod {
6687 979     979   3400 my($a, $b, $n) = @_;
6688 979 50       3470 croak "_bi_powmod must have positive exponent" if $b < 0;
6689 979 50       137143 croak "_bi_powmod must have n > 1" if $n <= 1;
6690              
6691 979         166339 my $refn = ref($n);
6692 979 100       3715 if (!$refn) {
6693 155         5403 $n = tobigint($n);
6694 155         429 $refn = ref($n);
6695             }
6696 979 100       4118 $b = $refn->new($b) unless ref($b) eq $refn;
6697              
6698 979         34958 my $r = $refn->new($a);
6699              
6700 979 50       97300 if ($refn eq 'Math::GMPz') {
    50          
    50          
    0          
6701 0         0 Math::GMPz::Rmpz_powm($r, $r, $b, $n);
6702             } elsif ($refn eq 'Math::GMP') {
6703 0         0 $r = $r->powm_gmp($b,$n);
6704             } elsif ($refn eq 'Math::BigInt') {
6705 979 50       6923 $r->bmod($n) if $BIGINTVERSION < 1.999;
6706 979         164437 $r->bmodpow($b,$n);
6707             } elsif ($refn eq 'Math::Pari') {
6708 0 0       0 $a = $refn->new("$a") unless ref($a) eq $refn;
6709 0 0       0 $b = $refn->new("$b") unless ref($b) eq $refn;
6710 0 0 0     0 if ($n <= 4294967295 && $b > 4294967295) {
6711 0         0 $b = $b % Math::Prime::Util::carmichael_lambda($n);
6712             }
6713 0         0 $r = Math::Pari::lift(Math::Pari::gpow(Math::Pari::Mod($a,$n),$b));
6714             } else {
6715 0         0 $r->bmodpow("$b","$n");
6716             }
6717 979         53637639 $r;
6718             }
6719              
6720             sub powmod {
6721 988     988 0 5160 my($a, $b, $n) = @_;
6722 988 50       4844 if ($n <= 1) {
6723 0 0 0     0 if ($n < 0) { $n = tobigint($n) if $n <= INTMIN && !ref($n); $n = -$n; }
  0 0       0  
  0         0  
6724 0 0       0 return (undef,0)[$n] if $n <= 1;
6725             }
6726 988 0       77664 return ($b > 0) ? 0 : 1 if $a == 0;
    50          
6727              
6728 988 50       13435 if ($Math::Prime::Util::_GMPfunc{"powmod"}) {
6729 0         0 my $r = Math::Prime::Util::GMP::powmod($a,$b,$n);
6730 0 0       0 return (defined $r) ? reftyped($_[0], $r) : undef;
6731             }
6732              
6733             # If the exponent is negative: a=1/a ; b=-b
6734 988 100       2896 if ($b < 0) {
6735 1         6 $a = Minvmod($a,$n);
6736 1 50       4 return undef unless defined $a;
6737 1 50 33     12 $b = tobigint($b) if $b <= INTMIN && !ref($b);
6738 1         7 $b = -$b;
6739             }
6740              
6741 988 100       48527 if ($b <= 8) {
6742 565 100       1379 return 1 if $b == 0;
6743 551 100       1314 return _modabsint($a,$n) if $b == 1;
6744 483 100       5706 return Mmulmod($a,$a,$n) if $b == 2;
6745             # For exponents 3-8, this can be 20x faster for native n
6746 266 50 66     1490 if (!ref($n) && $a <= 31622776 && $a >= -31622776) {
      66        
6747 224         512 my $a2 = int($a*$a);
6748 224 100       757 return Mmulmod($a2,$a,$n) if $b == 3;
6749 44         168 my $a4 = Mmulmod($a2,$a2,$n);
6750 44 100       165 return $a4 if $b == 4;
6751 32 100       83 return Mmulmod($a4,$a,$n) if $b == 5;
6752 17 100       76 return Mmulmod($a4,$a2,$n) if $b == 6;
6753 11 100       51 return Mmulmod($a4,Mmulmod($a2,$a,$n),$n) if $b == 7;
6754 6 50       47 return Mmulmod($a4,$a4,$n) if $b == 8;
6755             }
6756             }
6757              
6758 465         41823 my $r = _bi_powmod($a,$b,$n);
6759 465 100       5866 return $r <= INTMAX ? _bigint_to_int($r) : $r;
6760             }
6761              
6762             sub muladdmod {
6763 12556     12556 0 105974 my($a, $b, $c, $n) = @_;
6764 12556 50       43055 if ($n <= 1) {
6765 0 0       0 $n = Mnegint($n) if $n < 0;
6766 0 0       0 return (undef,0)[$n] if $n <= 1;
6767             }
6768              
6769 12556 50 100     2424858 if (!ref($n) && $n <= INTMAX
      66        
      100        
      66        
      66        
      33        
      33        
6770             && $a <= INTMAX && $b <= INTMAX && $c <= INTMAX
6771             && $a >= INTMIN && $b >= INTMIN && $c >= INTMIN) {
6772 2161 50       4380 $a = $n - ((-$a) % $n) if $a < 0;
6773 2161 50       3984 $b = $n - ((-$b) % $n) if $b < 0;
6774 2161 50       4030 $c = $n - ((-$c) % $n) if $c < 0;
6775             #$c %= $n if $c >= $n; # For mulsubmod
6776 2161         4850 return _addmod(_mulmod($a,$b,$n),$c,$n);
6777             }
6778             return reftyped($_[0], Math::Prime::Util::GMP::muladdmod($a,$b,$c,$n))
6779 10395 50       35381 if $Math::Prime::Util::_GMPfunc{"muladdmod"};
6780              
6781 10395 100       27346 $n = tobigint($n) unless ref($n);
6782 10395 50       29176 if (ref($n) eq 'Math::Pari') {
6783 0 0       0 $a = tobigint("$a") unless ref($a) eq 'Math::Pari';
6784 0 0       0 $b = tobigint("$b") unless ref($b) eq 'Math::Pari';
6785             } else {
6786 10395 100 66     53960 $a = tobigint($a) unless ref($a) || ref($b);
6787             }
6788 10395 100       41260 $c = tobigint($c) unless ref($c);
6789 10395         40364 my $r = (($a * $b) + $c) % $n;
6790 10395 100       8776892 return $r <= INTMAX ? _bigint_to_int($r) : $r;
6791             }
6792             sub mulsubmod {
6793 19456     19456 0 83222 my($a, $b, $c, $n) = @_;
6794 19456 50       76730 if ($n <= 1) {
6795 0 0       0 $n = Mnegint($n) if $n < 0;
6796 0 0       0 return (undef,0)[$n] if $n <= 1;
6797             }
6798              
6799 19456 50 100     4191833 if (!ref($n) && $n <= INTMAX
      66        
      100        
      66        
      66        
      33        
      33        
6800             && $a <= INTMAX && $b <= INTMAX && $c <= INTMAX
6801             && $a >= INTMIN && $b >= INTMIN && $c >= INTMIN) {
6802 1275 50       2567 $a = $n - ((-$a) % $n) if $a < 0;
6803 1275 50       2223 $b = $n - ((-$b) % $n) if $b < 0;
6804 1275 50       2326 $c = $n - ((-$c) % $n) if $c < 0;
6805 1275 50       2570 $c = ($c < $n) ? $n-$c : $n-($c % $n); # $c = -$c (mod n)
6806 1275         2595 return _addmod(_mulmod($a,$b,$n),$c,$n);
6807             }
6808             return reftyped($_[0], Math::Prime::Util::GMP::mulsubmod($a,$b,$c,$n))
6809 18181 50       58660 if $Math::Prime::Util::_GMPfunc{"mulsubmod"};
6810              
6811             # return Msubmod(Mmulmod($a,$b,$n),$c,$n);
6812              
6813 18181 100       49263 $n = tobigint($n) unless ref($n);
6814 18181 50       49991 if (ref($n) eq 'Math::Pari') {
6815 0 0       0 $a = tobigint("$a") unless ref($a) eq 'Math::Pari';
6816 0 0       0 $b = tobigint("$b") unless ref($b) eq 'Math::Pari';
6817             } else {
6818 18181 100 100     64931 $a = tobigint($a) unless ref($a) || ref($b);
6819             }
6820 18181 100       77190 $c = tobigint($c) unless ref($c);
6821 18181         67452 my $r = (($a * $b) - $c) % $n;
6822 18181 100       18468422 return $r <= INTMAX ? _bigint_to_int($r) : $r;
6823             }
6824              
6825             sub invmod {
6826 684     684 0 3320 my($a,$n) = @_;
6827 684 100       2145 if ($n <= 1) {
6828 1 50 33     5 if ($n < 0) { $n = tobigint($n) if $n <= INTMIN && !ref($n); $n = -$n; }
  1 50       5  
  1         2  
6829 1 50       4 return (undef,0)[$n] if $n <= 1;
6830             }
6831 684 50       53819 return if $a == 0;
6832              
6833 684 100       28930 if ($n < INTMAX) { # Fast all native math
6834 448         1478 my($t,$nt,$r,$nr) = (0, 1, $n, _modabsint($a,$n));
6835 448         1270 while ($nr != 0) {
6836             # Use mod before divide to force correct behavior with high bit set
6837 1598         5235 my $quot = int( ($r-($r % $nr))/$nr );
6838 1598         3393 ($nt,$t) = ($t-$quot*$nt,$nt);
6839 1598         4479 ($nr,$r) = ($r-$quot*$nr,$nr);
6840             }
6841 448 100       1961 return $r > 1 ? undef
    100          
6842             : $t < 0 ? $t+$n
6843             : $t;
6844             }
6845              
6846 236         57343 $n = tobigint($n);
6847 236         697 $a = tobigint($a) % $n;
6848 236         44725 my $refn = ref($n);
6849 236         582 my $I;
6850              
6851 236 50       886 if ($refn eq 'Math::BigInt') {
    0          
    0          
    0          
6852 236         853 $I = $a->copy->bmodinv($n);
6853 236 100 66     804242 $I = undef if defined $I && !$I->is_int();
6854             } elsif ($refn eq 'Math::GMPz') {
6855 0         0 $I = Math::GMPz->new();
6856 0         0 Math::GMPz::Rmpz_invert($I, $a, $n);
6857 0 0 0     0 $I = undef if defined $I && $I == 0;
6858             } elsif ($refn eq 'Math::GMP') {
6859 0         0 $I = $a->gmp_copy->bmodinv($n);
6860 0 0 0     0 $I = undef if defined $I && $I == 0;
6861             } elsif ($refn eq 'Math::Pari') {
6862 0         0 $I = eval{1/Math::Pari::Mod($a,$n)};
  0         0  
6863 0 0 0     0 $I = defined $I && $I != 0 ? Math::Pari::lift($I) : undef;
6864             } else {
6865 0         0 $I = Math::BigInt->new("$a")->bmodinv("$n");
6866 0 0 0     0 $I = undef if defined $I && !$I->is_int();
6867 0 0       0 $I = tobigint("$I") if defined $I;
6868             }
6869 236 100 100     4535 $I = _bigint_to_int($I) if defined $I && $I <= INTMAX;
6870 236         58994 return $I;
6871             }
6872              
6873             sub divmod {
6874 199     199 0 1535 my($a, $b, $n) = @_;
6875 199 50       650 if ($n <= 1) {
6876 0 0 0     0 if ($n < 0) { $n = tobigint($n) if $n <= INTMIN && !ref($n); $n = -$n; }
  0 0       0  
  0         0  
6877 0 0       0 return (undef,0)[$n] if $n <= 1;
6878             }
6879              
6880 199         907 my $invb = Minvmod($b,$n);
6881 199 50       506 return undef unless defined $invb;
6882 199         570 return Mmulmod($a,$invb,$n);
6883             }
6884              
6885             sub negmod {
6886 2     2 0 5487 my($a,$n) = @_;
6887 2         9 validate_integer($a);
6888 2         44 validate_integer($n);
6889              
6890 2 50       28 if ($n <= 0) {
6891 0 0       0 return undef if $n == 0; # standard mod behavior with n = 0
6892 0 0 0     0 $n = tobigint($n) if $n <= INTMIN && !ref($n);
6893 0         0 $n = -$n; # we use |n|, unlike modint
6894             }
6895             # Easy:
6896             # Msubmod(0, $a, $n);
6897              
6898 2 50 33     191 $a = Mmodint($a,$n) if $a >= $n || $a < 0;
6899 2 50       14 return $a ? $n-$a : 0;
6900             }
6901              
6902             # No validation.
6903             sub _negmod {
6904 5     5   21 my($a,$n) = @_;
6905 5 50       25 if ($n <= 0) {
6906 0 0       0 return undef if $n == 0;
6907 0 0 0     0 $n = tobigint($n) if $n <= INTMIN && !ref($n);
6908 0         0 $n = -$n;
6909             }
6910 5 50 33     31 $a = Mmodint($a,$n) if $a >= $n || $a < 0;
6911 5 50       21 return $a ? $n-$a : 0;
6912             }
6913              
6914             ################################################################################
6915             ################################################################################
6916              
6917             # no validation, x is allowed to be negative, y must be >= 0
6918             sub _gcd_ui {
6919 1339     1339   2847 my($x, $y) = @_;
6920 1339 100       2849 if ($y < $x) { ($x, $y) = ($y, $x); }
  918 50       1964  
6921 0         0 elsif ($x < 0) { $x = -$x; }
6922 1339         3076 while ($y > 0) {
6923 10763         27021 ($x, $y) = ($y, $x % $y);
6924             }
6925 1339         2668 $x;
6926             }
6927              
6928             sub _powerof_ret {
6929 1031     1031   3067 my($n, $refp) = @_;
6930              
6931 1031         2002 my $k = 2;
6932 1031         1665 while (1) {
6933 4713         8391 my $rk;
6934 4713         21810 my $r = Mrootint($n, $k, \$rk);
6935 4713 100       17373 return 0 if $r == 1;
6936 4378 100       104656 if ($rk == $n) {
6937 696         30689 my $next = _powerof_ret($r, $refp);
6938 696 100 100     3230 $$refp = $r if !$next && defined $refp;
6939 696 100       1633 $k *= $next if $next != 0;
6940 696         3201 return $k;
6941             }
6942 3682         195835 $k = Mnext_prime($k);
6943             }
6944 0         0 0;
6945             }
6946              
6947             sub is_power {
6948 345     345 0 326781 my ($n, $a, $refp) = @_;
6949 345         3332 validate_integer($n);
6950 345 100       3298 if (!defined $a) { $a = 0; } else { validate_integer_nonneg($a); }
  147         492  
  198         699  
6951 345 50 66     2141 croak("is_power third argument not a scalar reference") if defined($refp) && !ref($refp);
6952 345 100 100     1574 return 0 if abs($n) <= 3 && !$a;
6953              
6954 343 0 0     108815 if ($Math::Prime::Util::_GMPfunc{"is_power"} &&
      33        
6955             ($Math::Prime::Util::GMP::VERSION >= 0.42 ||
6956             ($Math::Prime::Util::GMP::VERSION >= 0.28 && $n > 0))) {
6957 0         0 my $k = Math::Prime::Util::GMP::is_power($n,$a);
6958 0 0       0 return 0 unless $k > 0;
6959 0 0       0 if (defined $refp) {
6960 0 0       0 $a = $k unless $a;
6961 0         0 my $isneg = ($n < 0);
6962 0 0       0 $n =~ s/^-// if $isneg;
6963 0         0 $$refp = Mrootint($n, $a);
6964 0 0       0 $$refp = reftyped($_[0], $$refp) if $$refp > INTMAX;
6965 0 0       0 $$refp = Mnegint($$refp) if $isneg;
6966             }
6967 0         0 return $k;
6968             }
6969              
6970 343 100       1185 if ($a != 0) {
6971 8 50       28 if ($a == 1) {
6972 0 0       0 $$refp = $n if defined $refp;
6973 0         0 return 1; # Everything is a 1st power
6974             }
6975 8 50 33     31 return 0 if $n < 0 && $a % 2 == 0; # Negative n never an even power
6976 8 100       528 if ($a == 2) {
6977 3 50       55 if (_is_perfect_square($n)) {
6978 3 50       41 $$refp = Msqrtint($n) if defined $refp;
6979 3         17 return 1;
6980             }
6981             } else {
6982              
6983 5         63 my @rootmask = (
6984             0x00000000,0x00000000,0xfdfcfdec,0x54555454,0xfffcfffc, # 0-4
6985             0x55555554,0xfdfdfdfc,0x55555554,0xfffffffc,0x55555554,0xfdfdfdfc,# 5-10
6986             0x55555554,0xfffdfffc,0xd5555556,0xfdfdfdfc,0xf57d57d6,0xfffffffc,# 11-16
6987             0xffffd556,0xfdfdfdfe,0xd57ffffe,0xfffdfffc,0xffd7ff7e,0xfdfdfdfe,# 17-22
6988             0xffffd7fe,0xfffffffc,0xffffffd6,0xfdfffdfe,0xd7fffffe,0xfffdfffe,# 23-28
6989             0xfff7fffe,0xfdfffffe,0xfffff7fe,0xfffffffc,0xfffffff6,0xfffffdfe,# 29-34
6990             0xf7fffffe,0xfffdfffe,0xfff7fffe,0xfdfffffe,0xfffff7fe,0xfffffffc # 35-40
6991             );
6992 5 50       20 if ($a <= 40) {
6993 5 100       29 my $n32 = 1 << (ref($n) ? Mmodint($n,32) : $n & 31);
6994 5 100       32 return 0 if $n32 & $rootmask[$a];
6995             }
6996 3         9 my $RK;
6997 3 50       10 if ($n >= 0) {
6998 3         266 my $root = Mrootint($n, $a, \$RK);
6999 3 0       18 if ($RK == $n) { $$refp = $root if defined $refp; return 1; }
  0 50       0  
  0         0  
7000             } else {
7001 0         0 my $N = Mnegint($n);
7002 0         0 my $root = Mrootint($N, $a, \$RK);
7003 0 0       0 if ($RK == $N) { $$refp = Mnegint($root) if defined $refp; return 1; }
  0 0       0  
  0         0  
7004             }
7005             }
7006 3         77 return 0;
7007             }
7008              
7009 335         1366 my $negn = $n < 0;
7010 335 100       66419 $n = Mnegint($n) if $negn;
7011 335         34088 my $r;
7012 335 100       1674 my $k = _powerof_ret($n, defined $refp ? \$r : undef);
7013 335 100       1593 return 0 if $k < 2;
7014 278 100 100     1945 if ($negn && $k % 2 == 0) {
7015 128         699 my $v = Mvaluation($k, 2);
7016 128         328 $k >>= $v;
7017 128 100       437 return 0 if $k < 2;
7018 122 100       913 $r = Mpowint($r, Mpowint(2,$v)) if defined $r;
7019             }
7020 272 100 66     3968 $$refp = $negn ? Mnegint($r) : $r if defined $refp && $k > 0;
    100          
7021 272         2853 $k;
7022             }
7023              
7024             sub is_square {
7025 2     2 0 1143 my($n) = @_;
7026 2 50       47 return 0 if $n < 0;
7027             #Mis_power($n,2);
7028 2         30 validate_integer($n);
7029 2         14 _is_perfect_square($n);
7030             }
7031              
7032             sub is_prime_power {
7033 60     60 0 208 my ($n, $refp) = @_;
7034 60         212 validate_integer($n);
7035 60 50 66     889 croak("is_prime_power second argument not a scalar reference") if defined($refp) && !ref($refp);
7036 60 50       147 return 0 if $n <= 1;
7037              
7038 60 100       2615 if (Mis_prime($n)) { $$refp = $n if defined $refp; return 1; }
  18 100       87  
  18         81  
7039 42         84 my $r;
7040 42         169 my $k = Mis_power($n,0,\$r);
7041 42 100       141 if ($k) {
7042 13 50 66     76 $r = _bigint_to_int($r) if ref($r) && $r <= INTMAX;
7043 13 50       2198 return 0 unless Mis_prime($r);
7044 13 100       1344 $$refp = $r if defined $refp;
7045             }
7046 42         152 $k;
7047             }
7048              
7049             sub is_gaussian_prime {
7050 7     7 0 1668 my($a,$b) = @_;
7051 7         48 validate_integer_abs($a);
7052 7         27 validate_integer_abs($b);
7053 7 100       58 return ((($b % 4) == 3) ? Mis_prime($b) : 0) if $a == 0;
    100          
7054 5 100       44 return ((($a % 4) == 3) ? Mis_prime($a) : 0) if $b == 0;
    100          
7055 3         22 Mis_prime( Maddint( Mmulint($a,$a), Mmulint($b,$b) ) );
7056             }
7057              
7058             sub is_polygonal {
7059 4     4 0 40 my ($n, $k, $refp) = @_;
7060 4         38 validate_integer($n);
7061 4         23 validate_integer_nonneg($k);
7062 4 50 33     19 croak("is_polygonal third argument not a scalar reference") if defined($refp) && !ref($refp);
7063 4 50       15 croak("is_polygonal: k must be >= 3") if $k < 3;
7064 4 50       38 return 0 if $n < 0;
7065 4 0       657 if ($n <= 1) { $$refp = $n if defined $refp; return 1; }
  0 50       0  
  0         0  
7066              
7067 4 50       567 if ($Math::Prime::Util::_GMPfunc{"polygonal_nth"}) {
7068 0         0 my $nth = Math::Prime::Util::GMP::polygonal_nth($n, $k);
7069 0 0       0 return 0 unless $nth;
7070 0 0       0 $$refp = reftyped($_[0], $nth) if defined $refp;
7071 0         0 return 1;
7072             }
7073              
7074 4         21 my($D,$R);
7075 4 100       27 if ($k == 4) {
7076 1 50       5 return 0 unless _is_perfect_square($n);
7077 1 50       34 $$refp = Msqrtint($n) if defined $refp;
7078 1         9 return 1;
7079             }
7080 3 100 66     18 if ($n <= MPU_HALFWORD && $k <= MPU_HALFWORD) {
7081 1 50       6 $D = ($k==3) ? 1+($n<<3) : (8*$k-16)*$n + ($k-4)*($k-4);
7082 1 50       7 return 0 unless _is_perfect_square($D);
7083 1         9 $D = $k-4 + Msqrtint($D);
7084 1         5 $R = 2*$k-4;
7085             } else {
7086 2 50       516 if ($k == 3) {
7087 2         53 $D = Maddint(1, Mmulint($n, 8));
7088             } else {
7089 0         0 $D = Maddint(Mmulint($n, Mmulint(8, $k) - 16), Mmulint($k-4,$k-4));
7090             }
7091 2 100       553 return 0 unless _is_perfect_square($D);
7092 1         373 $D = Maddint( Msqrtint($D), $k-4 );
7093 1         265 $R = Mmulint(2, $k) - 4;
7094             }
7095 2 50       25 return 0 if ($D % $R) != 0;
7096 2 50       642 $$refp = $D / $R if defined $refp;
7097 2         21 1;
7098             }
7099              
7100             sub is_sum_of_squares {
7101 23     23 0 117 my($n, $k) = @_;
7102 23         94 validate_integer_abs($n);
7103 23 100       309 if (defined $k) { validate_integer_nonneg($k); }
  1         5  
7104 22         35 else { $k = 2; }
7105              
7106 23 0       1125 return ($n == 0) ? 1 : 0 if $k == 0;
    50          
7107 23 50       72 return 1 if $k > 3;
7108 23 50       65 return _is_perfect_square($n) if $k == 1;
7109              
7110 23 100       103 return 1 if $n < 3;
7111              
7112 18 100       289 if ($k == 3) {
7113 1         9 my $tz = Mvaluation($n,2);
7114 1 50       7 return 1 if ($tz & 1) == 1;
7115 1 50       9 return 1 unless Mis_congruent(Mrshiftint($n,$tz), 7, 8);
7116 1         13 return 0;
7117             }
7118              
7119             # k = 2
7120 17         51 while (($n % 2) == 0) { $n >>= 1; }
  14         34  
7121 17 100       60 return 0 if ($n % 4) == 3;
7122              
7123 11         64 foreach my $F (Mfactor_exp($n)) {
7124 7         23 my($f,$e) = @$F;
7125 7 100 100     74 return 0 if ($e & 1) == 1 && ($f % 4) == 3;
7126             }
7127 10         72 1;
7128             }
7129              
7130             sub cornacchia {
7131 3     3 0 10 my($d, $n) = @_;
7132 3         47 validate_integer_nonneg($d);
7133 3         10 validate_integer_nonneg($n);
7134              
7135 3 50       22 return (0,0) if $n == 0;
7136 3 50       17 if ($d == 0) {
7137 0 0       0 return undef unless _is_perfect_square($n);
7138 0         0 return (Msqrtint($n), 0);
7139             }
7140              
7141 3 100       35 if (Mis_prime($n)) {
7142 2         5 my ($u,$rk);
7143 2         39 my $negd = _negmod($d,$n);
7144 2 50       19 return undef if Mkronecker($negd, $n) == -1;
7145 2         56 $u = _sqrtmod_prime($negd, $n);
7146 2 50       28 return undef unless defined $u;
7147 2 100       18 $u = $n-$u if $u > ($n>>1);
7148             {
7149 2         5 my $l = Msqrtint($n);
  2         10  
7150 2         19 my($a, $b) = ($n, $u);
7151 2         18 while ($a > $l) {
7152 5         15 ($a,$b) = ($b, $a % $b);
7153             }
7154 2         5 $rk = $a;
7155             }
7156 2         9 $u = _negmod(Mmulmod($rk,$rk,$n),$n);
7157 2 100       14 $u = (($u % $d) == 0) ? Mdivint($u,$d) : 0;
7158 2 100 66     44 return ($rk, Msqrtint($u)) if $u && _is_perfect_square($u);
7159 1         6 return undef;
7160             }
7161              
7162 1         6 my $limu = Msqrtint(Mdivint($n,$d));
7163 1         6 for my $u (0 .. $limu) {
7164 7         53 my $t = $n - Mvecprod($d,$u,$u);
7165 7 100       22 return (Msqrtint($t), $u) if _is_perfect_square($t);
7166             }
7167 0         0 undef;
7168             }
7169              
7170             sub is_congruent_number {
7171 17     17 0 1490 my($n) = @_;
7172 17         57 validate_integer_nonneg($n);
7173              
7174 17 50 0     47 return ($n >= 5 && $n <= 7) if $n < 13;
7175              
7176 17         31 my $n8 = $n % 8;
7177 17 100 100     126 return 1 if $n8 == 5 || $n8 == 6 || $n8 == 7;
      100        
7178              
7179 14 100       51 if (!Mis_square_free($n)) {
7180 1         5 my $N = 1;
7181 1         6 foreach my $f (Mfactor_exp($n)) {
7182 2         6 my($p,$e) = @$f;
7183 2 100       13 $N = Mmulint($N,$p) if ($e % 2) == 1;
7184             }
7185 1         49 return is_congruent_number($N);
7186             }
7187              
7188 13         45 my $ndiv2 = Mrshiftint($n);
7189              
7190 13 100 100     46 if (Mis_even($n) && Mis_prime($ndiv2)) {
    100          
7191 2         6 my $p = $ndiv2;
7192 2         7 my $p8 = $p % 8;
7193 2 50 33     31 return 1 if $p8 == 3 || $p8 == 7;
7194 2 100 66     30 return 0 if $p8 == 5 || ($p % 16) == 9;
7195             } elsif (Mis_prime($n)) {
7196 3 100       16 return 0 if $n8 == 3;
7197 2 50 33     14 return 1 if $n8 == 5 || $n8 == 7;
7198              
7199 2         11 my $r = _sqrtmod_prime(2, $n);
7200 2 100 66     18 return 0 if defined $r && Mkronecker(1+$r, $n) == -1;
7201             } elsif (1) {
7202 8         26 my @factors = Mfactor($n);
7203 8 100 33     57 if (scalar(@factors) == 2) {
    50          
7204 4         14 my($p, $q) = ($factors[0], $factors[1]);
7205 4         10 my($p8, $q8) = ($p % 8, $q %8);
7206 4 100 100     51 return 0 if $p8 == 3 && $q8 == 3;
7207 3 50 66     24 return 0 if $p8 == 1 && $q8 == 3 && kronecker($p,$q) == -1;
      66        
7208 2 50 66     27 return 0 if $p8 == 3 && $q8 == 1 && kronecker($q,$p) == -1;
      66        
7209             } elsif (scalar(@factors) == 3 && $factors[0] == 2) {
7210 4         27 my($p, $q) = ($factors[1], $factors[2]);
7211 4         10 my($p8, $q8) = ($p % 8, $q %8);
7212 4 100 100     24 return 0 if $p8 == 5 && $q8 == 5;
7213 3 50 66     23 return 0 if $p8 == 1 && $q8 == 5 && kronecker($p,$q) == -1;
      66        
7214 2 50 66     34 return 0 if $p8 == 5 && $q8 == 1 && kronecker($q,$p) == -1;
      66        
7215             }
7216             }
7217              
7218             # General test
7219 4         31 my @sols = (0,0);
7220 4 100       21 if (Mis_odd($n)) {
7221 2         29 my $limz = Msqrtint($n >> 3);
7222 2         9 foreach my $z (0 .. $limz) {
7223 6         12 my $zsols = 0;
7224 6         54 my $n8z = $n - 8*$z*$z;
7225 6         21 my $limy = Msqrtint($n8z >> 1);
7226 6         16 foreach my $y (0 .. $limy) {
7227 24         42 my $x = $n8z - 2*$y*$y;
7228 24 100       65 $zsols += 1 << (1 + ($y>0) + ($z>0))
7229             if _is_perfect_square($x);
7230             }
7231 6         20 $sols[$z % 2] += $zsols;
7232             }
7233             } else {
7234 2         14 my $limz = Msqrtint($ndiv2 >> 3);
7235 2         10 foreach my $z (0 .. $limz) {
7236 4         8 my $zsols = 0;
7237 4         30 my $n8z = $ndiv2 - 8*$z*$z; # ndiv2 odd => n8z is odd
7238 4         12 my $limx = Msqrtint($n8z);
7239 4         16 for (my $x = 1; $x <= $limx; $x += 2) {
7240 8         16 my $y = $n8z - $x*$x;
7241 8 100 100     33 $zsols += 1 << (1 + ($y>0) + ($z>0))
7242             if $y == 0 || _is_perfect_square($y);
7243             }
7244 4         30 $sols[$z % 2] += $zsols;
7245             }
7246             }
7247 4 100       31 return ($sols[0] == $sols[1]) ? 1 : 0;
7248             }
7249              
7250             sub is_perfect_number {
7251 4     4 0 1211 my($n) = @_;
7252 4         39 validate_integer($n);
7253 4 50       18 return 0 if $n <= 0;
7254              
7255 4 50       683 if (Mis_even($n)) {
7256 4         242 my $v = Mvaluation($n,2);
7257 4         759 my $m = Mrshiftint($n, $v);
7258 4 100       166 return 0 if Mrshiftint($m,$v) != 1;
7259 3 50       43 return 0 if Math::Prime::Util::hammingweight($m) != $v+1;
7260 3         53 return Math::Prime::Util::is_mersenne_prime($v+1);
7261             }
7262              
7263             # N is odd. See https://www.lirmm.fr/~ochem/opn/
7264 0 0       0 return 0 if length($n) <= 2200;
7265 0 0       0 return 0 unless Mis_divisible($n, 105);
7266 0 0 0     0 return 0 unless Mis_congruent($n, 1, 12)
      0        
7267             || Mis_congruent($n,117,468)
7268             || Mis_congruent($n, 81, 324);
7269 0         0 Mcmpint($n,Msubint(Mdivisor_sum($n),$n)) == 0;
7270             }
7271              
7272             sub valuation {
7273 507     507 0 1985 my($n, $k) = @_;
7274             # The validation in PP is 2x more time than our actual work.
7275 507         3240 validate_integer_abs($n);
7276 507         126815 validate_integer_positive($k);
7277 507 50       2125 croak "valuation: k must be > 1" if $k <= 1;
7278              
7279 507 50       1808 return if $k < 2;
7280 507 50       1694 return (undef,0)[$n] if $n <= 1;
7281 507         103068 my $v = 0;
7282 507 100       2019 if ($k == 2) { # Accelerate power of 2
7283 499         1060 my $s;
7284 499 100       2942 if (!ref($n)) {
    50          
    0          
7285 8 50       68 return 0 if $n & 1;
7286 8 100       36 return 1 if $n & 2;
7287 6 50       26 return 2 if $n & 4;
7288 6         36 $s = sprintf("%b","$n");
7289             } elsif (ref($n) eq 'Math::BigInt') {
7290 491         2911 $s = $n->as_bin;
7291             } elsif (ref($n) eq 'Math::GMPz') {
7292 0         0 return Math::GMPz::Rmpz_scan1($n,0);
7293             } else {
7294 0         0 $s = Math::BigInt->new("$n")->as_bin;
7295             }
7296 497         190673 return length($s) - rindex($s,'1') - 1;
7297             }
7298 8         30 while ( !($n % $k) ) {
7299 12         1779 $n /= $k;
7300 12         2890 $v++;
7301             }
7302 8         444 $v;
7303             }
7304              
7305             sub hammingweight {
7306 2     2 0 26 return 0 + (Mtodigitstring($_[0],2) =~ tr/1//);
7307             }
7308              
7309             my @_digitmap = (0..9, 'a'..'z');
7310             my %_mapdigit = map { $_digitmap[$_] => $_ } 0 .. $#_digitmap;
7311             sub _splitdigits {
7312 176     176   6855 my($n, $base, $len) = @_; # n is num or bigint, base is in range
7313 176         951 validate_integer_nonneg($n);
7314 176         6233 my @d;
7315 176 100       876 if ($base == 10) {
    100          
    100          
7316 1         7 @d = split(//,"$n");
7317             } elsif ($base == 2) {
7318 145         831 @d = split(//,substr(Math::BigInt->new("$n")->as_bin,2));
7319             } elsif ($base == 16) {
7320 27         128 @d = map { $_mapdigit{$_} } split(//,substr(Math::BigInt->new("$n")->as_hex,2));
  523         14337  
7321             } else {
7322             # The validation turned n into a bigint if necessary
7323 3         7 while ($n >= 1) {
7324 98         43039 my $rem = $n % $base;
7325 98         17167 unshift @d, $rem;
7326 98         184 $n = ($n-$rem)/$base; # Always an exact division
7327             }
7328             }
7329 176 50 33     66082 if ($len >= 0 && $len != scalar(@d)) {
7330 0         0 while (@d < $len) { unshift @d, 0; }
  0         0  
7331 0         0 while (@d > $len) { shift @d; }
  0         0  
7332             }
7333 176         4812 @d;
7334             }
7335              
7336             sub todigits {
7337 141     141 0 617 my($n,$base,$len) = @_;
7338 141         924 validate_integer_abs($n);
7339 141 100       20932 $base = 10 unless defined $base;
7340 141 50       552 $len = -1 unless defined $len;
7341 141 50       483 die "Invalid base: $base" if $base < 2;
7342 141 50       475 return if $n == 0;
7343 141         19342 _splitdigits($n, $base, $len);
7344             }
7345              
7346             sub _tobinarystring {
7347 14     14   41 my($n) = @_;
7348 14         75 $n =~ s/^-//;
7349 14 50       329 return "" if $n == 0;
7350 14 100       1705 return sprintf("%b",$n) if $n < INTMAX;
7351 6 50       1697 $n = tobigint($n) unless ref($n);
7352 6         15 my $refn = ref($n);
7353 6 50       20 return Math::GMPz::Rmpz_get_str($n,2) if $refn eq 'Math::GMPz';
7354 6 50       15 return Math::GMP::get_str_gmp($n,2) if $refn eq 'Math::GMP';
7355 6 50       17 if ($BIGINTVERSION >= 1.999814) {
7356 0 0       0 $n = Math::BigInt->new("$n") if $refn ne 'Math::BigInt';
7357 0         0 return $n->to_base(2);
7358             }
7359 6         25 return join("", _splitdigits($n, 2, -1));
7360             }
7361              
7362             sub todigitstring {
7363 44     44 0 6783 my($n,$base,$len) = @_;
7364 44         342 validate_integer($n);
7365 44 50       1619 $base = 10 unless defined $base;
7366 44 100 66     294 return _tobinarystring($n) if $base == 2 && !defined $len;
7367 30 50 33     184 croak "Invalid base for string: $base" if $base < 2 || $base > 36;
7368 30 50       118 $len = -1 unless defined $len;
7369 30         103 $n =~ s/^-//;
7370              
7371 30 50 33     1623 return "" if $len == 0 || $n == 0;
7372              
7373 30 100       6636 if ($n < INTMAX) {
7374 1 50 33     16 if ($base != 2 && $base != 8 && $base != 16) {
      33        
7375 0 0       0 return join "", _splitdigits($n, $base, $len) if $base <= 10;
7376 0         0 return join "", map { $_digitmap[$_] } _splitdigits($n, $base, $len);
  0         0  
7377             }
7378 1         2 my $s;
7379 1 50       7 $s = sprintf("%b",$n) if $base == 2;
7380 1 50       5 $s = sprintf("%o",$n) if $base == 8;
7381 1 50       8 $s = sprintf("%x",$n) if $base == 16;
7382 1 50       5 if ($len > 0) {
7383 0         0 $s = substr($s,0,$len);
7384 0 0       0 $s = '0' x ($len-length($s)) . $s if length($s) < $len;
7385             }
7386 1         9 return $s;
7387             }
7388              
7389 29 50       6651 $n = tobigint($n) unless ref($n);
7390 29         121 my $refn = ref($n);
7391 29         64 my $s;
7392              
7393 29 50       179 if ($refn eq 'Math::GMPz') {
    50          
    50          
7394 0         0 $s = Math::GMPz::Rmpz_get_str($n,$base);
7395             } elsif ($refn eq 'Math::GMP') {
7396 0         0 $s = Math::GMP::get_str_gmp($n,$base);
7397             } elsif ($BIGINTVERSION >= 1.999814) {
7398 0 0       0 $n = Math::BigInt->new("$n") if $refn ne 'Math::BigInt';
7399 0         0 $s = $n->to_base($base);
7400             } else {
7401 29 50       115 my @d = ($n == 0) ? () : _splitdigits($n, $base, -1);
7402 29 100       121 if ($base <= 10) {
7403 2         9 $s = join("", @d);
7404             } else {
7405 27 50       89 die "Invalid base for string: $base" if $base > 36;
7406 27         76 $s = join("", map { $_digitmap[$_] } @d);
  544         1654  
7407             }
7408             }
7409 29 50       1406 if ($len > 0) {
7410 0         0 $s = substr($s,0,$len);
7411 0 0       0 $s = '0' x ($len-length($s)) . $s if length($s) < $len;
7412             }
7413 29         168 return lc($s);
7414             }
7415              
7416             sub _FastIntegerInput {
7417 93     93   212 my($digits, $B) = @_;
7418 93 50       259 return 0 if scalar(@$digits) == 0;
7419 93 50       217 return $digits->[0] if scalar(@$digits) == 1;
7420 93         418 my $L = [reverse @$digits];
7421 93         191 my $k = scalar(@$L);
7422 93         257 while ($k > 1) {
7423 326         568 my @T;
7424 326         958 for my $i (1 .. $k>>1) {
7425 1111         3225 my $x = $L->[2*$i-2];
7426 1111         1890 my $y = $L->[2*$i-1];
7427 1111         3349 push(@T, Maddint($x, Mmulint($B, $y)));
7428             }
7429 326 100       5030 push(@T, $L->[$k-1]) if ($k&1);
7430 326         862 $L = \@T;
7431 326         2024 $B = Mmulint($B, $B);
7432 326         8242 $k = ($k+1) >> 1;
7433             }
7434 93         553 $L->[0];
7435             }
7436              
7437             sub fromdigits {
7438 93     93 0 221 my($r, $base) = @_;
7439 93 50       248 $base = 10 unless defined $base;
7440 93         237 my $refr = ref($r);
7441              
7442 93 100 66     399 if ($refr && $refr !~ /^Math::/) {
7443 77 50       183 croak "fromdigits: first argument must be a string or array reference"
7444             unless $refr eq 'ARRAY';
7445             # Math::BigInt->from_base_num is identical but slower
7446 77         219 return _FastIntegerInput($r,$base);
7447             }
7448              
7449 16         53 my $n;
7450 16         158 $r =~ s/^0*//;
7451 16 50       66 return 0 if $r eq "";
7452             { # Validate string
7453 16         55 my $cmap = substr("0123456789abcdefghijklmnopqrstuvwxyz",0,$base);
  16         57  
7454 16 50       321 croak "Invalid digit for base $base" if $r =~ /[^$cmap]/i;
7455             }
7456 16 50 66     162 if (defined $_BIGINT && $_BIGINT =~ /^Math::(GMPz|GMP)$/) {
    50          
7457 0         0 $n = $_BIGINT->new($r, $base);
7458             } elsif ($BIGINTVERSION < 1.999814) {
7459 16         246 $n=_FastIntegerInput([map{index("0123456789abcdefghijklmnopqrstuvwxyz",$_)}split(//,lc($r))],$base);
  820         1685  
7460             } else {
7461             # from_base is 2x slower than calling the method directly (TODO file an RT)
7462 0 0       0 if ($base == 2) { $n = Math::BigInt->from_bin($r); }
  0 0       0  
    0          
    0          
7463 0         0 elsif ($base == 8) { $n = Math::BigInt->from_oct($r); }
7464 0         0 elsif ($base == 10) { $n = Math::BigInt->new($r); }
7465 0         0 elsif ($base == 16) { $n = Math::BigInt->from_hex($r); }
7466 0         0 else { $n = Math::BigInt->from_base($r,$base); }
7467 0 0 0     0 $n = tobigint($n) if defined $_BIGINT && $_BIGINT ne 'Math::BigInt';
7468             }
7469 16 100       277 return $n <= INTMAX ? _bigint_to_int($n) : $n;
7470             }
7471              
7472             sub _validate_zeckendorf {
7473 2     2   6 my($s) = @_;
7474 2 50       11 if ($s ne '0') {
7475 2 50       15 croak "fromzeckendorf: expected binary string"
7476             unless $s =~ /^1[01]*\z/;
7477 2 50       10 croak "fromzeckendorf: expected binary string in canonical Zeckendorf form"
7478             if $s =~ /11/;
7479             }
7480 2         5 1;
7481             }
7482              
7483             sub fromzeckendorf {
7484 2     2 0 4140 my($s) = @_;
7485 2         10 _validate_zeckendorf($s);
7486              
7487 2         5 my($n, $fb, $fc) = (0, 1, 1);
7488 2         39 for my $c (split(//,reverse $s)) {
7489 153 100       13268 $n = Maddint($n,$fc) if $c eq '1';
7490 153         5676 ($fb, $fc) = ($fc, Maddint($fb,$fc));
7491             }
7492 2         355 $n;
7493             }
7494              
7495             sub tozeckendorf {
7496 2     2 0 11 my($n) = @_;
7497 2         25 validate_integer_nonneg($n);
7498 2 50       9 return '0' if $n == 0;
7499              
7500 2         274 my($rn, $s, $fa, $fb, $fc) = ($n, '', 0, 1, 1);
7501 2         31 my($i, $k);
7502 2         11 for ($k = 2; $fc <= $rn; $k++) {
7503 153         30428 ($fa, $fb, $fc) = ($fb, $fc, Maddint($fb,$fc));
7504             }
7505 2         183 for ($i = $k-1; $i >= 2; $i--) {
7506 153         291 ($fc, $fb, $fa) = ($fb, $fa, Msubint($fb,$fa));
7507 153 100       7720 if ($fc <= $rn) {
7508 48         698 $rn = Msubint($rn, $fc);
7509 48         3174 $s .= '1';
7510             } else {
7511 105         1123 $s .= '0';
7512             }
7513             }
7514             # croak "wrong tozeckendorf $n" unless $n == fromzeckendorf($s);
7515 2         21 $s;
7516             }
7517              
7518              
7519             sub sqrtint {
7520 2212     2212 0 10642 my($n) = @_;
7521 2212         6439 validate_integer_nonneg($n);
7522 2212 100       15501 return int(sqrt("$n")) if $n <= 562949953421312; # 2^49 safe everywhere
7523              
7524 61         13950 my $refn = ref($n);
7525 61         165 my $R;
7526              
7527 61 100       293 if ($refn eq 'Math::BigInt') {
    50          
    50          
7528 58         233 $R = $n->copy->bsqrt;
7529             } elsif ($refn eq 'Math::GMPz') {
7530 0         0 $R = Math::GMPz->new();
7531 0         0 Math::GMPz::Rmpz_sqrt($R, $n);
7532             } elsif ($refn eq 'Math::GMP') {
7533 0         0 $R = $n->bsqrt();
7534             } else {
7535 3         71 $R = Math::BigInt->new("$n")->bsqrt;
7536             }
7537 61 100       89465 $R = _bigint_to_int($R) if $R <= INTMAX;
7538 61         4543 $R;
7539             }
7540              
7541             sub rootint {
7542 9724     9724 0 33450 my ($n, $k, $refp) = @_;
7543 9724         36069 validate_integer_nonneg($n);
7544 9724         230550 validate_integer_positive($k);
7545 9724 50 66     34973 croak("rootint: third argument not a scalar reference") if defined $refp && !ref($refp);
7546              
7547 9724 100       21966 if ($k == 1) {
7548 75 50       234 $$refp = $n if defined $refp;
7549 75         312 return $n;
7550             }
7551 9649 100       31645 if (!ref($n)) { # native integer
7552 5886 50       12350 if ($n == 0) {
7553 0 0       0 $$refp = 0 if defined $refp;
7554 0         0 return 0;
7555             }
7556 5886 100 100     13186 if ($k == 2 && $n <= 562949953421312) {
7557 559         1190 my $R = int(sqrt($n));
7558 559 100       1279 $$refp = $R*$R if defined $refp;
7559 559         1364 return $R;
7560             }
7561 5327 100 66     18598 if ($k >= MPU_MAXBITS || $n >> $k == 0) {
7562 675 100       1526 $$refp = 1 if defined $refp;
7563 675         1389 return 1;
7564             }
7565 4652         14431 my $R = int($n ** (1/$k)); # Could be off by +/-1.
7566 4652 100       10101 my $F = $n <= 562949953421312 ? $R**$k : powint($R,$k);
7567 4652 50       7945 if ($F > $n) {
7568 0         0 $R--;
7569 0 0       0 $F = $n <= 562949953421312 ? $R**$k : powint($R,$k);
7570             } else {
7571 4652 100       10440 my $F1 = $n <= 562949953421312 ? ($R+1)**$k : powint($R+1,$k);
7572 4652 100       20459 if ($F1 <= $n) {
7573 24         43 $R++;
7574 24         42 $F = $F1;
7575             }
7576             }
7577 4652 100       10461 $$refp = $F if defined $refp;
7578 4652         11380 return $R;
7579             }
7580              
7581             # It's unclear whether we should add GMPfunc here. We want it in logint
7582             # because it's slow or not included in Perl bigint classes.
7583              
7584 3763         7690 my $refn = ref($n);
7585 3763         7247 my $R;
7586 3763 50       10499 if ($refn eq 'Math::BigInt') {
    0          
    0          
7587 3763         13856 $R = $n->copy->broot($k);
7588             } elsif ($refn eq 'Math::GMPz') {
7589 0         0 $R = Math::GMPz->new();
7590 0         0 Math::GMPz::Rmpz_root($R, $n, $k);
7591             } elsif ($refn eq 'Math::GMP') {
7592 0         0 $R = $n->broot($k);
7593             } else {
7594 0         0 $R = Math::BigInt->new("$n")->broot($k);
7595             }
7596 3763 100       9657904 $R = _bigint_to_int($R) if $R <= INTMAX;
7597 3763 100       517493 $$refp = Mpowint($R,$k) if defined $refp;
7598 3763         754159 $R;
7599             }
7600              
7601             sub _logint {
7602 4868     4868   8632 my($n,$b) = @_;
7603 4868 50       8565 return 0 if $n < $b;
7604 4868 100       92494 return length("$n")-1 if $b == 10;
7605 4867 100       8423 if ($n < INTMAX) {
7606 4484 100       14325 return length(sprintf("%b",$n))-1 if $b == 2;
7607 5 50       26 return length(sprintf("%o",$n))-1 if $b == 8;
7608 5 50       18 return length(sprintf("%x",$n))-1 if $b == 16;
7609             }
7610 388         86029 my $l;
7611 388 50       1297 if (length("$n") > 150) {
7612             # Reduce size so native log works
7613 0         0 my $N = substr($n,0,80);
7614 0         0 my $reddigits = length("$n") - length($N);
7615 0         0 $l = log($N) + 2.302585092994045684*$reddigits;
7616             } else {
7617 388         18954 $l = log("$n");
7618             }
7619 388         17807 $l /= log($b);
7620              
7621             # Just in case something failed, escape via using Math::BigInt's blog
7622 388 50 33     2691 if ($l == MPU_INFINITY || !defined($l<=>MPU_INFINITY)) {
7623 0         0 my $R = Math::BigInt->new("$n")->copy->blog($b);
7624 0 0       0 $R = _bigint_to_int($R) if $R <= INTMAX;
7625 0         0 return $R;
7626             }
7627              
7628 388         2889 my $R = int($l);
7629 388 100 66     2653 if ($R != int($l+1e-7) || $R != int($l-1e-7)) {
7630 9         892 my $BR = Mpowint($b,$R);
7631 9 50       2310 if ($BR > $n) {
    100          
7632 0         0 $R--;
7633             } elsif ($BR < $n) {
7634 7         817 my $BRB = Mmulint($BR, $b);
7635 7 50       1832 $R++ if $BRB <= $n;
7636             }
7637             }
7638 388         1772 $R;
7639             }
7640              
7641             sub logint {
7642 4868     4868 0 14427 my ($n, $b, $refp) = @_;
7643 4868         12095 validate_integer_positive($n);
7644 4868         31177 validate_integer_nonneg($b);
7645 4868 50       9867 croak "logint: base must be > 1" if $b <= 1;
7646 4868 50 66     10751 croak("logint third argument not a scalar reference") if defined($refp) && !ref($refp);
7647              
7648 4868 50       9049 if ($Math::Prime::Util::_GMPfunc{"logint"}) {
7649 0         0 my $e = Math::Prime::Util::GMP::logint($n, $b);
7650 0 0       0 if (defined $refp) {
7651             # logint in 0.47, powmod in 0.36, powint in 0.52
7652 0         0 my $r = Math::Prime::Util::GMP::powmod($b, $e, $n);
7653 0 0       0 $r = $n if $r == 0;
7654 0         0 $$refp = reftyped($_[0], $r);
7655             }
7656 0         0 return reftyped($_[0], $e);
7657             }
7658              
7659 4868         10939 my $log = _logint($n,$b);
7660 4868 100       16531 $$refp = Mpowint($b,$log) if defined $refp;
7661 4868         9715 return $log;
7662             }
7663              
7664             # Seidel (Luschny), core using Trizen's simplications from Math::AnyNum.
7665             # http://oeis.org/wiki/User:Peter_Luschny/ComputationAndAsymptoticsOfBernoulliNumbers#Bernoulli_numbers__after_Seidel
7666             sub _bernoulli_seidel {
7667 22     22   50 my($n) = @_;
7668 22 50       79 return (1,1) if $n == 0;
7669 22 50 33     145 return (0,1) if $n > 1 && $n % 2;
7670              
7671 22         116 my @D = (0, 1, map { 0} 1 .. ($n>>1)-1);
  421         573  
7672 22         68 my ($h, $w) = (1, 1);
7673              
7674 22         76 foreach my $i (0 .. $n-1) {
7675 886 100       57442 if ($w ^= 1) {
7676 443         3941 $D[$_] = Maddint($D[$_],$D[$_-1]) for 1.. $h-1;
7677             } else {
7678 443         703 $w = $h++;
7679 443         3689 $D[$w] = Maddint($D[$w],$D[$w+1]) while --$w;
7680             }
7681             }
7682 22         3311 my $num = $D[$h-1];
7683 22         153 my $den = Msubint(Mpowint(2,$n+1),2);
7684 22         185 my $gcd = Mgcd($num,$den);
7685 22 100       110 ($num,$den) = map { Mdivint($_,$gcd) } ($num,$den) if $gcd > 1;
  42         184  
7686 22 100       111 $num = Mnegint($num) if ($n % 4) == 0;
7687 22         1674 ($num,$den);
7688             }
7689              
7690             sub bernfrac {
7691 26     26 0 4341 my($n) = @_;
7692 26         106 validate_integer_nonneg($n);
7693 26 100       105 return (1,1) if $n == 0;
7694 25 100       73 return (1,2) if $n == 1; # We're choosing 1/2 instead of -1/2
7695 24 100 66     187 return (0,1) if $n < 0 || $n & 1;
7696              
7697             # We should have used one of the GMP functions before coming here.
7698              
7699 22         69 _bernoulli_seidel($n);
7700             }
7701              
7702             sub stirling {
7703 184     184 0 98820 my($n, $m, $type) = @_;
7704 184 100       670 return 1 if $m == $n;
7705 181 50 33     1582 return 0 if $n == 0 || $m == 0 || $m > $n;
      33        
7706 181 100       644 $type = 1 unless defined $type;
7707 181 50 100     1048 croak "stirling type must be 1, 2, or 3" unless $type == 1 || $type == 2 || $type == 3;
      66        
7708 181 100       677 if ($m == 1) {
7709 3 50       13 return 1 if $type == 2;
7710 0 0       0 return Mfactorial($n) if $type == 3;
7711 0 0       0 return Mfactorial($n-1) if $n & 1;
7712 0         0 return Mvecprod(-1, Mfactorial($n-1));
7713             }
7714             return reftyped($_[0], Math::Prime::Util::GMP::stirling($n,$m,$type))
7715 178 50       630 if $Math::Prime::Util::_GMPfunc{"stirling"};
7716             # Go through vecsum with quoted negatives to make sure we don't overflow.
7717 178         392 my $s;
7718 178 100       752 if ($type == 3) {
    100          
7719 5         519 $s = Mvecprod( Mbinomial($n,$m), Mbinomial($n-1,$m-1), Mfactorial($n-$m) );
7720             } elsif ($type == 2) {
7721 125 100       487 return Mbinomial($n,2) if $m==$n-1;
7722 116         245 my @terms;
7723 116         381 for my $j (1 .. $m) {
7724 2791         209250 my $t = Mmulint(
7725             Mpowint($j,$n),
7726             Mbinomial($m,$j)
7727             );
7728 2791 100       591576 $t = Mnegint($t) if ($m-$j) & 1;
7729 2791         174908 push @terms, $t;
7730             }
7731 116         743 $s = Mdivint(vecsum(@terms),Mfactorial($m));
7732             } else {
7733 48         134 my $M = $n-$m;
7734             # Both work on all inputs, but perform differently. Select one.
7735 48 100 100     128 if ($n <= 21 || $m < $M) { # Simple direct (see Arndt)
7736 47         199 my @S = (0)x($n+1);
7737 47         94 $S[1]=1;
7738 47         123 for my $k (2 .. $n) {
7739 979         63491 $S[$_] = addint($S[$_-1],mulint($k-1,$S[$_])) for reverse(1..$k);
7740             }
7741 47         3712 $s = $S[$m];
7742             } else { # Concrete Mathematics, eq 6.27
7743 1         7 my @terms = map { Mvecprod( Mbinomial($M-$n, $M+$_),
  65         5963  
7744             Mbinomial($M+$n, $M-$_),
7745             Mstirling($M+$_, $_, 2) ) } 1 .. $M;
7746 1         13 $s = vecsum(@terms);
7747             }
7748 48 100       204 $s = Mnegint($s) if is_odd($n-$m);
7749             }
7750 169         3723 $s;
7751             }
7752              
7753             sub _harmonic_split { # From Fredrik Johansson
7754 144     144   222 my($a,$b) = @_;
7755 144 100       264 return (1, $a) if $b-$a == 1;
7756 119 100       324 return (Mvecsum($a,$a,1), Maddint(Mmulint($a,$a),$a)) if $b-$a == 2;
7757 68         180 my $m = Mrshiftint(Maddint($a,$b));
7758 68         155 my ($p,$q) = _harmonic_split($a, $m);
7759 68         275 my ($r,$s) = _harmonic_split($m, $b);
7760 68         869 (Maddint(Mmulint($p,$s),Mmulint($q,$r)), Mmulint($q,$s));
7761             }
7762              
7763             sub harmfrac {
7764 9     9 0 13242 my($n) = @_;
7765 9         34 validate_integer_nonneg($n);
7766 9 100       29 return (0,1) if $n <= 0;
7767 8         31 my($p,$q) = _harmonic_split(1, Madd1int($n));
7768 8         409 my $gcd = Mgcd($p,$q);
7769 8 100       32 ($p,$q) = map { Mdivint($_,$gcd) } ($p,$q) if $gcd > 1;
  10         551  
7770 8         88 ($p,$q);
7771             }
7772              
7773             sub harmreal {
7774 22     22 0 34 my($n, $precision) = @_;
7775              
7776 22 50       42 do { require Math::BigFloat; Math::BigFloat->import(); } unless defined $Math::BigFloat::VERSION;
  0         0  
  0         0  
7777 22 50       36 return Math::BigFloat->bzero if $n <= 0;
7778              
7779             # Use asymptotic formula for larger $n if possible. Saves lots of time if
7780             # the default Calc backend is being used.
7781             {
7782 22         24 my $sprec = $precision;
  22         26  
7783 22 50       65 $sprec = Math::BigFloat->precision unless defined $sprec;
7784 22 50       238 $sprec = 40 unless defined $sprec;
7785 22 50 33     213 if ( ($sprec <= 23 && $n > 54) ||
      33        
      33        
      33        
      33        
      33        
      33        
7786             ($sprec <= 30 && $n > 348) ||
7787             ($sprec <= 40 && $n > 2002) ||
7788             ($sprec <= 50 && $n > 12644) ) {
7789 0         0 $n = Math::BigFloat->new($n, $sprec+5);
7790 0         0 my($n2, $one, $h) = ($n*$n, Math::BigFloat->bone, Math::BigFloat->bzero);
7791 0         0 my $nt = $n2;
7792 0         0 my $eps = Math::BigFloat->new(10)->bpow(-$sprec-4);
7793 0         0 foreach my $d (-12, 120, -252, 240, -132, 32760, -12, 8160, -14364, 6600, -276, 65520, -12) { # OEIS A006593
7794 0         0 my $term = $one/($d * $nt);
7795 0 0       0 last if $term->bacmp($eps) < 0;
7796 0         0 $h += $term;
7797 0         0 $nt *= $n2;
7798             }
7799 0         0 $h->badd(scalar $one->copy->bdiv(2*$n));
7800 0         0 $h->badd(_Euler($sprec));
7801 0         0 $h->badd($n->copy->blog);
7802 0         0 $h->round($sprec);
7803 0         0 return $h;
7804             }
7805             }
7806              
7807 22         172 my($num,$den) = Math::Prime::Util::harmfrac($n);
7808             # Note, with Calc backend this can be very, very slow
7809 22         86 scalar Math::BigFloat->new($num)->bdiv($den, $precision);
7810             }
7811              
7812             sub is_pseudoprime {
7813 86     86 0 404 my($n, @bases) = @_;
7814 86         617 validate_integer($n);
7815 86 50       4033 return 0 if $n < 0;
7816 86 50       17327 @bases = (2) if scalar(@bases) == 0;
7817 86 50       281 return 0+($n >= 2) if $n < 3;
7818              
7819 86         16707 foreach my $a (@bases) {
7820 86 50       344 croak "Base $a is invalid" if $a < 2;
7821 86 50       343 $a = $a % $n if $a >= $n;
7822 86 100 66     11167 return 0 unless $a == 1 || Mpowmod($a, $n-1, $n) == 1;
7823             }
7824 20         1280 1;
7825             }
7826              
7827             sub is_euler_pseudoprime {
7828 1     1 0 1310 my($n, @bases) = @_;
7829 1         8 validate_integer($n);
7830 1 50       4 return 0 if $n < 0;
7831 1 50       3 @bases = (2) if scalar(@bases) == 0;
7832 1 50       3 return 0+($n >= 2) if $n < 3;
7833 1 50       4 return 0 if ($n % 2) == 0;
7834              
7835 1         2 foreach my $a (@bases) {
7836 1 50       3 croak "Base $a is invalid" if $a < 2;
7837 1 50       4 $a = $a % $n if $a >= $n;
7838 1         15 my $j = Mkronecker($a, $n);
7839 1 50       5 return 0 if $j == 0; # gcd(a,n) != 1
7840 1 50       9 $j = ($j > 0) ? 1 : $n-1;
7841 1 50       50 return 0 unless Mpowmod($a, ($n-1)>>1, $n) == $j;
7842             }
7843 1         93 1;
7844             }
7845              
7846             sub is_euler_plumb_pseudoprime {
7847 1     1 0 3 my($n) = @_;
7848 1         4 validate_integer($n);
7849 1 50       4 return 0 if $n < 0;
7850 1 50       4 return 0+($n >= 2) if $n < 4;
7851 1 50       3 return 0 if ($n % 2) == 0;
7852 1         4 my $nmod8 = $n % 8;
7853 1         2 my $exp = 1 + ($nmod8 == 1);
7854 1         6 my $ap = Mpowmod(2, ($n-1) >> $exp, $n);
7855 1 50 0     36 if ($ap == 1) { return ($nmod8 == 1 || $nmod8 == 7); }
  0         0  
7856 1 50 33     4 if ($ap == $n-1) { return ($nmod8 == 1 || $nmod8 == 3 || $nmod8 == 5); }
  1         11  
7857 0         0 0;
7858             }
7859              
7860             sub _miller_rabin_2 {
7861 3730     3730   26630 my($n, $nm1, $s, $d) = @_;
7862 3730 50       7228 return 0 if $n < 0;
7863 3730 50       102007 return 0+($n >= 2) if $n < 4;
7864 3730 50       102602 return 0 if ($n % 2) == 0;
7865              
7866 3730 100       249112 if (ref($n)) {
7867              
7868 449 50       1864 if (!defined $nm1) {
7869 449         3891 $nm1 = Msub1int($n);
7870 449         108592 $s = valuation($nm1,2);
7871 449         2593 $d = rshiftint($nm1,$s);
7872             }
7873 449         102448 my $x = _bi_powmod(2,$d,$n);
7874 449 100 100     2979 return 1 if $x == 1 || $x == $nm1;
7875 368         127414 foreach my $r (1 .. $s-1) {
7876 363         14494 $x = Mmulmod($x,$x,$n);
7877 363 50       81580 last if $x == 1;
7878 363 100       69782 return 1 if $x == $nm1;
7879             }
7880              
7881             } else {
7882              
7883 3281 50       6250 if (!defined $nm1) {
7884 3281         4319 $nm1 = $n-1;
7885 3281         4218 $s = 0;
7886 3281         4377 $d = $nm1;
7887 3281         6638 while ( ($d & 1) == 0 ) {
7888 7639         9015 $s++;
7889 7639         13396 $d >>= 1;
7890             }
7891             }
7892              
7893 3281 100       5559 if ($n < MPU_HALFWORD) {
7894 3225         10172 my $x = _native_powmod(2, $d, $n);
7895 3225 100 100     11066 return 1 if $x == 1 || $x == $nm1;
7896 3194         7416 foreach my $r (1 .. $s-1) {
7897 3812         5046 $x = ($x*$x) % $n;
7898 3812 100       5866 last if $x == 1;
7899 3809 100       7644 return 1 if $x == $n-1;
7900             }
7901             } else {
7902 56         278 my $x = _powmod(2, $d, $n);
7903 56 100 100     614 return 1 if $x == 1 || $x == $nm1;
7904 33         187 foreach my $r (1 .. $s-1) {
7905 39 100       211 $x = ($x < MPU_HALFWORD) ? ($x*$x) % $n : _mulmod($x, $x, $n);
7906 39 50       162 last if $x == 1;
7907 39 100       317 return 1 if $x == $n-1;
7908             }
7909             }
7910             }
7911 3222         29913 0;
7912             }
7913              
7914             sub is_strong_pseudoprime {
7915 3313     3313 0 9270 my($n, @bases) = @_;
7916 3313         8843 validate_integer($n);
7917 3313 50       8005 return 0 if $n < 0;
7918 3313 100       15633 return _miller_rabin_2($n) if scalar(@bases) == 0;
7919              
7920 3312 100       6041 return 0+($n >= 2) if $n < 4;
7921 3308 50       14119 return 0 if ($n % 2) == 0;
7922              
7923 3308         29467 my @newbases;
7924 3308         5616 for my $a (@bases) {
7925 3733 50       6600 croak "Base $a is invalid" if $a < 2;
7926 3733 100       14946 $a %= $n if $a >= $n;
7927 3733 100 66     19315 next if $a <= 1 || $a == $n-1;
7928 3732 100       49134 if ($a == 2) {
7929 3237 100       5670 return 0 unless _miller_rabin_2($n);
7930 351         2012 next;
7931             }
7932 495         6002 push @newbases, $a;
7933             }
7934 422 100       1059 return 1 if scalar(@newbases) == 0;
7935 414         908 @bases = @newbases;
7936              
7937 414 100       1182 if (ref($n)) {
7938              
7939 37         241 my $nm1 = Msub1int($n);
7940 37         7097 my $s = Mvaluation($nm1,2);
7941 37         223 my $d = Mrshiftint($nm1,$s);
7942              
7943 37         6031 foreach my $ma (@bases) {
7944 69         4965 my $x = Mpowmod($ma,$d,$n);
7945 69 100 100     14990 next if $x == 1 || $x == $nm1;
7946 30         5921 foreach my $r (1 .. $s-1) {
7947 26         645 $x = Mmulmod($x,$x,$n);
7948 26 50       4080 return 0 if $x == 1;
7949 26 100       3393 last if $x == $nm1;
7950             }
7951 30 100       882 return 0 if $x != $nm1;
7952             }
7953              
7954             } else {
7955              
7956 377         598 my $s = 0;
7957 377         755 my $d = $n - 1;
7958 377         975 while ( ($d & 1) == 0 ) {
7959 1673         2200 $s++;
7960 1673         2901 $d >>= 1;
7961             }
7962              
7963 377 100       897 if ($n < MPU_HALFWORD) {
7964 363         655 foreach my $ma (@bases) {
7965 382         988 my $x = _native_powmod($ma, $d, $n);
7966 382 100 100     1653 next if ($x == 1) || ($x == ($n-1));
7967 329         992 foreach my $r (1 .. $s-1) {
7968 960         1400 $x = ($x*$x) % $n;
7969 960 100       4340 return 0 if $x == 1;
7970 959 100       1919 last if $x == $n-1;
7971             }
7972 328 100       1069 return 0 if $x != $n-1;
7973             }
7974             } else {
7975 14         58 foreach my $ma (@bases) {
7976 27         107 my $x = _powmod($ma, $d, $n);
7977 27 100 100     341 next if ($x == 1) || ($x == ($n-1));
7978 20         110 foreach my $r (1 .. $s-1) {
7979 17 100       118 $x = ($x < MPU_HALFWORD) ? ($x*$x) % $n : _mulmod($x, $x, $n);
7980 17 50       89 return 0 if $x == 1;
7981 17 100       79 last if $x == $n-1;
7982             }
7983 20 100       171 return 0 if $x != $n-1;
7984             }
7985             }
7986              
7987             }
7988 376         4434 1;
7989             }
7990              
7991              
7992             # Calculate Kronecker symbol (a|b). Cohen Algorithm 1.4.10.
7993             # Extension of the Jacobi symbol, itself an extension of the Legendre symbol.
7994             sub kronecker {
7995 829     829 0 12724 my($a, $b) = @_;
7996 829 0       2564 return (abs($a) == 1) ? 1 : 0 if $b == 0;
    50          
7997 829         69469 my $k = 1;
7998 829 100       2449 if ($b % 2 == 0) {
7999 4 100       399 return 0 if $a % 2 == 0;
8000 2         6 my $v = 0;
8001 2         15 do { $v++; $b /= 2; } while $b % 2 == 0;
  2         5  
  2         10  
8002 2 50 33     16 $k = -$k if $v % 2 == 1 && ($a % 8 == 3 || $a % 8 == 5);
      33        
8003             }
8004 827 50       159815 if ($b < 0) {
8005 0         0 $b = -$b;
8006 0 0       0 $k = -$k if $a < 0;
8007             }
8008 827 100       63763 if ($a < 0) { $a = -$a; $k = -$k if $b % 4 == 3; }
  11 100       29  
  11         43  
8009 827 100 100     4276 $b = _bigint_to_int($b) if ref($b) && $b <= INTMAX;
8010 827 50 66     72850 $a = _bigint_to_int($a) if ref($a) && $a <= INTMAX;
8011             # Now: b > 0, b odd, a >= 0
8012 827         3520 while ($a != 0) {
8013 1388 100       133445 if ($a % 2 == 0) {
8014 618         72688 my $v = 0;
8015 618         1079 do { $v++; $a /= 2; } while $a % 2 == 0;
  1130         65414  
  1130         3268  
8016 618 100 100     139157 $k = -$k if $v % 2 == 1 && ($b % 8 == 3 || $b % 8 == 5);
      100        
8017             }
8018 1388 100 100     112827 $k = -$k if $a % 4 == 3 && $b % 4 == 3;
8019 1388         206367 ($a, $b) = ($b % $a, $a);
8020             # If a,b are bigints and now small enough, finish as native.
8021 1388 100 100     172482 return $k * kronecker(_bigint_to_int($a),_bigint_to_int($b))
      100        
      100        
8022             if $a <= INTMAX && $b <= INTMAX && ref($a) && ref($b);
8023             }
8024 527 100       11808 return ($b == 1) ? $k : 0;
8025             }
8026              
8027             sub is_qr {
8028 4     4 0 1898 my($a, $n) = @_;
8029 4         42 validate_integer($a);
8030 4         141 validate_integer_abs($n);
8031              
8032             # return (defined Math::Prime::Util::sqrtmod($a,$n)) ? 1 : 0;
8033              
8034 4 50       511 return (undef,1,1)[$n] if $n <= 2;
8035 4 100 66     373 $a = Mmodint($a,$n) if $a >= $n || $a < 0;;
8036 4 50       31 return 1 if $a <= 1;
8037              
8038 4         386 foreach my $f (Mfactor_exp($n)) {
8039 11         603 my($p,$e) = @$f;
8040 11 100 100     113 next if $e == 1 && Mkronecker($a,$p) == 1;
8041 6 100       47 return 0 unless defined _sqrtmod_prime_power($a,$p,$e);
8042             }
8043 2         27 1;
8044             }
8045              
8046             sub _binomialu {
8047 262     262   807 my($r, $n, $k) = (1, @_);
8048 262 50       840 return ($k == $n) ? 1 : 0 if $k >= $n;
    100          
8049 249 100       798 $k = $n - $k if $k > ($n >> 1);
8050 249         833 foreach my $d (1 .. $k) {
8051 2949 100       6074 if ($r >= int(INTMAX/$n)) {
8052 459         835 my($g, $nr, $dr);
8053 459         1423 $g = _gcd_ui($n, $d); $nr = int($n/$g); $dr = int($d/$g);
  459         981  
  459         930  
8054 459         924 $g = _gcd_ui($r, $dr); $r = int($r/$g); $dr = int($dr/$g);
  459         954  
  459         877  
8055 459 100       1530 return 0 if $r >= int(INTMAX/$nr);
8056 266         580 $r *= $nr;
8057 266         584 $r = int($r/$dr);
8058             } else {
8059 2490         3889 $r *= $n;
8060 2490         4012 $r = int($r/$d);
8061             }
8062 2756         4503 $n--;
8063             }
8064 56         127 $r;
8065             }
8066              
8067             sub binomial {
8068 272     272 0 28100 my($n, $k) = @_;
8069 272         1245 validate_integer($n);
8070 272         1212 validate_integer($k);
8071              
8072             # 1. Try GMP
8073             return reftyped($_[0], Math::Prime::Util::GMP::binomial($n,$k))
8074 272 0 0     1105 if $Math::Prime::Util::_GMPfunc{"binomial"} &&
      33        
8075             ($Math::Prime::Util::GMP::VERSION >= 0.53 || ($n >= 0 && $k >= 0 && $n < 4294967296 && $k < 4294967296));
8076              
8077             # 2. Exit early for known 0 cases, and adjust k to be positive.
8078 272 50 33     778 if ($n >= 0) { return 0 if $k < 0 || $k > $n; }
  206 100       3884  
8079 66 50 66     268 else { return 0 if $k < 0 && $k > $n; }
8080 272 100       2362 $k = $n - $k if $k < 0;
8081              
8082             # TODO: consider reflection for large k (e.g. k=n-2 => k=2)
8083             # Also, be careful with large n and k with bigints.
8084              
8085 272         488 my $r;
8086              
8087             # 3. Try to do in integer Perl
8088 272 100       781 if (!ref($n)) {
8089 262 100       723 if ($n >= 0) {
8090 196         647 $r = _binomialu($n, $k);
8091 196 100 66     990 return $r if $r > 0 && $r eq int($r);
8092             } else {
8093 66         326 $r = _binomialu(-$n+$k-1, $k);
8094 66 100 66     287 if ($r > 0 && $r eq int($r)) {
8095 1 50       8 return $r if !($k & 1);
8096 1         46 return Mnegint($r);
8097             }
8098             }
8099             }
8100              
8101             # 4. Overflow. Solve using Math::BigInt
8102 203 50       599 return 1 if $k == 0; # Work around bug in old
8103 203 100 66     1219 return $n if $k == 1 || $k == $n-1; # Math::BigInt (fixed in 1.90)
8104              
8105 202         5918 my $R;
8106 202 100       1109 $n = tobigint($n) unless ref($n);
8107              
8108             # Older Math::BigInt isn't right for negative n. Adjust now.
8109 202         475 my $negate = 0;
8110 202 100       808 if ($n < 0) {
8111 65         13126 $n = -$n + ($k-1);
8112 65 100       28891 $negate = 1 if $k & 1;
8113             }
8114              
8115 202 50 33     35078 if (defined $Math::GMPz::VERSION) {
    50 33        
    100 66        
8116 0         0 $R = Math::GMPz->new();
8117 0         0 Math::GMPz::Rmpz_bin_ui($R, Math::GMPz->new($n), $k);
8118             } elsif (defined $Math::GMP::VERSION && $Math::GMP::VERSION >= 2.23 && $n < 4294967296) {
8119             # This will silently coerce inputs to C 'long' type.
8120 0         0 $R = Math::GMP::bnok("$n","$k");
8121             } elsif ($n > INTMAX && $k < 100) {
8122             # Incomplete work around problem with Math::BigInt not liking bigint n.
8123             # Fixed in 2.003003.
8124 9         2405 $R = Mdivint(Mfalling_factorial($n,$k),Mfactorial($k));
8125             } else {
8126 193         47669 $R = Math::BigInt::bnok("$n","$k");
8127             }
8128 202 100       3125678 $R = -$R if $negate;
8129 202 50 66     5008 return $R <= INTMAX && $R >= INTMIN ? _bigint_to_int($R)
    50 33        
8130             : defined $_BIGINT && $_BIGINT eq ref($R) ? $R
8131             : tobigint($R);
8132             }
8133              
8134             sub binomialmod {
8135 8     8 0 299 my($n,$k,$m) = @_;
8136 8         31 validate_integer($n);
8137 8         59 validate_integer($k);
8138 8         65 validate_integer_abs($m);
8139 8 50       242 return (undef,0)[$m] if $m <= 1;
8140              
8141             return reftyped($_[0], Math::Prime::Util::GMP::binomialmod($n,$k,$m))
8142 8 50       154 if $Math::Prime::Util::_GMPfunc{"binomialmod"};
8143              
8144             # Avoid the possible enormously slow bigint creation.
8145 8 0 33     21 if ($Math::Prime::Util::_GMPfunc{"binomial"} && $Math::Prime::Util::_GMPfunc{"modint"}) {
8146 0 0 0     0 if ($Math::Prime::Util::GMP::VERSION >= 0.53 || ($n >= 0 && $k >= 0 && $n < 4294967296 && $k < 4294967296)) {
      0        
      0        
      0        
8147 0         0 return reftyped($_[2], Math::Prime::Util::GMP::modint(Math::Prime::Util::GMP::binomial($n,$k),$m));
8148             }
8149             }
8150              
8151 8 100 66     31 return 1 if $k == 0 || $k == $n;
8152 7 50 33     193 return 0 if $n >= 0 && ($k < 0 || $k > $n);
      33        
8153 7 0 0     256 return 0 if $n < 0 && ($k < 0 && $k > $n);
      33        
8154 7 50       144 return 0+!(($n-$k) & $k) if $m == 2;
8155              
8156             # TODO: Lucas split, etc.
8157             # 1. factorexp
8158             # 2. bin[i] = _binomial_lucas_mod_prime_power(n, k, $f, $e)
8159             # 2a. _factorialmod_without_prime
8160             # 3. chinese(bin, p^e)
8161             # we can just run the more general code path.
8162              
8163             # Give up.
8164 7         397 return Mmodint(Mbinomial($n,$k),$m);
8165             }
8166              
8167             sub _falling_factorial {
8168 16     16   50 my($n,$m) = @_;
8169 16 0       69 if ($m <= 1) { return ($m == 0) ? 1 : $n }
  0 50       0  
8170 16 50 33     88 return 0 if $n >= 0 && $m > $n;
8171 16 50       4118 return Mvecprod($n,map { Msubint($n,$_) } 1 .. Msubint($m,1)) if $m < 250;
  323         17514  
8172 0         0 Mmulint(Mbinomial($n,$m),Mfactorial($m));
8173             }
8174             sub falling_factorial {
8175 13     13 0 8124 my($n,$m) = @_;
8176 13         90 validate_integer($n);
8177 13         562 validate_integer_nonneg($m);
8178 13         66 _falling_factorial($n,$m);
8179             }
8180             sub rising_factorial {
8181 3     3 0 10187 my($n,$m) = @_;
8182 3         15 validate_integer($n);
8183 3         12 validate_integer_nonneg($m);
8184 3         26 _falling_factorial(Mvecsum($n,$m,-1),$m);
8185             }
8186              
8187             sub factorial {
8188 388     388 0 127166 my($n) = @_;
8189 388 100       1536 return (1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600)[$n] if $n <= 12;
8190 352 50       1029 return Math::GMP::bfac($n) if ref($n) eq 'Math::GMP';
8191 352 50       898 do { my $r = Math::GMPz->new(); Math::GMPz::Rmpz_fac_ui($r,$n); return $r; }
  0         0  
  0         0  
  0         0  
8192             if ref($n) eq 'Math::GMPz';
8193 352 50       1380 if (Math::BigInt->config()->{lib} !~ /GMP|Pari/) {
8194             # It's not a GMP or GMPz object, and we have a slow bigint library.
8195 352         51376 my $r;
8196 352 50 33     1991 if (defined $Math::GMPz::VERSION) {
    50          
    50          
8197 0         0 $r = Math::GMPz->new(); Math::GMPz::Rmpz_fac_ui($r,$n);
  0         0  
8198             } elsif (defined $Math::GMP::VERSION) {
8199 0         0 $r = Math::GMP::bfac($n);
8200             } elsif (defined &Math::Prime::Util::GMP::factorial && getconfig()->{'gmp'}) {
8201 0         0 $r = Math::Prime::Util::GMP::factorial($n);
8202             }
8203 352 50       895 return reftyped($_[0], $r) if defined $r;
8204             }
8205             # maybe roll our own: https://oeis.org/A000142/a000142.pdf
8206 352         1867 my $r = Math::BigInt->new($n)->bfac();
8207 352 50       19718269 $r = _bigint_to_int($r) if $r <= INTMAX;
8208 352         83618 $r;
8209             }
8210              
8211             sub factorialmod {
8212 4     4 0 2923 my($n,$m) = @_;
8213 4         34 validate_integer($n);
8214 4         164 validate_integer_abs($m);
8215 4 50       482 return (undef,0)[$m] if $m <= 1;
8216              
8217             return reftyped($_[1], Math::Prime::Util::GMP::factorialmod($n,$m))
8218 4 50 33     503 if $Math::Prime::Util::_GMPfunc{"factorialmod"} && $n < ~0;
8219              
8220 4 50 33     31 return 0 if $n >= $m || $m == 1;
8221              
8222 4 50       678 return factorial($n) % $m if $n <= 10;
8223              
8224 4         179 my($F, $N, $m_prime) = (1, $n, Mis_prime($m));
8225              
8226             # Check for Wilson's theorem letting us go backwards
8227 4 50 66     689 $n = $m-$n-1 if $m_prime && $n > Mrshiftint($m);
8228 4 0       30 return ($n == 0) ? ($m-1) : 1 if $n < 2;
    50          
8229              
8230 4 100 100     190 if ($n > 100 && !$m_prime) { # Check for a composite that leads to zero
8231 2         126 my $maxpk = 0;
8232 2         16 foreach my $f (Mfactor_exp($m)) {
8233 12         30 my $pk = Mmulint($f->[0],$f->[1]);
8234 12 50       24 $maxpk = $pk if $pk > $maxpk;
8235             }
8236 2 100       23 return 0 if $n >= $maxpk;
8237             }
8238              
8239 3         8 my($t,$e);
8240             Mforprimes( sub {
8241 165     165   12122 ($t,$e) = ($n,0);
8242 165         425 while ($t > 0) {
8243 384         719 $t = int($t/$_);
8244 384         788 $e += $t;
8245             }
8246 165         662 $F = Mmulmod($F,Mpowmod($_,$e,$m),$m);
8247 3         110 }, 2, $n >> 1);
8248             Mforprimes( sub {
8249 133     133   9841 $F = Mmulmod($F, $_, $m);
8250 3         235 }, ($n >> 1)+1, $n);
8251              
8252             # Adjust for Wilson's theorem if we used it
8253 3 50 33     208 if ($n != $N && $F != 0) {
8254 0 0       0 $F = Msubmod($m, $F, $m) if !($n & 1);
8255 0         0 $F = Minvmod($F, $m);
8256             }
8257              
8258 3         34 $F;
8259             }
8260              
8261             sub subfactorial {
8262 6     6 0 73382 my($n) = @_;
8263 6         36 validate_integer_nonneg($n);
8264 6 50       24 if ($n <= 3) { return ($n == 0) ? 1 : $n-1; }
  1 100       9  
8265 5         9 my $r = 0;
8266 5         21 for my $k (2..$n) {
8267 186         8797 $r = Mmulint($r,$k);
8268 186 100       24362 if ($k&1) { $r--; } else { $r++; }
  92         241  
  94         240  
8269             }
8270 5         336 $r;
8271             }
8272              
8273             my $_fubinis = [1,1,3,13,75];
8274             sub _add_fubini { # Add the next Fubini sequence term to an array reference.
8275 33     33   78 my($A)= @_;
8276 33         70 my $N = @$A;
8277              
8278             # Faster method from Daniel Șuteu.
8279             # 1..400 no-GMP GMP Math::GMPz
8280             # old 51.82 13.95 0.804
8281             # new 35.73 3.79 0.380
8282              
8283 33         66 my($t,$x) = (1);
8284 33         118 push @$A, Mvecsum(map { $x = Smulint($t, $A->[$_]);
  427         2325  
8285 427         8034 $t = Smulint($t, $N - $_);
8286 427         1052 $t = Sdivint($t, $_+1);
8287 427         1006 $x } 0..$N-1);
8288             }
8289             _register_free_sub(sub { $_fubinis = [1,1,3,13,75]; });
8290             sub fubini {
8291 16     16 0 4811 my($n) = @_;
8292 16         64 validate_integer_nonneg($n);
8293              
8294 16 50       49 my $cmax = $n < 500 ? $n : 500;
8295 16         104 _add_fubini($_fubinis) until defined $_fubinis->[$cmax];
8296 16 50       127 return $_fubinis->[$n] if defined $_fubinis->[$n];
8297              
8298 0         0 my @F = @$_fubinis; # copy the cached values to our own.
8299 0         0 _add_fubini(\@F) until defined $F[$n];
8300 0         0 return $F[$n];
8301             }
8302              
8303              
8304             # Rational maps
8305              
8306             sub _rational_cfrac {
8307 27     27   1004 my($num,$den,$non_reduce_ok) = @_;
8308 27         48 my @CF;
8309 27         96 while ($den > 0) {
8310 476         34364 my($quo,$rem) = Mtdivrem($num,$den);
8311 476         1244 ($num,$den) = ($den,$rem);
8312 476         1802 push @CF, $quo;
8313             }
8314 27 50 33     106 croak "Rational must be reduced" unless $num == 1 || $non_reduce_ok;
8315 27         148 @CF;
8316             }
8317              
8318             # https://kconrad.math.uconn.edu/blurbs/ugradnumthy/contfrac-neg-invert.pdf
8319             sub _negcfrac {
8320 11     11   29 my(@CF) = @_;
8321 11         33 my $neg0 = Mnegint($CF[0]);
8322 11 100       40 if (@CF == 1) {
    100          
8323 3         5 $CF[0] = $neg0;
8324             } elsif ($CF[1] == 1) {
8325 2         16 splice(@CF, 0, 3, Msub1int($neg0), Madd1int($CF[2]));
8326             } else {
8327 6         31 splice(@CF, 0, 2, Msub1int($neg0), 1, Msub1int($CF[1]));
8328             }
8329 11         106 @CF;
8330             }
8331              
8332             sub contfrac {
8333 16     16 0 66056 my($num,$den) = @_;
8334 16         136 validate_integer($num);
8335 16         3134 validate_integer_positive($den);
8336              
8337 16         139 my @CF = _rational_cfrac(Mabsint($num),$den,1);
8338 16 100       91 return ($num >= 0) ? @CF : _negcfrac(@CF);
8339             }
8340              
8341             sub from_contfrac {
8342 18 50   18 0 19511 return (0,1) unless @_;
8343              
8344 18         47 my $b0 = shift @_;
8345 18         68 validate_integer($b0);
8346              
8347 18         49 my($A0,$A1,$B0,$B1) = (1,$b0,0,1);
8348              
8349 18         54 while (@_) {
8350 330         37906 my $bi = shift @_;
8351 330         1089 validate_integer_positive($bi);
8352 330         1528 ($A0,$A1) = ($A1, Maddint(Mmulint($bi,$A1),$A0));
8353 330         43608 ($B0,$B1) = ($B1, Maddint(Mmulint($bi,$B1),$B0));
8354             }
8355 18         1017 return ($A1,$B1);
8356             }
8357              
8358             sub next_calkin_wilf {
8359 1     1 0 4 my($num,$den) = @_;
8360 1         4 validate_integer_positive($num);
8361 1         3 validate_integer_positive($den);
8362             # Check gcd to ensure a valid CW entry?
8363 1         6 ($den, Mvecprod(2,$den,Mdivint($num,$den)) + $den - $num);
8364             }
8365             sub next_stern_brocot {
8366 1     1 0 4 my($num,$den) = @_;
8367 1         7 validate_integer_positive($num);
8368 1         4 validate_integer_positive($den);
8369             # There should be a better solution
8370 1         4 nth_stern_brocot(Madd1int(stern_brocot_n($num,$den)));
8371             }
8372              
8373             sub calkin_wilf_n {
8374 5     5 0 6367 my($num,$den) = @_;
8375 5         27 validate_integer_positive($num);
8376 5         20 validate_integer_positive($den);
8377              
8378 5         19 my @CF = _rational_cfrac($num,$den);
8379             # Note: vecsum(@CF) gives the number of bits in the output
8380              
8381 5         13 $CF[-1]--;
8382 5         29 my $bitstr = '1';
8383 5         78 $bitstr .= (1-($_%2)) x $CF[$_] for reverse 0 .. $#CF;
8384 5         375 return Mfromdigits($bitstr,2);
8385             }
8386             sub stern_brocot_n {
8387 6     6 0 84318 my($num,$den) = @_;
8388 6         33 validate_integer_positive($num);
8389 6         21 validate_integer_positive($den);
8390 6         28 my @CF = _rational_cfrac($num,$den);
8391 6         20 $CF[-1]--;
8392 6         19 my $bitstr = '1';
8393 6         91 $bitstr .= (1-($_%2)) x $CF[$_] for 0 .. $#CF;
8394 6         296 return Mfromdigits($bitstr,2);
8395             }
8396              
8397             sub nth_calkin_wilf {
8398 5     5 0 5088 my($n) = @_;
8399 5         47 validate_integer_positive($n);
8400              
8401 5         34 my @M = (1,0);
8402 5         33 $M[$_] = Mvecsum(@M) for split(//, Mtodigitstring($n,2));
8403 5         105 ($M[1],$M[0]);
8404             }
8405             sub nth_stern_brocot {
8406 5     5 0 4627 my($n) = @_;
8407 5         42 validate_integer_positive($n);
8408              
8409 5         16 my @M = (1,0);
8410 5         32 my @bits = split(//,Mtodigitstring($n,2));
8411 5         231 $M[$_] = Mvecsum(@M) for 1,reverse(@bits[1..$#bits]);
8412 5         86 ($M[1],$M[0]);
8413             }
8414              
8415             sub nth_stern_diatomic {
8416 1     1 0 5 my ($n) = @_;
8417 1         8 validate_integer_nonneg($n);
8418 1         5 my @M = (1,0);
8419 1         7 $M[$_] = Mvecsum(@M) for split(//, Mtodigitstring($n,2));
8420 1         14 $M[1];
8421             }
8422              
8423             sub farey {
8424 3     3 0 12 my($n,$k) = @_;
8425 3         14 validate_integer_positive($n);
8426 3         14 my $len = Madd1int(Math::Prime::Util::sumtotient($n));
8427              
8428 3         48 my($p0, $q0, $p1, $q1, $p2, $q2, $j) = (0,1,1,$n);
8429              
8430 3 100       13 if (defined $k) {
8431 1         3 validate_integer_nonneg($k);
8432 1 50       3 return undef if $k >= $len;
8433 1         4 for (1 .. $k) {
8434 146         290 $j = Mdivint(($q0 + $n), $q1);
8435 146         268 $p2 = Mmulint($j, $p1) - $p0;
8436 146         318 $q2 = Mmulint($j, $q1) - $q0;
8437 146         340 ($p0, $q0, $p1, $q1) = ($p1, $q1, $p2, $q2);
8438             }
8439 1         33 return [$p0,$q0];
8440             }
8441              
8442 2 100       16 return $len unless wantarray;
8443              
8444 1         12 my @V;
8445 1         5 for (1 .. $len) {
8446 13         32 push @V, [$p0, $q0];
8447 13         30 $j = Mdivint(($q0 + $n), $q1);
8448 13         23 $p2 = Mmulint($j, $p1) - $p0;
8449 13         21 $q2 = Mmulint($j, $q1) - $q0;
8450 13         24 ($p0, $q0, $p1, $q1) = ($p1, $q1, $p2, $q2);
8451             }
8452 1         46 @V;
8453             }
8454              
8455             # Uses gcdext to find next entry with only one point.
8456             sub next_farey {
8457 1     1 0 6 my($n,$frac) = @_;
8458 1         5 validate_integer_positive($n);
8459 1 50       8 croak "next_farey second argument not an array reference" unless ref($frac) eq 'ARRAY';
8460 1         3 my($p,$q) = @$frac;
8461 1         5 validate_integer_nonneg($p);
8462 1         4 validate_integer_positive($q);
8463 1 50       5 return undef if $p >= $q;
8464 1         6 my($u,$v,$g) = Mgcdext($p,$q);
8465 1 50       6 ($p,$q) = (Mdivint($p,$g),Mdivint($q,$g)) if $g != 1;
8466 1         5 my $d = Mmulint(Mdivint(($n+$u),$q),$q) - $u;
8467 1         6 my $c = Mdivint((Mmulint($d,$p)+1),$q);
8468 1         11 [$c,$d];
8469             }
8470              
8471             sub farey_rank {
8472 2     2 0 6 my($n,$frac) = @_;
8473 2         29 validate_integer_positive($n);
8474 2 50       9 croak "next_farey second argument not an array reference" unless ref($frac) eq 'ARRAY';
8475 2         7 my($p,$q) = @$frac;
8476 2         7 validate_integer_nonneg($p);
8477 2         20 validate_integer_positive($q);
8478              
8479 2 50       8 return 0 if $p == 0;
8480              
8481 2         19 my $g = Mgcd($p,$q);
8482 2 50       8 ($p,$q) = (Mdivint($p,$g),Mdivint($q,$g)) if $g != 1;
8483              
8484 2         16 my @count = (0,0,map { Mdivint(Mmulint($p,$_)-1,$q); } 2..$n);
  374         715  
8485 2         32 my $sum = 1;
8486 2         10 for my $i (2 .. $n) {
8487 374         601 my $icount = $count[$i];
8488 374         799 for (my $j = Mmulint($i,2); $j <= $n; $j = Maddint($j,$i)) {
8489 1280         2634 $count[$j] -= $icount;
8490             }
8491 374         704 $sum += $icount;
8492             }
8493 2         100 $sum;
8494             }
8495              
8496             # End of Rational maps
8497              
8498              
8499             sub _is_perfect_square {
8500 260     260   59739 my($n) = @_;
8501 260 100       1070 return (1,1,0,0,1)[$n] if $n <= 4;
8502              
8503 244 100       24048 if (ref($n)) {
8504 110 100       1134 return 0 if ((1 << Mmodint($n,32)) & 0xfdfcfdec);
8505 35         402 my $sq = Msqrtint($n);
8506 35 100       2963 return 1 if Mmulint($sq,$sq) == $n;
8507             } else {
8508 134 100       702 return 0 if (1 << ($n & 31)) & 0xfdfcfdec;
8509 51 100       266 my $sq = $n < 562949953421312 ? int(sqrt($n)) : Msqrtint($n);
8510 51 100       279 return 1 if ($sq*$sq) == $n;
8511             }
8512 67         10052 0;
8513             }
8514              
8515             sub is_primitive_root {
8516 22     22 0 33244 my($a, $n) = @_;
8517 22         2243 validate_integer($a);
8518 22         300 validate_integer_abs($n);
8519              
8520 22 50       1672 return (undef,1)[$n] if $n <= 1;
8521 22 100 66     1534 $a = Mmodint($a, $n) if $a < 0 || $a >= $n;
8522 22 100       1054 return 0+($a == $n-1) if $n <= 4;
8523 17 100       1434 return 0 if $a <= 1;
8524              
8525             return Math::Prime::Util::GMP::is_primitive_root($a,$n)
8526 16 50       109 if $Math::Prime::Util::_GMPfunc{"is_primitive_root"};
8527              
8528             # my $order = Mznorder($a,$n); return 0 unless defined $order; return 0+($order == Mtotient($n));
8529              
8530 16 100       96 if (Mis_even($n)) {
8531 2 50       263 return 0 if ($n % 4) == 0; # n can't still be even after we shift it
8532 2 50       1352 return 0 if Mis_even($a); # n and a cannot both be even
8533 2         13 $n = Mrshiftint($n); # a is odd, so it is a primroot of p^k also
8534             }
8535 16 100       1052 return 0 if Mgcd($a, $n) != 1;
8536 15 100       84 return 0 if _is_perfect_square($a);
8537              
8538 14         39 my ($p,$k,$phi);
8539 14         159 $k = Mis_prime_power($n,\$p);
8540 14 50       78 return 0 if !$k;
8541 14         36 $n = $p;
8542 14         89 $phi = Msub1int($n);
8543 14 50 66     1176 return 0 if $k > 1 && Mpowmod($a, $phi, Mmulint($p,$p)) == 1;
8544              
8545 14 100       2319 return 0 if Mkronecker($a,$n) != -1;
8546 13 50 66     136 return 0 if ($phi % 3) == 0 && Mpowmod($a,Mdivint($phi,3),$n) == 1;
8547 13 50 66     2350 return 0 if ($phi % 5) == 0 && Mpowmod($a,Mdivint($phi,5),$n) == 1;
8548 13         2299 foreach my $f (Mfactor_exp($phi)) {
8549 39         5965 my $fp = $f->[0];
8550 39 50 66     299 return 0 if $fp > 5 && Mpowmod($a, Mdivint($phi,$fp), $n) == 1;
8551             }
8552 13         1399 1;
8553             }
8554              
8555             sub znorder {
8556 6     6 0 6181 my($a, $n) = @_;
8557 6         37 validate_integer_abs($n);
8558 6 50       431 return (undef,1)[$n] if $n <= 1;
8559 6         672 $a = Mmodint($a, $n);
8560 6 50       27 return undef if $a <= 0;
8561 6 50       35 return 1 if $a == 1;
8562              
8563             return reftyped($_[0], Math::Prime::Util::GMP::znorder($a,$n))
8564 6 50       25 if $Math::Prime::Util::_GMPfunc{"znorder"};
8565              
8566 6 100       32 return undef if Mgcd($a, $n) > 1;
8567              
8568             # Factor n, compute znorder mod each prime power, LCM the results.
8569             # This is much faster than working mod n because each p^e is smaller.
8570 4         24 my $order = 1;
8571 4         24 foreach my $fn (Mfactor_exp($n)) {
8572 12         54 my($p, $e) = @$fn;
8573 12 100       47 my $pe = ($e == 1) ? $p : Mpowint($p, $e);
8574 12         42 my $amod = Mmodint($a, $pe);
8575 12 100       37 next if $amod <= 1;
8576             # phi(p^e) = (p-1) * p^(e-1)
8577 11         36 my $pm1 = Msubint($p, 1);
8578 11 100       53 my $phi = ($e == 1) ? $pm1 : Mmulint($pm1, Mpowint($p, $e-1));
8579              
8580             # For small phi, enumerate sorted divisors directly.
8581 11 50       42 if ($phi < 2 ** MPU_MAXBITS) {
8582 11         21 my $found = 0;
8583 11         70 foreach my $d (Mdivisors($phi)) {
8584 86 100       2968 if (Mpowmod($amod, $d, $pe) == 1) {
8585 11         373 $order = Mlcm($order, $d);
8586 11         30 $found = 1;
8587 11         26 last;
8588             }
8589             }
8590 11 50       50 return undef unless $found;
8591 11         31 next;
8592             }
8593              
8594             # Algorithm 1.7 from A. Das applied to phi(p^e).
8595 0         0 my $k = 1;
8596 0         0 foreach my $f (Mfactor_exp($phi)) {
8597 0         0 my($pi, $ei, $enum) = ($f->[0], $f->[1], 0);
8598 0         0 my $phidiv = Mdivint($phi, Mpowint($pi, $ei));
8599 0         0 my $b = Mpowmod($amod, $phidiv, $pe);
8600 0         0 while ($b != 1) {
8601 0 0       0 return undef if $enum++ >= $ei;
8602 0         0 $b = Mpowmod($b, $pi, $pe);
8603 0         0 $k = Mmulint($k, $pi);
8604             }
8605             }
8606 0         0 $order = Mlcm($order, $k);
8607             }
8608 4         80 $order;
8609             }
8610              
8611             sub _dlp_trial {
8612 3     3   12 my ($a,$g,$p,$limit) = @_;
8613 3 50 33     24 $limit = $p if !defined $limit || $limit > $p;
8614              
8615 3 50       338 if ($limit < 1_000_000_000) {
8616 3         26 my $t = $g;
8617 3         12 for my $k (1 .. $limit) {
8618 215 100       5022 return $k if $t == $a;
8619 213         1193 $t = Mmulmod($t, $g, $p);
8620             }
8621 1         6 return 0;
8622             }
8623              
8624 0         0 ($a, $g, $p, $limit) = map { tobigint($_) } ($a, $g, $p, $limit);
  0         0  
8625 0         0 my $t = tobigint($g);
8626 0         0 for (my $k = tobigint(1); $k < $limit; $k++) {
8627 0 0       0 return Maddint($k,0) if $t == $a;
8628 0         0 $t *= $g;
8629 0         0 $t %= $p;
8630             }
8631 0         0 0;
8632             }
8633             sub _dlp_bsgs {
8634 1     1   5 my ($a,$g,$p,$_verbose) = @_;
8635 1         20 my $invg = Minvmod($g, $p);
8636 1 50       9 return 0 unless defined $invg;
8637 1         9 my $N = Madd1int(Msqrtint($p-1));
8638             # Limit for time and space.
8639 1 50       9 my $b = $N > 4_000_000 ? 4_000_000 : $N;
8640              
8641 1         4 my %hash;
8642 1         3 my $am = 1;
8643 1         22 my $gm = Mpowmod($invg, $N, $p);
8644 1         47 my $key = $a;
8645 1         20 my $r;
8646              
8647 1 50       8 print " BSGS starting $b loops\n" if $_verbose > 1;
8648 1         5 foreach my $m (0 .. $b) {
8649             # Baby Step
8650 86 50       229 if ($m <= $N) {
8651 86         237 $r = $hash{"$am"};
8652 86 50       249 if (defined $r) {
8653 0 0       0 print " bsgs found in stage 1 after $m tries\n" if $_verbose;
8654 0         0 $r = Mmuladdmod($r, $N, $m, $p);
8655 0         0 return $r;
8656             }
8657 86         345 $hash{"$am"} = $m;
8658 86         223 $am = Mmulmod($am,$g,$p);
8659 86 50       313 if ($am == $a) {
8660 0 0       0 print " bsgs found during bs\n" if $_verbose;
8661 0         0 return $m+1;
8662             }
8663             }
8664              
8665             # Giant Step
8666 86         16003 $r = $hash{"$key"};
8667 86 100       223 if (defined $r) {
8668 1 50       23 print " bsgs found in stage 2 after $m tries\n" if $_verbose;
8669 1         49 $r = Mmuladdmod($m, $N, $r, $p);
8670 1         97 return $r;
8671             }
8672 85         822 $hash{"$key"} = $m;
8673 85         301 $key = Mmulmod($key,$gm,$p);
8674             }
8675 0         0 0;
8676             }
8677              
8678             sub znlog {
8679 3     3 0 1840 my($a, $g, $n) = @_;
8680 3         27 validate_integer($a);
8681 3         148 validate_integer($g);
8682 3         113 validate_integer_abs($n);
8683 3 50       514 return (undef,0,1)[$n] if $n <= 1;
8684 3         557 $a = Mmodint($a, $n);
8685 3         20 $g = Mmodint($g, $n);
8686 3 50 33     26 return 0 if $a == 1 || $g == 0 || $n < 2;
      33        
8687              
8688 3         1498 my $_verbose = getconfig()->{'verbose'};
8689              
8690             # For large p, znorder can be very slow. Do a small trial test first.
8691 3         27 my $x = _dlp_trial($a, $g, $n, 200);
8692              
8693 3 100       182 if ($x == 0) {
8694 1         7 ($a,$g,$n) = map { tobigint($_) } ($a,$g,$n);
  3         19  
8695 1         25 $x = _dlp_bsgs($a, $g, $n, $_verbose);
8696 1 50 33     8 $x = _bigint_to_int($x) if ref($x) && $x <= INTMAX;
8697 1 50 33     11 return $x if $x > 0 && Mpowmod($g,$x,$n) == $a;
8698 0 0 0     0 print " BSGS giving up\n" if $x == 0 && $_verbose;
8699 0 0 0     0 print " BSGS incorrect answer $x\n" if $x > 0 && $_verbose > 1;
8700 0         0 $x = _dlp_trial($a,$g,$n);
8701             }
8702 2 50 33     15 $x = _bigint_to_int($x) if ref($x) && $x <= INTMAX;
8703 2 50       26 return ($x == 0) ? undef : $x;
8704             }
8705              
8706             sub znprimroot {
8707 12     12 0 30373 my($n) = @_;
8708 12         101 validate_integer_abs($n);
8709 12 100       1357 return (undef,0,1,2,3)[$n] if $n <= 4;
8710 10 100       1188 return if $n % 4 == 0;
8711              
8712 9         3061 my $iseven = Mis_even($n);
8713 9 100       610 $n = Mrshiftint($n) if $iseven;
8714              
8715 9         515 my($k,$p);
8716 9         83 $k = Mis_prime_power($n, \$p);
8717 9 100       40 return if $k < 1;
8718 8 50 33     31 return 5 if $p == 3 && $iseven;
8719 8         1169 my $ispow = ($k > 1);
8720              
8721 8         27 my $phi = $p-1;
8722 8 100       1953 my $psquared = $ispow ? Mmulint($p,$p) : 0;
8723              
8724 34         215 my @phidivfac = map { Mdivint($phi, $_) }
8725 42         110 grep { $_ > 2 }
8726 8         1049 map { $_->[0] } Mfactor_exp($phi);
  42         113  
8727 8         55 my $a = 1;
8728 8         17 while (1) {
8729 127 100       2113 $a += $iseven ? 2 : 1;
8730 127 50       339 return if $a >= $p;
8731 127 100 100     4884 next if $a == 4 || $a == 8 || $a == 9;
      100        
8732 119 100       441 next if Mkronecker($a,$p) != -1;
8733 37 100   70   581 next if Mvecany(sub { Mpowmod($a,$_,$p) == 1 }, @phidivfac);
  70         13733  
8734 8 50 66     2230 return $a unless $ispow && Mpowmod($a,$phi,$psquared) == 1;
8735             }
8736             }
8737              
8738             sub qnr {
8739 3     3 0 226 my($n) = @_;
8740 3         26 validate_integer_abs($n);
8741 3 50       372 return (undef,1,2)[$n] if $n <= 2;
8742              
8743 3 50       463 return 2 if Mkronecker(2,$n) == -1;
8744              
8745 3 100       30 if (Mis_prime($n)) {
8746 2         11 for (my $a = 3; $a < $n; $a = Mnext_prime($a)) {
8747 14 100       1267 return $a if Mkronecker($a,$n) == -1;
8748             }
8749             } else {
8750 1 50       244 if ($n % 2 == 0) {
8751 1         368 my $e = Mvaluation($n, 2);
8752 1         6 $n >>= $e;
8753 1 50 33     399 return 2 if $n == 1 || $e >= 2;
8754             }
8755 0 0 0     0 return 2 if !($n%3) || !($n%5) || !($n%11) || !($n%13) || !($n%19);
      0        
      0        
      0        
8756 0         0 my @F = Mfactor_exp($n);
8757 0         0 for (my $a = 2; $a < $n; $a = Mnext_prime($a)) {
8758 0         0 for my $pe (@F) {
8759 0         0 my $p = $pe->[0];
8760 0 0 0     0 return $a if $a < $p && Mkronecker($a,$p) == -1;
8761             }
8762             }
8763             }
8764 0         0 0;
8765             }
8766              
8767              
8768             # Find first D in sequence (5,-7,9,-11,13,-15,...) where (D|N) == -1
8769             sub _lucas_selfridge_params {
8770 8     8   29 my($n) = @_;
8771              
8772             # D is typically quite small: 67 max for N < 10^19. However, it is
8773             # theoretically possible D could grow unreasonably. I'm giving up at 4000M.
8774 8         22 my $d = 5;
8775 8         18 my $sign = 1;
8776 8         19 while (1) {
8777 21         85 my $gcd = Mgcd($d, $n);
8778 21 50 33     84 return (0,0,0) if $gcd > 1 && $gcd != $n; # Found divisor $d
8779 21         76 my $j = Mkronecker($d * $sign, $n);
8780 21 100       77 last if $j == -1;
8781 13         30 $d += 2;
8782 13 50       40 croak "Could not find Jacobi sequence for $n" if $d > 4_000_000_000;
8783 13         29 $sign = -$sign;
8784             }
8785 8         21 my $D = $sign * $d;
8786 8         19 my $P = 1;
8787 8         29 my $Q = int( (1 - $D) / 4 );
8788 8         35 ($P, $Q, $D)
8789             }
8790              
8791             sub _lucas_extrastrong_params {
8792 162     162   540 my($n, $increment) = @_;
8793 162 100       753 $increment = 1 unless defined $increment;
8794 162 50       606 croak "internal lucas, increment $increment" if $increment < 1;
8795              
8796 162         504 my ($P, $Q, $D) = (3, 1, 5);
8797 162         361 while (1) {
8798 382         2556 my $gcd = Mgcd($D, $n);
8799 382 50 33     1669 return (0,0,0) if $gcd > 1 && $gcd != $n; # Found divisor $d
8800 382 100       2096 last if Mkronecker($D, $n) == -1;
8801 220         605 $P += $increment;
8802 220 50       590 croak "Could not find Jacobi sequence for $n" if $P > 65535;
8803 220         529 $D = $P*$P - 4;
8804             }
8805 162         976 ($P, $Q, $D);
8806             }
8807              
8808             # returns U_k, V_k, Q_k all mod n
8809             sub lucas_sequence {
8810 0     0 0 0 my($n, $P, $Q, $k) = @_;
8811              
8812 0 0       0 croak "lucas_sequence: n must be > 0" if $n < 1;
8813 0 0       0 croak "lucas_sequence: k must be >= 0" if $k < 0;
8814 0 0       0 return (0,0,0) if $n == 1;
8815              
8816 0 0 0     0 if ($Math::Prime::Util::_GMPfunc{"lucas_sequence"} && $Math::Prime::Util::GMP::VERSION >= 0.30 && !ref($P) && !ref($Q)) {
      0        
      0        
8817 0         0 return maybetobigintall(
8818             Math::Prime::Util::GMP::lucas_sequence($n, $P, $Q, $k)
8819             );
8820             }
8821              
8822 0         0 return (lucasuvmod($P,$Q,$k,$n), Mpowmod($Q,$k,$n));
8823             }
8824              
8825             sub lucasuv {
8826 80     80 0 73166 my($P, $Q, $k) = @_;
8827              
8828 80 50       315 croak "lucasuv: k must be >= 0" if $k < 0;
8829 80 50       281 return (0,2) if $k == 0;
8830              
8831 80 50 33     446 if ($Math::Prime::Util::_GMPfunc{"lucasuv"} && $Math::Prime::Util::GMP::VERSION >= 0.53) {
8832 0         0 return maybetobigintall(
8833             Math::Prime::Util::GMP::lucasuv($P, $Q, $k)
8834             );
8835             }
8836              
8837             # Do this very generic. Optimize later if needed (D=0,Q=1,Q=-1,n odd).
8838              
8839 80         218 ($P,$Q) = map { tobigint($_) } ($P,$Q);
  160         606  
8840 80         239 my($Uh, $Vl, $Vh, $Ql, $Qh) = map { tobigint($_) } (1, 2, $P, 1, 1);
  400         1003  
8841              
8842 80         245 my $s = 0;
8843 80         618 my @kbits = Mtodigits($k, 2);
8844 80         334 while ($kbits[-1] == 0) { $s++; pop @kbits; } # Remove trailing zeros.
  71         131  
  71         166  
8845 80         170 pop @kbits; # Remove trailing 1.
8846              
8847 80         224 foreach my $bit (@kbits) {
8848 394         174092 $Ql *= $Qh;
8849 394 100       110067 if ($bit) {
8850 205         604 $Qh = $Ql * $Q;
8851 205         33762 $Uh = $Uh * $Vh;
8852 205         94585 $Vl = $Vh * $Vl - $P * $Ql;
8853 205         181658 $Vh = $Vh * $Vh - ($Qh+$Qh);
8854             } else {
8855 189         405 $Qh = $Ql;
8856 189         747 $Uh = $Uh * $Vl - $Ql;
8857 189         95163 $Vh = $Vh * $Vl - $P * $Ql;
8858 189         121777 $Vl = $Vl * $Vl - ($Ql+$Ql);
8859             }
8860             }
8861 80         105887 $Ql *= $Qh;
8862 80         118957 $Qh = $Ql * $Q;
8863 80         22462 $Uh = $Uh * $Vl - $Ql;
8864 80         244025 $Vl = $Vh * $Vl - $P * $Ql;
8865 80         271245 $Ql *= $Qh;
8866 80         457775 for (1 .. $s) {
8867 71         4077 $Uh *= $Vl;
8868 71         752592 $Vl = $Vl * $Vl - ($Ql+$Ql);
8869 71         1005208 $Ql *= $Ql;
8870             }
8871 80 100 66     1836903 $Uh = _bigint_to_int($Uh) if $Uh <= INTMAX && $Uh >= INTMIN;
8872 80 100 100     18331 $Vl = _bigint_to_int($Vl) if $Vl <= INTMAX && $Vl >= INTMIN;
8873 80         18426 ($Uh, $Vl);
8874             }
8875              
8876             sub lucasuvmod {
8877 146     146 0 38081 my($P, $Q, $k, $n) = @_;
8878 146         667 validate_integer($P);
8879 146         696 validate_integer($Q);
8880 146         1136 validate_integer_nonneg($k);
8881 146         4448 validate_integer_abs($n);
8882 146 50       27733 return if $n == 0;
8883 146 50       25767 return (0,0) if $n == 1;
8884 146 50       25534 return (0, Mmodint(2,$n)) if $k == 0;
8885              
8886 146 50 33     19256 if ($Math::Prime::Util::_GMPfunc{"lucasuvmod"} && $Math::Prime::Util::GMP::VERSION >= 0.53) {
8887 0         0 return maybetobigintall(
8888             Math::Prime::Util::GMP::lucasuvmod($P, $Q, $k, $n)
8889             );
8890             }
8891              
8892 146 50 33     950 $P = Mmodint($P,$n) if $P < 0 || $P >= $n;
8893 146 100 66     18668 $Q = Mmodint($Q,$n) if $Q < 0 || $Q >= $n;
8894 146         29926 my $D = Mmulsubmod($P, $P, Mmulmod(4,$Q,$n), $n);
8895              
8896 146 50       8687 if ($D == 0) {
8897 0         0 my $S = Mdivmod($P, 2, $n);
8898 0 0       0 if ($S) {
8899 0         0 my $U = Mmulmod($k, Mpowmod($S, $k-1, $n), $n);
8900 0         0 my $V = Mmulmod(2, Mpowmod($S, $k, $n), $n);
8901 0         0 return ($U, $V);
8902             }
8903             }
8904              
8905 146         4799 my @kbits = Mtodigits($k, 2);
8906 146         483 shift @kbits; # Remove leading 1
8907 146         429 my $U = 1;
8908 146         446 my $V = $P;
8909 146         1196 my $invD = Minvmod($D, $n);
8910 146         1046 my $nisodd = Mis_odd($n);
8911              
8912 146 100 66     12531 if ($Q == 1 && $invD) {
    100 66        
    100 66        
8913 113         4557 $U = Mmulsubmod($P, $P, 2, $n);
8914 113         5097 foreach my $bit (@kbits) {
8915 8120         1734416 my $T = Mmulsubmod($U, $V, $P, $n);
8916 8120 100       1740985 if ($bit) {
8917 3489         8329 $V = $T;
8918 3489         22881 $U = Mmulsubmod($U, $U, 2, $n);
8919             } else {
8920 4631         10005 $U = $T;
8921 4631         28503 $V = Mmulsubmod($V, $V, 2, $n);
8922             }
8923             }
8924 113         23476 $V = Mmodint($V,$n);
8925 113         969 $U = Maddmod($U, $U, $n);
8926 113         22519 $U = Msubmod($U, Mmulmod($V, $P, $n), $n);
8927 113         13385 $U = Mmulmod($U, $invD, $n);
8928             } elsif ($nisodd && ($Q == 1 || $Q == ($n-1))) {
8929 13         25 my $ps = ($P == 1);
8930 13         23 my $qs = ($Q == 1);
8931 13         43 my $halfn = Madd1int(Mrshiftint($n));
8932 13         47 foreach my $bit (@kbits) {
8933 124         356 $U = Mmulmod($U, $V, $n);
8934 124 100       402 $V = ($qs) ? Mmulsubmod($V,$V,2,$n) : Mmuladdmod($V,$V,2,$n);
8935 124         205 $qs = 1;
8936 124 100       285 if ($bit) {
8937 70         187 my $t = Mmulmod($U, $D, $n);
8938 70 50       267 $U = (!$ps) ? Mmuladdmod($U,$P,$V,$n) : Maddmod($U,$V,$n);
8939 70 100       211 if (Mis_odd($U)) {
8940 18         56 $U = Maddint(Mrshiftint($U), $halfn);
8941             } else {
8942 52         167 $U = Mrshiftint($U);
8943             }
8944 70 50       291 $V = (!$ps) ? Mmuladdmod($V,$P,$t,$n) : Maddmod($V,$t,$n);
8945 70 100       177 if (Mis_odd($V)) {
8946 18         55 $V = Maddint(Mrshiftint($V), $halfn);
8947             } else {
8948 52         168 $V = Mrshiftint($V);
8949             }
8950 70         205 $qs = ($Q==1);
8951             }
8952             }
8953             } elsif ($nisodd) {
8954 11         4784 my $Qk = $Q;
8955 11         70 my $halfn = Madd1int(Mrshiftint($n));
8956 11         1468 foreach my $bit (@kbits) {
8957 259         22174 $U = Mmulmod($U, $V, $n);
8958 259         51085 $V = Mmulsubmod($V, $V, Maddmod($Qk, $Qk, $n), $n);
8959 259         44564 $Qk = Mmulmod($Qk, $Qk, $n);
8960 259 100       60200 if ($bit) {
8961 130         618 my $t = Mmulmod($U, $D, $n);
8962 130         24945 $U = Mmuladdmod($U, $P, $V, $n);
8963 130 100       21736 if (Mis_odd($U)) {
8964 54         3218 $U = Maddint(Mrshiftint($U), $halfn);
8965             } else {
8966 76         5087 $U = Mrshiftint($U);
8967             }
8968 130         21648 $V = Mmuladdmod($V, $P, $t, $n);
8969 130 100       22671 if (Mis_odd($V)) {
8970 66         5068 $V = Maddint(Mrshiftint($V), $halfn);
8971             } else {
8972 64         3541 $V = Mrshiftint($V);
8973             }
8974 130         21658 $Qk = Mmulmod($Qk, $Q, $n);
8975             }
8976             }
8977             } else {
8978 9         1977 my ($s, $Uh, $Vl, $Vh, $Ql, $Qh) = (0, 1, 2, $P, 1, 1);
8979 9         48 unshift @kbits, 1; # Add back leading 1.
8980 9         38 while ($kbits[-1] == 0) { $s++; pop @kbits; } # Remove trailing zeros.
  3         8  
  3         12  
8981 9         22 pop @kbits; # Remove trailing 1.
8982 9         27 foreach my $bit (@kbits) {
8983 247         27621 $Ql = Mmulmod($Ql, $Qh, $n);
8984 247 100       24239 if ($bit) {
8985 138         561 $Qh = Mmulmod($Ql, $Q, $n);
8986 138         11193 $Uh = Mmulmod($Uh, $Vh, $n);
8987 138         15112 $Vl = Mmulsubmod($Vh, $Vl, Mmulmod($P, $Ql, $n), $n);
8988 138         16589 $Vh = Mmulsubmod($Vh, $Vh, Maddmod($Qh, $Qh, $n), $n);
8989             } else {
8990 109         228 $Qh = $Ql;
8991 109         482 $Uh = Mmulsubmod($Uh, $Vl, $Ql, $n);
8992 109         13626 $Vh = Mmulsubmod($Vh, $Vl, Mmulmod($P, $Ql, $n), $n);
8993 109         13569 $Vl = Mmulsubmod($Vl, $Vl, Maddmod($Ql, $Ql, $n), $n);
8994             }
8995             }
8996 9         1868 $Ql = Mmulmod($Ql, $Qh, $n);
8997 9         1943 $Qh = Mmulmod($Ql, $Q, $n);
8998 9         1829 $Uh = Mmulsubmod($Uh, $Vl, $Ql, $n);
8999 9         1727 $Vl = Mmulsubmod($Vh, $Vl, Mmulmod($P, $Ql, $n), $n);
9000 9         2162 $Ql = Mmulmod($Ql, $Qh, $n);
9001 9         2062 for (1 .. $s) {
9002 3         21 $Uh = Mmulmod($Uh, $Vl, $n);
9003 3         815 $Vl = Mmulsubmod($Vl, $Vl, Maddmod($Ql, $Ql, $n), $n);
9004 3         792 $Ql = Mmulmod($Ql, $Ql, $n);
9005             }
9006 9         812 ($U, $V) = ($Uh, $Vl);
9007             }
9008 146         17619 ($U,$V);
9009             }
9010              
9011             sub lucasu {
9012             return maybetobigint( Math::Prime::Util::GMP::lucasu($_[0], $_[1], $_[2]) )
9013 27 50   27 0 105644 if $Math::Prime::Util::_GMPfunc{"lucasu"};
9014 27         113 (lucasuv(@_))[0];
9015             }
9016             sub lucasv {
9017             return maybetobigint( Math::Prime::Util::GMP::lucasv($_[0], $_[1], $_[2]) )
9018 27 50   27 0 48778 if $Math::Prime::Util::_GMPfunc{"lucasv"};
9019 27         119 (lucasuv(@_))[1];
9020             }
9021              
9022             sub lucasumod {
9023             return maybetobigint( Math::Prime::Util::GMP::lucasumod($_[0], $_[1], $_[2], $_[3]) )
9024 15 50   15 0 5528 if $Math::Prime::Util::_GMPfunc{"lucasumod"};
9025 15         84 (lucasuvmod(@_))[0];
9026             }
9027             sub lucasvmod {
9028 9     9 0 6624 my($P, $Q, $k, $n) = @_;
9029             return maybetobigint( Math::Prime::Util::GMP::lucasvmod($P, $Q, $k, $n) )
9030 9 50       57 if $Math::Prime::Util::_GMPfunc{"lucasvmod"};
9031 9         64 validate_integer($P);
9032 9         272 validate_integer($Q);
9033 9         253 validate_integer_nonneg($k);
9034 9         293 validate_integer_abs($n);
9035 9 50       1440 return if $n == 0;
9036              
9037 9 100       1586 return (lucasuvmod($P, $Q, $k, $n))[1] if $Q != 1;
9038              
9039             # Fast algorithm for Q=1
9040 3         18 $P = Mmodint($P, $n);
9041 3         9 my $V = 2;
9042 3         6 my $U = $P;
9043 3         21 foreach my $bit (Mtodigits($k, 2)) {
9044 74         8696 my $T = Mmulsubmod($U, $V, $P, $n);
9045 74 100       8536 if ($bit) {
9046 31         67 $V = $T;
9047 31         172 $U = Mmulsubmod($U, $U, 2, $n);
9048             } else {
9049 43         97 $U = $T;
9050 43         203 $V = Mmulsubmod($V, $V, 2, $n);
9051             }
9052             }
9053 3         195 return $V;
9054             }
9055              
9056             my %_ppc = (3 => 8, 5 => 20, 7 => 16, 11 => 10, 13 => 28, 17 => 36, 19 => 18);
9057             _register_free_sub(sub {
9058             %_ppc = (3 => 8, 5 => 20, 7 => 16, 11 => 10, 13 => 28, 17 => 36, 19 => 18);
9059             });
9060             sub _pisano_pp {
9061 15     15   26 my($p,$e) = @_;
9062 15 50       33 return 1 if $e == 0;
9063 15 100 66     65 return 3 << ($e-1) if $p == 2 && $e < 32;
9064 12 50       36 return Mlshiftint(3,$e-1) if $p == 2;
9065 12         39 my $k = $_ppc{$p};
9066              
9067 12 100       24 if (!defined $k) {
9068 3         16 $k = Msubint($p, Mkronecker(5,$p));
9069 3         18 for my $f (Mfactor_exp($k)) {
9070 7         15 my($fac,$exp) = @$f;
9071 7         15 for my $j (1 .. $exp) {
9072 8         18 my $rk = Mdivint($k,$fac);
9073 8 100       36 last if Mlucasumod(1, $p-1, $rk, $p) != 0;
9074 2         8 $k = $rk;
9075             }
9076             }
9077 3         13 $_ppc{$p} = $k;
9078             }
9079 12 100       285 $k = Mmulint($k, Mpowint($p, $e-1)) if $e > 1;
9080 12         797 $k;
9081             }
9082             sub pisano_period {
9083 4     4 0 1523 my($n) = @_;
9084 4         38 validate_integer_nonneg($n);
9085 4 50       68 return 0 if $n < 0;
9086 4 50       419 return (0,1,3,8,6,20,24,16,12,24,60)[$n] if $n <= 10;
9087              
9088 4         398 my $k = Mlcm(map { _pisano_pp($_->[0],$_->[1]) } Mfactor_exp($n));
  15         37  
9089              
9090 4         143 my $lim = Mmulint(6,$n);
9091 4         657 for (my $ret = $k; $ret <= $lim; $ret = Maddint($ret,$k)) {
9092 7 100       175 return $ret if Mlucasumod(1, -1, Msub1int($ret), $n) == 1;
9093             }
9094 0         0 undef;
9095             }
9096              
9097             sub is_lucas_pseudoprime {
9098 4     4 0 19 my($n) = @_;
9099              
9100 4 50       16 return 0+($n >= 2) if $n < 4;
9101 4 50 33     42 return 0 if ($n % 2) == 0 || _is_perfect_square($n);
9102              
9103 4         31 my ($P, $Q, $D) = _lucas_selfridge_params($n);
9104 4 50       21 return 0 if $D == 0; # We found a divisor in the sequence
9105 4 50       25 die "Lucas parameter error: $D, $P, $Q\n" if ($D != $P*$P - 4*$Q);
9106              
9107 4         23 my($U, $V) = lucasuvmod($P, $Q, $n+1, $n);
9108 4 50       66 return ($U == 0) ? 1 : 0;
9109             }
9110              
9111             sub is_strong_lucas_pseudoprime {
9112 4     4 0 9 my($n) = @_;
9113              
9114 4 50       14 return 0+($n >= 2) if $n < 4;
9115 4 50 33     29 return 0 if ($n % 2) == 0 || _is_perfect_square($n);
9116              
9117 4         26 my ($P, $Q, $D) = _lucas_selfridge_params($n);
9118 4 50       17 return 0 if $D == 0; # We found a divisor in the sequence
9119 4 50       16 die "Lucas parameter error: $D, $P, $Q\n" if ($D != $P*$P - 4*$Q);
9120              
9121 4         6 my $m = $n+1;
9122 4         9 my($s, $k) = (0, $m);
9123 4   66     18 while ( $k > 0 && !($k % 2) ) {
9124 11         9 $s++;
9125 11         30 $k >>= 1;
9126             }
9127 4         17 my($U, $V) = lucasuvmod($P, $Q, $k, $n);
9128 4 100       40 return 1 if $U == 0;
9129              
9130 2         12 my $Qk = Mpowmod($Q,$k,$n);
9131 2         101 foreach my $r (0 .. $s-1) {
9132 7 100       445 return 1 if $V == 0;
9133 5 50       17 if ($r < ($s-1)) {
9134 5         17 $V = Mmulsubmod($V, $V, Maddmod($Qk,$Qk,$n), $n);
9135 5         18 $Qk = Mmulmod($Qk, $Qk, $n);
9136             }
9137             }
9138 0         0 return 0;
9139             }
9140              
9141             sub is_extra_strong_lucas_pseudoprime {
9142 112     112 0 410 my($n) = @_;
9143              
9144 112 50       510 return 0+($n >= 2) if $n < 4;
9145 112 50 33     23909 return 0 if ($n % 2) == 0 || _is_perfect_square($n);
9146              
9147 112         10223 my ($P, $Q, $D) = _lucas_extrastrong_params($n);
9148 112 50       476 return 0 if $D == 0; # We found a divisor in the sequence
9149 112 50       519 die "Lucas parameter error: $D, $P, $Q\n" if ($D != $P*$P - 4*$Q);
9150              
9151             # This would be a great place to use a factor remove function
9152 112         837 my($s, $k) = (0, Madd1int($n));
9153 112   66     26788 while (Mis_even($k) && $k != 0) {
9154 1338         733770 $s++;
9155 1338         8564 $k = Mrshiftint($k);
9156             }
9157              
9158 112         30034 my($U, $V) = lucasuvmod($P, $Q, $k, $n);
9159 112 50 66     1083 return 1 if $U == 0 && ($V == 2 || $V == Msubint($n,2));
      100        
9160 52         9755 foreach my $r (0 .. $s-2) {
9161 1217 100       284998 return 1 if $V == 0;
9162 1169         267822 $V = Mmulsubmod($V, $V, 2, $n);
9163             }
9164 4         47 return 0;
9165             }
9166              
9167             sub is_almost_extra_strong_lucas_pseudoprime {
9168 50     50 0 194 my($n, $incr) = @_;
9169 50 100       239 if (defined $incr) {
9170 9         25 validate_integer($incr);
9171 9 50 33     93 croak "Invalid lucas parameter increment: $incr" if $incr<1 || $incr>256;
9172             } else {
9173 41         110 $incr = 1;
9174             }
9175              
9176 50 50       199 return 0+($n >= 2) if $n < 4;
9177 50 50 33     479 return 0 if ($n % 2) == 0 || _is_perfect_square($n);
9178              
9179 50         312 my ($P, $Q, $D) = _lucas_extrastrong_params($n, $incr);
9180 50 50       226 return 0 if $D == 0; # We found a divisor in the sequence
9181 50 50       205 die "Lucas parameter error: $D, $P, $Q\n" if ($D != $P*$P - 4*$Q);
9182              
9183 50         294 my($s, $k) = (0, Madd1int($n));
9184 50   66     435 while (Mis_even($k) && $k != 0) {
9185 119         197 $s++;
9186 119         464 $k = Mrshiftint($k);
9187             }
9188 50         655 my @kbits = Mtodigits($k, 2);
9189 50         130 shift @kbits; # Remove leading 1
9190 50         181 my($V,$W) = ($P,$P*$P-2);
9191 50         151 foreach my $bit (@kbits) {
9192 2144 100       3854 if ($bit) {
9193 1197         2802 $V = Mmulsubmod($V, $W, $P, $n);
9194 1197         3000 $W = Mmulsubmod($W, $W, 2, $n);
9195             } else {
9196 947         2078 $W = Mmulsubmod($W, $V, $P, $n);
9197 947         2108 $V = Mmulsubmod($V, $V, 2, $n);
9198             }
9199             }
9200 50 100 100     746 return 1 if $V == 2 || Msubint($n,$V) == 2;
9201 17         74 foreach my $r (0 .. $s-2) {
9202 60 100       281 return 1 if $V == 0;
9203 46         145 $V = Mmulsubmod($V, $V, 2, $n);
9204             }
9205 3         42 return 0;
9206             }
9207              
9208             sub is_frobenius_khashin_pseudoprime {
9209 1     1 0 4 my($n) = @_;
9210 1 50       3 return 0+($n >= 2) if $n < 4;
9211 1 50       3 return 0 unless $n % 2;
9212 1 50       6 return 0 if _is_perfect_square($n);
9213              
9214 1         10 $n = tobigint($n);
9215              
9216 1         3 my($k,$c) = (2,1);
9217 1 50       8 if ($n % 4 == 3) { $c = $n-1; }
  1 0       497  
9218 0         0 elsif ($n % 8 == 5) { $c = 2; }
9219             else {
9220 0         0 do {
9221 0         0 $c += 2;
9222 0         0 $k = Mkronecker($c, $n);
9223             } while $k == 1;
9224             }
9225 1 50 33     255 return 0 if $k == 0 || ($k == 2 && !($n % 3));
      33        
9226              
9227 1 50       308 my $ea = ($k == 2) ? 2 : 1;
9228 1         6 my($ra,$rb,$a,$b,$d) = ($ea,1,$ea,1,$n-1);
9229 1         317 while ($d != 0) {
9230 29 100       46912 if ($d % 2 == 1) {
9231 18         7064 ($ra, $rb) = ( (($ra*$a)%$n + ((($rb*$b)%$n)*$c)%$n) % $n,
9232             (($rb*$a)%$n + ($ra*$b)%$n) % $n );
9233             }
9234 29         31102 $d >>= 1;
9235 29 100       8210 if ($d != 0) {
9236 28         4940 ($a, $b) = ( (($a*$a)%$n + ((($b*$b)%$n)*$c)%$n) % $n,
9237             (($b*$a)%$n + ($a*$b)%$n) % $n );
9238             }
9239             }
9240 1 50 33     444 return ($ra == $ea && $rb == $n-1) ? 1 : 0;
9241             }
9242              
9243             sub is_frobenius_underwood_pseudoprime {
9244 1     1 0 3 my($n) = @_;
9245 1 50       4 return 0+($n >= 2) if $n < 4;
9246 1 50       4 return 0 unless $n % 2;
9247              
9248 1         3 my($a, $temp1, $temp2);
9249 1 50       5 if ($n % 4 == 3) {
9250 1         4 $a = 0;
9251             } else {
9252 0         0 for ($a = 1; $a < 1000000; $a++) {
9253 0 0 0     0 next if $a==2 || $a==4 || $a==7 || $a==8 || $a==10 || $a==14 || $a==16 || $a==18;
      0        
      0        
      0        
      0        
      0        
      0        
9254 0         0 my $j = Mkronecker($a*$a - 4, $n);
9255 0 0       0 last if $j == -1;
9256 0 0 0     0 return 0 if $j == 0 || ($a == 20 && _is_perfect_square($n));
      0        
9257             }
9258             }
9259 1         8 $temp1 = Mgcd(($a+4)*(2*$a+5), $n);
9260 1 50 33     7 return 0 if $temp1 != 1 && $temp1 != $n;
9261              
9262 1         9 $n = tobigint($n);
9263 1         5 my($s, $t, $ap2) = map { tobigint($_) } (1, 2, $a+2);
  3         6  
9264 1         7 my $np1string = todigitstring($n+1,2);
9265 1         5 my $np1len = length($np1string);
9266              
9267 1         5 foreach my $bit (1 .. $np1len-1) {
9268 28         63 $temp2 = $t+$t;
9269 28 50       3056 $temp2 += ($s * $a) if $a != 0;
9270 28         58 $temp1 = $temp2 * $s;
9271 28         3098 $temp2 = $t - $s;
9272 28         3292 $s += $t;
9273 28         2363 $t = ($s * $temp2) % $n;
9274 28         7100 $s = $temp1 % $n;
9275 28 100       3426 if ( substr( $np1string, $bit, 1 ) ) {
9276 17 50       63 if ($a == 0) { $temp1 = $s + $s; }
  17         42  
9277 0         0 else { $temp1 = $s * $ap2; }
9278 17         2101 $temp1 += $t;
9279 17         1384 $t = $t + $t - $s;
9280 17         4187 $s = $temp1;
9281             }
9282             }
9283 1         5 $temp1 = (2*$a+5) % $n;
9284 1 50 33     165 return ($s == 0 && $t == $temp1) ? 1 : 0;
9285             }
9286              
9287             sub _perrin_signature {
9288 2     2   19 my($n) = @_;
9289 2         7 my @S = (1,$n-1,3, 3,0,2);
9290 2 50       8 return @S if $n <= 1;
9291              
9292 2         12 my @nbin = Mtodigits($n,2);
9293 2         6 shift @nbin;
9294              
9295 2         8 while (@nbin) {
9296 54         102 my @SUB = map { Maddmod($n-$S[5-$_], $n-$S[5-$_],$n) } 0..5;
  324         600  
9297 54         104 my @T = map { Mmuladdmod($S[$_], $S[$_], $SUB[$_], $n); } 0..5;
  324         696  
9298              
9299 54         155 my $T01 = Msubmod($T[2], $T[1], $n);
9300 54         129 my $T34 = Msubmod($T[5], $T[4], $n);
9301 54         131 my $T45 = Maddmod($T34, $T[3], $n);
9302 54 100       141 if (shift @nbin) {
9303 29         122 @S = ($T[0], $T01, $T[1], $T[4], $T45, $T[5]);
9304             } else {
9305 25         60 @S = ($T01, $T[1], Maddmod($T01,$T[0],$n), $T34, $T[4], $T45);
9306             }
9307             }
9308 2         9 @S;
9309             }
9310              
9311             sub is_perrin_pseudoprime {
9312 2     2 0 713 my($n, $restrict) = @_;
9313 2         15 validate_integer($n);
9314 2 100       11 if (defined $restrict) { validate_integer_nonneg($restrict); }
  1         10  
9315 1         2 else { $restrict = 0; }
9316 2 50       8 return 0+($n >= 2) if $n < 4;
9317 2 50 66     12 return 0 if $restrict > 2 && ($n % 2) == 0;
9318              
9319 2         8 my @S = _perrin_signature($n);
9320 2 50       9 return 0 unless $S[4] == 0;
9321 2 100       20 return 1 if $restrict == 0;
9322 1 50       10 return 0 unless $S[1] == Msub1int($n);
9323 1 50       5 return 1 if $restrict == 1;
9324 1         6 my $j = Mkronecker(-23,$n);
9325 1 50       6 if ($j == -1) {
9326 0         0 my $B = $S[2];
9327 0         0 my $B2 = Mmulmod($B,$B,$n);
9328 0         0 my $A = Msubmod(Mmuladdmod(3, $B, 1, $n), $B2, $n);
9329 0         0 my $C = Mmulsubmod(3,$B2,2,$n);
9330 0 0 0     0 return 1 if $S[0] == $A && $S[2] == $B && $S[3] == $B && $S[5] == $C && $B != 3 && Mmulsubmod($B2,$B,$B,$n) == 1;
      0        
      0        
      0        
      0        
9331             } else {
9332 1 0 33     7 return 0 if $j == 0 && $n != 23 && $restrict > 2;
      33        
9333 1 50 33     21 return 1 if $S[0] == 1 && $S[2] == 3 && $S[3] == 3 && $S[5] == 2;
      33        
      33        
9334 0 0 0     0 return 1 if $S[0] == 0 && $S[5] == $n-1 && $S[2] != $S[3] && Maddmod($S[2],$S[3],$n) == $n-3 && Mmulmod(Msubmod($S[2],$S[3],$n),Msubmod($S[2],$S[3],$n),$n) == $n-(23%$n);
      0        
      0        
      0        
9335             }
9336 0         0 0;
9337             }
9338              
9339             # Aebi and Cairns (2008)
9340             sub _catgamma {
9341 9     9   16 my($n,$mod) = @_;
9342              
9343             # Theorem 6, allowing us to possibly reduce n
9344 9 100       14 if ($mod < $n) {
9345 3         8 my $NP = Mdivint($n,$mod);
9346 3 50       8 if ($NP & 1) { # odd
9347 0 0       0 return $mod*$NP == $n ? _catgamma($NP,$mod) : 0;
9348             } else {
9349 3         16 return Mmulmod(_catgamma($NP+1,$mod),_catgamma($n-$mod*$NP,$mod),$mod);
9350             }
9351             }
9352             # Section 5 rephrases Theorem 2 into the middle binomial.
9353 6         16 my $N = Msub1int($n);
9354 6         30 my $m = Mrshiftint($N);
9355 6         16 my $r = Math::Prime::Util::binomialmod($N, $m, $mod);
9356 6 100       65 return ($m & 1) ? $mod-$r : $r;
9357             }
9358             sub _catvtest {
9359 4     4   6 my($n,$p) = @_;
9360 4 50       13 while ($n = int($n/$p)) { return 1 if $n % 2; }
  11         30  
9361 4         11 0;
9362             }
9363             sub is_catalan_pseudoprime {
9364 3     3 0 6 my($n) = @_;
9365 3 50       7 return 0+($n >= 2) if $n < 4;
9366 3 50       7 return 0 unless $n & 1;
9367              
9368             {
9369 3         4 my @f = Mtrial_factor($n, 10000);
  3         14  
9370 3 50 66     18 if (@f == 2 && is_prime($f[1]) && $f[0] != $f[1]) {
      66        
9371 1         3 my($p,$q) = ($f[0],$f[1]); # two primes, q > p
9372 1 50       4 return 0 if 2*$p+1 >= $q; # by Theorem 6(a)
9373             # Proposition 3 (semiprimes)
9374 1 50 33     3 return 0 unless _catgamma($q,$p) == 1 && _catgamma($p,$q) == 1;
9375             }
9376 2 50       9 if (is_prime($f[-1])) { # fully factored
9377 2         12 for my $F (vecuniq(@f)) {
9378 4 50       14 return 0 if _catvtest($n-1,$F);
9379             }
9380             }
9381             }
9382 2 50       8 return _catgamma($n,$n) == 1 ? 1 : 0;
9383             }
9384              
9385             sub is_frobenius_pseudoprime {
9386 1     1 0 3 my($n, $P, $Q) = @_;
9387 1 50 33     4 ($P,$Q) = (0,0) unless defined $P && defined $Q;
9388 1 50       3 return 0+($n >= 2) if $n < 4;
9389              
9390 1         7 $n = tobigint($n);
9391 1 50       8 return 0 if Mis_even($n);
9392              
9393 1         4 my($k, $Vcomp, $D, $Du) = (0, 4);
9394 1 50 33     8 if ($P == 0 && $Q == 0) {
9395 1         3 ($P,$Q) = (-1,2);
9396 1         3 while ($k != -1) {
9397 1         3 $P += 2;
9398 1 50       4 $P = 5 if $P == 3; # Skip 3
9399 1         3 $D = $P*$P-4*$Q;
9400 1 50       5 $Du = ($D >= 0) ? $D : -$D;
9401 1 50 33     20 last if $P >= $n || $Du >= $n; # TODO: remove?
9402 1         200 $k = Mkronecker($D, $n);
9403 1 50       6 return 0 if $k == 0;
9404 1 50 33     8 return 0 if $P == 10001 && _is_perfect_square($n);
9405             }
9406             } else {
9407 0         0 $D = $P*$P-4*$Q;
9408 0 0       0 $Du = ($D >= 0) ? $D : -$D;
9409 0 0       0 croak "Frobenius invalid P,Q: ($P,$Q)" if _is_perfect_square($Du);
9410             }
9411 1 0 33     5 return (Mis_prime($n) ? 1 : 0) if $n <= $Du || $n <= abs($Q) || $n <= abs($P);
    50 33        
9412 1 50       404 return 0 if Mgcd(abs($P*$Q*$D), $n) > 1;
9413              
9414 1 50       4 if ($k == 0) {
9415 0         0 $k = Mkronecker($D, $n);
9416 0 0       0 return 0 if $k == 0;
9417 0         0 my $Q2 = (2*abs($Q)) % $n;
9418 0 0       0 $Vcomp = ($k == 1) ? 2 : ($Q >= 0) ? $Q2 : $n-$Q2;
    0          
9419             }
9420              
9421 1         5 my($U, $V) = lucasuvmod($P, $Q, $n-$k, $n);
9422 1 50 33     16 return 1 if $U == 0 && $V == $Vcomp;
9423 1         18 0;
9424             }
9425              
9426             # Since people have graciously donated millions of CPU years to doing these
9427             # tests, it would be rude of us not to use the results. This means we don't
9428             # actually use the pretest and Lucas-Lehmer test coded below for any reasonable
9429             # size number.
9430             # See: http://www.mersenne.org/report_milestones/
9431             my %_mersenne_primes;
9432             undef @_mersenne_primes{2,3,5,7,13,17,19,31,61,89,107,127,521,607,1279,2203,2281,3217,4253,4423,9689,9941,11213,19937,21701,23209,44497,86243,110503,132049,216091,756839,859433,1257787,1398269,2976221,3021377,6972593,13466917,20996011,24036583,25964951,30402457,32582657,37156667,42643801,43112609,57885161,74207281,77232917,82589933,136279841};
9433              
9434             sub is_mersenne_prime {
9435 3     3 0 27 my($p) = @_;
9436              
9437             # Use the known Mersenne primes
9438 3 100       57 return 1 if exists $_mersenne_primes{$p};
9439 1 50       9 return 0 if $p < 79711549; # GIMPS has tested and verified all below
9440             # Past this we do a generic Mersenne prime test
9441              
9442 0 0       0 return 1 if $p == 2;
9443 0 0       0 return 0 unless is_prob_prime($p);
9444 0 0 0     0 return 0 if $p > 3 && $p % 4 == 3 && $p < ((~0)>>1) && is_prob_prime($p*2+1);
      0        
      0        
9445 0         0 my $mp = Msub1int(Mlshiftint(1,$p));
9446              
9447             # Definitely faster than using Math::BigInt that doesn't have GMP.
9448             return (0 == (Math::Prime::Util::GMP::lucasuvmod(4, 1, $mp+1, $mp))[0])
9449 0 0       0 if $Math::Prime::Util::_GMPfunc{"lucasuvmod"};
9450              
9451 0         0 my $V = 4;
9452 0         0 for my $k (3 .. $p) {
9453 0         0 $V = Mmulsubmod($V, $V, 2, $mp);
9454             }
9455 0         0 return $V == 0;
9456             }
9457              
9458              
9459             sub _poly_new {
9460 0     0   0 my($refn, @poly) = @_;
9461 0 0       0 push @poly, 0 unless scalar @poly;
9462 0 0       0 @poly = map { tobigint("$_") } @poly if $refn;
  0         0  
9463 0         0 return \@poly;
9464             }
9465              
9466             #sub _poly_print {
9467             # my($poly) = @_;
9468             # carp "poly has null top degree" if $#$poly > 0 && !$poly->[-1];
9469             # foreach my $d (reverse 1 .. $#$poly) {
9470             # my $coef = $poly->[$d];
9471             # print "", ($coef != 1) ? $coef : "", ($d > 1) ? "x^$d" : "x", " + "
9472             # if $coef;
9473             # }
9474             # my $p0 = $poly->[0] || 0;
9475             # print "$p0\n";
9476             #}
9477              
9478             sub _poly_mod_mul {
9479 0     0   0 my($px, $py, $r, $n) = @_;
9480              
9481 0         0 my $px_degree = $#$px;
9482 0         0 my $py_degree = $#$py;
9483 0 0       0 my @res = ref($n) ? map { tobigint(0) } 0..$r-1 : map { 0 } 0..$r-1;
  0         0  
  0         0  
9484              
9485             # convolve(px, py) mod (X^r-1,n)
9486 0         0 my @indices_y = grep { $py->[$_] } (0 .. $py_degree);
  0         0  
9487 0         0 foreach my $ix (0 .. $px_degree) {
9488 0         0 my $px_at_ix = $px->[$ix];
9489 0 0       0 next unless $px_at_ix;
9490 0         0 foreach my $iy (@indices_y) {
9491 0         0 my $rindex = ($ix + $iy) % $r; # reduce mod X^r-1
9492 0         0 $res[$rindex] = ($res[$rindex] + $px_at_ix * $py->[$iy]) % $n;
9493             }
9494             }
9495             # In case we had upper terms go to zero after modulo, reduce the degree.
9496 0         0 pop @res while !$res[-1];
9497 0         0 return \@res;
9498             }
9499              
9500             sub _poly_mod_pow {
9501 0     0   0 my($pn, $power, $r, $mod) = @_;
9502 0         0 my $res = _poly_new(ref($mod), 1);
9503 0         0 my $p = $power;
9504              
9505 0         0 while ($p) {
9506 0 0       0 $res = _poly_mod_mul($res, $pn, $r, $mod) if ($p % 2) != 0;
9507 0         0 $p >>= 1;
9508 0 0       0 $pn = _poly_mod_mul($pn, $pn, $r, $mod) if $p;
9509             }
9510 0         0 return $res;
9511             }
9512              
9513             sub _test_anr {
9514 0     0   0 my($a, $n, $r) = @_;
9515 0         0 my $pp = _poly_mod_pow(_poly_new(ref($n), $a, 1), $n, $r, $n);
9516 0         0 my $nr = $n % $r;
9517 0   0     0 $pp->[$nr] = (($pp->[$nr] || 0) - 1) % $n; # subtract X^(n%r)
9518 0   0     0 $pp->[ 0] = (($pp->[ 0] || 0) - $a) % $n; # subtract a
9519 0 0       0 return 0 if scalar grep { $_ } @$pp;
  0         0  
9520 0         0 1;
9521             }
9522              
9523             sub _log_gamma {
9524 624     624   1107 my($x) = @_;
9525 624         1302 my @lanczos = (0.99999999999980993, 676.5203681218851, -1259.1392167224028,
9526             771.32342877765313, -176.61502916214059, 12.507343278686905,
9527             -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7);
9528 624         1153 my($base,$sum) = ($x+7.5, 0);
9529 624         3797 $sum += $lanczos[$_] / ($x + $_) for (8,7,6,5,4,3,2,1);
9530 624         996 $sum += $lanczos[0];
9531 624         2329 return 0.91893853320467274178 + log($sum/$x) + (($x+0.5)*log($base)-$base);
9532             }
9533             sub _log_binomial {
9534 208     208   383 my($n,$k) = @_;
9535 208 50       498 return 0 if $n < $k;
9536 208         466 return _log_gamma($n+1) - _log_gamma($k+1) - _log_gamma($n-$k+1);
9537             }
9538             sub _log_bern41_binomial {
9539 52     52   120 my($r,$d,$i,$j,$s) = @_;
9540 52         160 return _log_binomial( 2*$s, $i)
9541             + _log_binomial( $d, $i)
9542             + _log_binomial( 2*$s-$i, $j)
9543             + _log_binomial( $r-2-$d, $j);
9544             }
9545             sub _bern41_acceptable {
9546 52     52   130 my($n,$r,$s) = @_;
9547 52         192 my $scmp = int(sqrt(($r-1)/3.0) + 0.99999) * log($n);
9548 52         111 my $d = int(0.5 * ($r-1));
9549 52         97 my $i = int(0.475 * ($r-1));
9550 52         106 my $j = $i;
9551 52 50       134 $d = $r-2 if $d > $r-2;
9552 52 50       135 $i = $d if $i > $d;
9553 52 50       143 $j = $r-2-$d if $j > ($r-2-$d);
9554 52         143 return _log_bern41_binomial($r,$d,$i,$j,$s) >= $scmp;
9555             }
9556              
9557             sub is_aks_prime {
9558 10     10 0 31 my($n) = @_;
9559 10         37 validate_integer($n);
9560 10 100 100     84 return 0 if $n < 2 || Mis_power($n);
9561 7 100       40 return 1 if $n == 2;
9562              
9563 6 100       25 if ($n > 11) {
9564 5 100       40 return 0 if Mis_divisible($n,2,3,5,7,11);
9565             }
9566              
9567 5         12 my($starta, $s);
9568 5         45 my $_verbose = getconfig()->{'verbose'};
9569              
9570 5         46 my $log2n = log($n)/log(2) + 0.0001; # Error on large side.
9571 5 50       25 my $r0 = ($log2n > 32 ? 0.010 : 0.003) * $log2n * $log2n;
9572 5 50       20 my $rmult = $log2n > 32 ? 6 : 30;
9573              
9574 5 50       45 my $r = Mnext_prime($r0 < 2 ? 2 : Mtoint($r0));
9575 5   100     72 while ( !Math::Prime::Util::is_primitive_root($n,$r)
9576             || !_bern41_acceptable($n,$r,$rmult * ($r-1))) {
9577 9         32 $r = next_prime($r);
9578             }
9579              
9580             {
9581 5         11 my $bi = 1;
  5         22  
9582 5         24 my $bj = $rmult * ($r-1);
9583 5         16 while ($bi < $bj) {
9584 38         95 $s = $bi + (($bj-$bi) >> 1);
9585 38 100       79 if (!_bern41_acceptable($n, $r, $s)) { $bi = $s+1; }
  11         35  
9586 27         113 else { $bj = $s; }
9587             }
9588 5         33 $s = $bj;
9589 5 50       14 croak "AKS: internal error bad s" unless _bern41_acceptable($n, $r, $s);
9590             # S will range from 2 to s+1
9591 5         15 $starta = 2;
9592 5         11 $s = $s+1;
9593             }
9594 5         26 my $slim = $s * ($s-1);
9595 5 50       28 print "# aks trial to $slim\n" if $_verbose >= 2;
9596             {
9597 5         11 my @f = Mtrial_factor($n, $slim);
  5         20  
9598 5 100       41 return 0 if @f >= 2;
9599             }
9600 3 50       17 return 1 if Mmulint($slim,$slim) >= $n;
9601             # Check b^(n-1) = 1 mod n for b in [2..s]
9602 0         0 for my $a (2 .. $s) {
9603 0 0       0 return 0 if Mpowmod($a, $n-1, $n) != 1;
9604             }
9605              
9606 0 0       0 if ($n < (MPU_HALFWORD-1) ) {
9607 0 0       0 $n = _bigint_to_int($n) if ref($n);
9608             } else {
9609 0         0 $n = tobigint($n);
9610             }
9611              
9612 0 0       0 print "# aks r = $r s = $s\n" if $_verbose;
9613 0 0       0 local $| = 1 if $_verbose > 1;
9614 0         0 for (my $a = $starta; $a <= $s; $a++) {
9615 0 0       0 return 0 unless _test_anr($a, $n, $r);
9616 0 0       0 print "." if $_verbose > 1;
9617             }
9618 0 0       0 print "\n" if $_verbose > 1;
9619              
9620 0         0 return 1;
9621             }
9622              
9623              
9624             ################################################################################
9625              
9626             sub factor_exp {
9627 3644     3644 0 38626 my($n) = @_;
9628 3644         8621 validate_integer_nonneg($n);
9629              
9630 3644         8392 my %exponents;
9631 3644         7827 my @factors = grep { !$exponents{$_}++ } Mfactor($n);
  12087         37929  
9632 3644 100       20805 return scalar @factors unless wantarray;
9633 552         888 return (map { [$_, $exponents{$_}] } @factors);
  1430         4558  
9634             }
9635              
9636             sub _basic_factor {
9637             # MODIFIES INPUT SCALAR
9638 30 0   30   164 return ($_[0] == 1) ? () : ($_[0]) if $_[0] < 4;
    50          
9639              
9640 30         3809 my @factors;
9641 30 100       151 if (!ref($_[0])) {
9642 14         58 while ( !($_[0] % 2) ) { push @factors, 2; $_[0] = int($_[0] / 2); }
  0         0  
  0         0  
9643 14         52 while ( !($_[0] % 3) ) { push @factors, 3; $_[0] = int($_[0] / 3); }
  0         0  
  0         0  
9644 14         76 while ( !($_[0] % 5) ) { push @factors, 5; $_[0] = int($_[0] / 5); }
  0         0  
  0         0  
9645             } else {
9646 16 50       122 if (Mgcd($_[0], 30) != 1) {
9647 0         0 while ($_[0] % 2 == 0) { push @factors, 2; $_[0] >>= 1; }
  0         0  
  0         0  
9648 0         0 while ($_[0] % 3 == 0) { push @factors, 3; $_[0] = Mdivint($_[0],3); }
  0         0  
  0         0  
9649 0         0 while ($_[0] % 5 == 0) { push @factors, 5; $_[0] = Mdivint($_[0],5); }
  0         0  
  0         0  
9650             }
9651             }
9652              
9653 30 50 33     225 if ($_[0] > 1 && _is_prime7($_[0])) {
9654 0         0 push @factors, $_[0];
9655 0         0 $_[0] = 1;
9656             }
9657 30         154 @factors;
9658             }
9659              
9660             # Assume $f divides $n. Remove all occurances, add them to @$flist. Return $n.
9661             sub _remove_factor {
9662 417     417   1239 my($n, $f, $flist) = @_;
9663              
9664 417         717 while (1) {
9665 1077         275703 push @$flist, $f;
9666 1077         5077 $n = Mdivint($n,$f);
9667 1077 100       10607 last unless Mis_divisible($n,$f);
9668             }
9669              
9670             # Better for many repeated factors
9671             #if ($n % ($f*$f)) {
9672             # push @$flist, $f;
9673             # $n = Mdivint($n,$f);
9674             #} else {
9675             # my($k,$fk,$fk1) = (2,$f*$f,Mmulint($f*$f,$f));
9676             # while (!($n % $fk1)) { $k++; ($fk,$fk1)=($fk1,Mmulint($fk1,$f)); }
9677             # $n = Mdivint($n,$fk);
9678             # push @$flist, map { $f } 1..$k;
9679             #}
9680              
9681 417         1088 $n = addint($n,0) if OLD_PERL_VERSION;
9682 417         1330 $n;
9683             }
9684             sub trial_factor {
9685 4407     4407 0 10301 my($n, $limit) = @_;
9686 4407         10203 validate_integer_nonneg($n);
9687 4407 50       16880 validate_integer_nonneg($limit) if defined $limit;
9688              
9689 4407 50       8114 return ($n==1) ? () : ($n) if $n < 4;
    100          
9690 4406 50 33     34643 return ($n) if defined $limit && $limit < 2;
9691              
9692 4406 50 33     10823 if ($Math::Prime::Util::_GMPfunc{"trial_factor"} && $Math::Prime::Util::GMP::VERSION >= 0.22) {
9693             # Not the same API -- other than 2/3/5, returns a single factor
9694 0         0 my @F = ();
9695 0         0 while (1) {
9696 0 0       0 my @f = defined $limit ? Math::Prime::Util::GMP::trial_factor($n,$limit)
9697             : Math::Prime::Util::GMP::trial_factor($n);
9698             # Pull off the factors of 2,3,5 that are done fully.
9699 0   0     0 push @F,shift(@f) while @f && $f[0] <= 5;
9700 0 0       0 push @F,$f[0] if @f == 1;
9701 0 0       0 last if @f <= 1;
9702             # Store the small factor we found, then keep factoring the remainder.
9703 0         0 $n = pop(@f);
9704 0         0 push @F,@f;
9705             }
9706 0 0       0 return ref($_[0]) ? maybetobigintall(@F) : @F;
9707             }
9708              
9709 4406         7054 my @factors;
9710             # Don't use _basic_factor here -- they want a trial forced.
9711              
9712             # For 32-bit n, we can simplify things a lot.
9713 4406 100       9679 if ($n <= 4294967295) {
9714 4308         8888 my $sqrtn = int(sqrt($n));
9715 4308 100 66     15227 $limit = $sqrtn if !defined $limit || $limit > $sqrtn;
9716              
9717 4308 100 66     13941 if ($limit >= 2 && ($n % 2 == 0)) {
9718 2095         3207 do { push @factors, 2; $n >>= 1; } while ($n % 2) == 0;
  4120         6874  
  4120         8945  
9719 2095         3597 $sqrtn = int(sqrt($n));
9720 2095 100       4640 $limit = $sqrtn if $sqrtn < $limit;
9721             }
9722 4308         9947 for my $p (3,5,7,11,13,17,19,23,29,31,37,41,43,47,53) {
9723 27028 100 100     76020 last if $n == 1 || $p > $limit;
9724 23058 100       44311 if ($n % $p == 0) {
9725 3445         6390 do { push @factors, $p; $n = int($n/$p); } while ($n % $p) == 0;
  4464         7666  
  4464         10194  
9726 3445         5314 $sqrtn = int(sqrt($n));
9727 3445 100       8071 $limit = $sqrtn if $sqrtn < $limit;
9728             }
9729             }
9730 4308 100       9127 return @factors if $n == 1;
9731 3956 100       15890 return (@factors,$n) if $limit < 59;
9732              
9733 251 50       760 _expand_prime_cache($limit+72) if $limit > $_primes_small[-1];;
9734              
9735 251         743 for my $i (17 .. $#_primes_small) {
9736 14000         20801 my $p = $_primes_small[$i];
9737 14000 100       26867 last if $p > $limit;
9738 13753 100       28008 if (($n % $p) == 0) {
9739 61         137 do { push @factors, $p; $n = int($n/$p); } while ($n % $p) == 0;
  65         148  
  65         227  
9740 61 100       191 last if $n == 1;
9741 57         123 $sqrtn = int(sqrt($n));
9742 57 50       171 $limit = $sqrtn if $sqrtn < $limit;
9743             }
9744             }
9745 251 100       782 push @factors, $n if $n > 1;
9746 251         946 return @factors;
9747             }
9748              
9749             # STEP 1 Pull out factors of 2
9750 98 100       21517 if (!ref($n)) {
    50          
    0          
9751 5         39 while ($n % 2 == 0) {
9752 2         5 push @factors, 2;
9753 2         8 $n >>= 1;
9754             }
9755             } elsif (ref($n) eq 'Math::BigInt') {
9756 93         255 my $k = 0;
9757 93 100       432 if ($n->is_even) {
9758 45         1086 my $s = substr($n->as_bin(),2);
9759 45         27272 $k = length($s) - rindex($s,'1') - 1;
9760             }
9761 93 100       1291 if ($k > 0) { push @factors, (2) x $k; $n = Mrshiftint($n,$k); }
  45         192  
  45         376  
9762             } elsif ($n % 2 == 0) {
9763 0         0 my $k = Mvaluation($n,2);
9764 0 0       0 if ($k > 0) { push @factors, (2) x $k; $n = Mrshiftint($n,$k); }
  0         0  
  0         0  
9765             }
9766              
9767             # STEP 2 Defined and accurate $limit, add more small primes
9768 98 50 33     10061 $limit = Msqrtint($n) if !defined $limit || $limit*$limit > $n;
9769              
9770             # Add more primes if we might use them. Maybe wait until needed?
9771 98 100 100     13264 _expand_prime_cache(100_003)
9772             if $_primes_small[-1] < 100_000 && $limit > $_primes_small[-1];
9773              
9774 98         317 my $I = 2; # small prime index, start at p=3
9775              
9776             # STEP 3: Math::BigInt using small primes list until native or no more
9777 98 100       416 if (ref($n) eq 'Math::BigInt') {
9778             # n is a odd positive Math::BigInt with at least 32 bits.
9779             # Batch primes and use gcd to check. If using Math::BigInt, 2-5x faster.
9780 88   100     856 while ($I+3 <= $#_primes_small && $_primes_small[$I+3] <= $limit && $I <= 1951956) {
      66        
9781 4697         125454 my($f1,$f2,$f3,$f4) = @_primes_small[$I .. $I+3];
9782 4697 100       23224 my $g = $n->bgcd($f1<=5581 ? $f1*$f2*$f3*$f4 : Mmulint($f1*$f4,$f2*$f3));
9783 4697         8104319 $I += 4;
9784 4697 100       15250 next if $g->is_one;
9785 208         4561 my $G = _bigint_to_int($g); # Native int (or larger)
9786 208 50       8915 $G = $g if $G >= INTMAX; # Must use original if multiples found.
9787 208 100       1086 $n = _remove_factor($n, $f1, \@factors) unless $G % $f1;
9788 208 100       1266 $n = _remove_factor($n, $f2, \@factors) unless $G % $f2;
9789 208 100       1141 $n = _remove_factor($n, $f3, \@factors) unless $G % $f3;
9790 208 100       991 $n = _remove_factor($n, $f4, \@factors) unless $G % $f4;
9791 208 100       913 if ($limit*$limit >= $n) {
9792 7         59 my $sqrtn = Msqrtint($n);
9793 7 50       25 $limit = $sqrtn if $limit > $sqrtn;
9794             }
9795 208 100       24044 last if !ref($n);
9796             }
9797             # n is either a bigint and > INTMAX, or a native type <= INTMAX;
9798 88 100       832 return @factors if $n == 1;
9799 81 50       5254 my $f = $I > $#_primes_small ? $_primes_small[-1]+2 : $_primes_small[$I];
9800 81 100       468 return (@factors,$n) if $f > $limit;
9801             }
9802              
9803             # STEP 4: any bigint, small primes list until native or no more
9804 72 100       347 if (ref($n)) {
9805 2         8 while ($I <= $#_primes_small) {
9806 8         2069 my $f = $_primes_small[$I];
9807 8 100       21 last if $f > $limit;
9808 6         10 $I++;
9809 6 50       18 next if $n % $f;
9810 0         0 $n = _remove_factor($n, $f, \@factors);
9811 0 0       0 if ($limit*$limit >= $n) {
9812 0         0 my $sqrtn = Msqrtint($n);
9813 0 0       0 $limit = $sqrtn if $limit > $sqrtn;
9814             }
9815 0 0       0 last if !ref($n);
9816             }
9817 2 50       7 return @factors if $n == 1;
9818 2 50       379 my $f = $I > $#_primes_small ? $_primes_small[-1]+2 : $_primes_small[$I];
9819 2 50       19 return (@factors,$n) if $f > $limit;
9820             }
9821              
9822             # STEP 5: Still a bigint. Wheel (mod 2310) starting from last small prime.
9823 70 50       265 if (ref($n)) {
9824 0         0 my $f = $_primes_small[-1];
9825 0         0 my($s,$w) = ($_primes_small[-1], 2*3*5*7*11);
9826 0     0   0 my @wheel = Mvecslide(sub{$b-$a}, grep { Mgcd($_,$w)==1 } $s+0..$s+$w);
  0         0  
  0         0  
9827 0         0 SEARCH: while ($f <= $limit) {
9828 0         0 for my $inc (@wheel) {
9829 0         0 $f += $inc;
9830 0 0 0     0 if ($f <= $limit && !($n % $f)) {
9831 0         0 $n = _remove_factor($n, $f, \@factors);
9832 0 0       0 last SEARCH if $n == 1;
9833 0 0       0 if ($limit*$limit >= $n) {
9834 0         0 my $sqrtn = Msqrtint($n);
9835 0 0       0 $limit = $sqrtn if $limit > $sqrtn;
9836             }
9837             }
9838             }
9839             }
9840 0 0       0 push @factors, $n if $n > 1;
9841 0         0 return @factors;
9842             }
9843              
9844             # STEP 6: native small primes list
9845 70         318 for my $i ($I .. $#_primes_small) {
9846 32616         47253 my $p = $_primes_small[$i];
9847 32616 100       62379 last if $p > $limit;
9848 32548 100       64352 if (($n % $p) == 0) {
9849 186         294 do { push @factors, $p; $n = int($n/$p); } while ($n % $p) == 0;
  196         404  
  196         643  
9850 186 100       496 last if $n == 1;
9851 184         403 my $newlim = int( sqrt($n) + 0.001);
9852 184 100       580 $limit = $newlim if $newlim < $limit;
9853             }
9854             }
9855 70 100       353 return @factors if $n == 1;
9856              
9857             # STEP 7: native wheel (mod 30)
9858 68 50       284 if ($_primes_small[-1] < $limit) {
9859 0 0       0 my $inc = (($_primes_small[-1] % 6) == 1) ? 4 : 2;
9860 0         0 my $p = $_primes_small[-1] + $inc;
9861 0         0 while ($p <= $limit) {
9862 0 0       0 if (($n % $p) == 0) {
9863 0         0 do { push @factors, $p; $n = int($n/$p); } while ($n % $p) == 0;
  0         0  
  0         0  
9864 0 0       0 last if $n == 1;
9865 0         0 my $newlim = int( sqrt($n) + 0.001);
9866 0 0       0 $limit = $newlim if $newlim < $limit;
9867             }
9868 0         0 $p += ($inc ^= 6);
9869             }
9870             }
9871 68 50       318 push @factors, $n if $n > 1;
9872 68         607 @factors;
9873             }
9874              
9875             my $_holf_r;
9876             my @_fsublist = (
9877             [ "power", sub { _power_factor (shift) } ],
9878              
9879             [ "pbrent 8k", sub { pbrent_factor (shift, 8*1024, 1, 1) } ],
9880             [ "p-1 16k", sub { pminus1_factor(shift, 16_384, 16_384, 1); } ],
9881             [ "ECM 500", sub { ecm_factor (shift, 500, 10_000, 10) } ],
9882             [ "ECM 4k", sub { ecm_factor (shift, 4_000, 20_000, 20) } ],
9883              
9884             [ "pbrent 512k",sub { pbrent_factor (shift, 512*1024, 7, 1) } ],
9885             [ "p-1 4M", sub { pminus1_factor(shift, 4_000_000, undef, 1); } ],
9886             [ "ECM 10k", sub { ecm_factor (shift, 10_000, 50_000, 10) } ],
9887             [ "pbrent 512k",sub { pbrent_factor (shift, 512*1024, 11, 1) } ],
9888             [ "HOLF 256k", sub { holf_factor (shift, 256*1024, $_holf_r); $_holf_r += 256*1024; } ],
9889             [ "p-1 20M", sub { pminus1_factor(shift,20_000_000); } ],
9890             [ "ECM 100k", sub { ecm_factor (shift, 100_000, 800_000, 10) } ],
9891             [ "HOLF 512k", sub { holf_factor (shift, 512*1024, $_holf_r); $_holf_r += 512*1024; } ],
9892             [ "pbrent 2M", sub { pbrent_factor (shift, 2048*1024, 13, 1) } ],
9893             [ "HOLF 2M", sub { holf_factor (shift, 2048*1024, $_holf_r); $_holf_r += 2048*1024; } ],
9894             [ "ECM 1M", sub { ecm_factor (shift, 1_000_000, 1_000_000, 10) } ],
9895             [ "p-1 100M", sub { pminus1_factor(shift, 100_000_000, 500_000_000); } ],
9896             );
9897              
9898             sub factor {
9899 4494     4494 0 12663 my($n) = @_;
9900 4494         11546 validate_integer_nonneg($n);
9901              
9902 4494         11211 my @factors;
9903 4494 100       9495 if ($n < 4) {
9904 118 100       373 @factors = ($n == 1) ? () : ($n);
9905 118         297 return @factors;
9906             }
9907              
9908 4376 50       28652 if ($Math::Prime::Util::_GMPfunc{"factor"}) {
9909 0         0 my @factors = Math::Prime::Util::GMP::factor($n);
9910 0 0       0 return ref($_[0]) ? maybetobigintall(@factors) : @factors;
9911             }
9912              
9913 4376 100       9767 $n = Maddint($n,0) if ref($n); # Ensure we have a copy
9914 4376         26162 my $lim = 4999; # How much trial factoring to do
9915              
9916             # For native integers, we could save a little time by doing hardcoded trials
9917             # by 2-29 here. Skipping it.
9918              
9919 4376         11460 push @factors, Mtrial_factor($n, $lim);
9920 4376 100       16211 return @factors if $factors[-1] < $lim*$lim;
9921 63         3762 $n = pop(@factors);
9922              
9923 63         435 my @nstack = ($n);
9924 63         222 while (@nstack) {
9925 97         210 $n = pop @nstack;
9926             # Don't use bignum on $n if it has gotten small enough.
9927 97 50 66     537 $n = _bigint_to_int($n) if ref($n) && $n <= INTMAX;
9928             #print "Looking at $n with stack ", join(",",@nstack), "\n";
9929 97   100     5888 while ( ($n >= ($lim*$lim)) && !_is_prime7($n) ) {
9930 34         96 my @ftry;
9931 34         89 $_holf_r = 1;
9932 34         116 foreach my $sub (@_fsublist) {
9933 102 100       398 last if scalar @ftry >= 2;
9934 68 50       393 print " starting $sub->[0]\n" if getconfig()->{'verbose'} > 1;
9935 68         481 @ftry = $sub->[1]->($n);
9936             }
9937 34 50       174 if (scalar @ftry > 1) {
9938             #print " split into ", join(",",@ftry), "\n";
9939 34         86 $n = shift @ftry;
9940 34 50 33     199 $n = _bigint_to_int($n) if ref($n) && $n <= INTMAX;
9941 34         211 push @nstack, @ftry;
9942             } else {
9943             #warn "trial factor $n\n";
9944 0         0 push @factors, Mtrial_factor($n);
9945             #print " trial into ", join(",",@factors), "\n";
9946 0         0 $n = 1;
9947 0         0 last;
9948             }
9949             }
9950 97 50       1404 push @factors, $n if $n != 1;
9951             }
9952 63         2288 Mvecsort(@factors);
9953             }
9954              
9955             sub _found_factor {
9956 61     61   357 my($f, $n, $what, @factors) = @_;
9957 61 50 33     492 if ($f == 1 || $f == $n) {
9958 0         0 push @factors, $n;
9959             } else {
9960 61         6794 my $f2 = Mdivint($n,$f);
9961 61 50       1475 croak "internal error in $what" unless Mmulint($f,$f2) == $n;
9962 61 100       9574 ($f,$f2) = ($f2,$f) if $f > $f2;
9963 61         984 push @factors, $f, $f2;
9964             # MPU::GMP prints this type of message if verbose, so do the same.
9965 61 50       370 print "$what found factor $f\n" if getconfig()->{'verbose'} > 0;
9966             }
9967 61         1420 @factors;
9968             }
9969              
9970             ################################################################################
9971              
9972             # TODO:
9973 0     0 0 0 sub squfof_factor { Mtrial_factor(@_) }
9974 0     0 0 0 sub lehman_factor { Mtrial_factor(@_) }
9975 0     0 0 0 sub pplus1_factor { pminus1_factor(@_) }
9976              
9977             sub _power_factor {
9978 34     34   89 my $r;
9979 34         395 my $k = Mis_power($_[0],0,\$r);
9980 34 50       270 return ($_[0]) unless $k > 1;
9981 0 0       0 print "power found factor $r\n" if getconfig()->{'verbose'} > 0;
9982 0         0 map { $r } 1..$k;
  0         0  
9983             }
9984              
9985             sub prho_factor {
9986 5     5 0 5300 my($n, $rounds, $pa, $skipbasic) = @_;
9987 5         28 validate_integer_nonneg($n);
9988 5 50       20 if (defined $rounds) { validate_integer_nonneg($rounds); }
  0         0  
9989 5         13 else { $rounds = 4*1024*1024; }
9990 5 50       15 if (defined $pa) { validate_integer_nonneg($pa); }
  0         0  
9991 5         11 else { $pa = 3; }
9992              
9993 5         26 my @factors;
9994 5 50       18 if (!$skipbasic) {
9995 5         24 @factors = _basic_factor($n);
9996 5 50       21 return @factors if $n < 4;
9997             }
9998              
9999 5         233 my($U,$V) = (7,7);
10000              
10001 5 100 100     29 if (ref($n) || $n >= MPU_HALFWORD) {
10002              
10003 3         9 my $inner = 32;
10004 3         16 $rounds = int( ($rounds + $inner-1) / $inner );
10005 3         31 while ($rounds-- > 0) {
10006 3         11 my($m, $oldU, $oldV, $f) = (1, $U, $V);
10007 3         21 for my $i (1 .. $inner) {
10008 96         8980 $U = Mmuladdmod($U, $U, $pa, $n);
10009 96         7597 $V = Mmuladdmod($V, $V, $pa, $n);
10010 96         9580 $V = Mmuladdmod($V, $V, $pa, $n);
10011 96 100       7771 $f = ($U > $V) ? Msubint($U,$V) : Msubint($V,$U);
10012 96         7731 $m = Mmulmod($m,$f,$n);
10013             }
10014 3         246 $f = Mgcd($m,$n);
10015 3 50       17 next if $f == 1;
10016 3 100       26 if ($f == $n) {
10017 1         3 ($U, $V) = ($oldU, $oldV);
10018 1         5 for my $i (1 .. $inner) {
10019 3         13 $U = Mmuladdmod($U, $U, $pa, $n);
10020 3         14 $V = Mmuladdmod($V, $V, $pa, $n);
10021 3         11 $V = Mmuladdmod($V, $V, $pa, $n);
10022 3 50       17 $f = ($U > $V) ? Msubint($U,$V) : Msubint($V,$U);
10023 3         10 $f = Mgcd($f, $n);
10024 3 100       12 last if $f != 1;
10025             }
10026 1 50 33     11 last if $f == 1 || $f == $n;
10027             }
10028 3         237 return _found_factor($f, $n, "prho-bigint", @factors);
10029             }
10030              
10031             } else {
10032              
10033 2         6 my $inner = 32;
10034 2         9 $rounds = int( ($rounds + $inner-1) / $inner );
10035 2         13 while ($rounds-- > 0) {
10036 2         17 my($m, $oldU, $oldV, $f) = (1, $U, $V);
10037 2         9 for my $i (1 .. $inner) {
10038 64         147 $U = ($U * $U + $pa) % $n;
10039 64         105 $V = ($V * $V + $pa) % $n;
10040 64         97 $V = ($V * $V + $pa) % $n;
10041 64 100       121 $f = ($U > $V) ? $U-$V : $V-$U;
10042 64         101 $m = ($m * $f) % $n;
10043             }
10044 2         12 $f = _gcd_ui( $m, $n );
10045 2 50       10 next if $f == 1;
10046 2 100       8 if ($f == $n) {
10047 1         4 ($U, $V) = ($oldU, $oldV);
10048 1         4 for my $i (1 .. $inner) {
10049 2         20 $U = ($U * $U + $pa) % $n;
10050 2         5 $V = ($V * $V + $pa) % $n;
10051 2         4 $V = ($V * $V + $pa) % $n;
10052 2 100       18 $f = ($U > $V) ? $U-$V : $V-$U;
10053 2         6 $f = _gcd_ui( $f, $n);
10054 2 100       9 last if $f != 1;
10055             }
10056 1 50 33     10 last if $f == 1 || $f == $n;
10057             }
10058 2         8 return _found_factor($f, $n, "prho-32", @factors);
10059             }
10060              
10061             }
10062 0         0 push @factors, $n;
10063 0         0 @factors;
10064             }
10065              
10066             sub pbrent_factor {
10067 40     40 0 4193 my($n, $rounds, $pa, $skipbasic) = @_;
10068 40         235 validate_integer_nonneg($n);
10069 40 100       857 if (defined $rounds) { validate_integer_nonneg($rounds); }
  35         134  
10070 5         14 else { $rounds = 4*1024*1024; }
10071 40 100       109 if (defined $pa) { validate_integer_nonneg($pa); }
  35         100  
10072 5         9 else { $pa = 3; }
10073              
10074 40         85 my @factors;
10075 40 100       133 if (!$skipbasic) {
10076 6         28 @factors = _basic_factor($n);
10077 6 50       24 return @factors if $n < 4;
10078             }
10079              
10080 40         324 my($Xi,$Xm) = (2,2);
10081              
10082 40 100 100     210 if (ref($n) || $n >= MPU_HALFWORD) {
10083              
10084             # Same code as the GMP version, but runs *much* slower. Even with
10085             # Math::BigInt::GMP it's >200x slower. With the default Calc backend
10086             # it's thousands of times slower.
10087 37         134 my($inner,$r,$saveXi,$f) = (32,1);
10088              
10089 37         149 while ($rounds > 0) {
10090 317 50       1135 my $rleft = ($r > $rounds) ? $rounds : $r;
10091 317         746 while ($rleft > 0) {
10092 896 100       2271 my $dorounds = ($rleft > $inner) ? $inner : $rleft;
10093 896         1698 my $m = 1;
10094 896         3262 $saveXi = Maddint($Xi,0);
10095 896         36614 foreach my $i (1 .. $dorounds) {
10096 23947         1317051 $Xi = Mmuladdmod($Xi, $Xi, $pa, $n);
10097 23947         1321889 if (OLD_PERL_VERSION) { $m=mulmod($m,subint($Xi,$Xm),$n); next; }
10098 23947 100       84041 $m = Mmulmod($m, $Xi > $Xm ? $Xi-$Xm : $Xm-$Xi,$n);
10099             }
10100 896         51933 $rleft -= $dorounds;
10101 896         1610 $rounds -= $dorounds;
10102 896         4437 $f = Mgcd($m,$n);
10103 896 100       4452 last unless $f == 1;
10104             }
10105 317 100       905 if ($f == 1) {
10106 280         570 $r *= 2;
10107 280         1229 $Xm = Maddint($Xi,0);
10108 280         20370 next;
10109             }
10110 37 100       159 if ($f == $n) { # back up to determine the factor
10111 1         7 $Xi = Maddint($saveXi,0);
10112 1   66     32 do {
10113 7         31 $Xi = Mmuladdmod($Xi, $Xi, $pa, $n);
10114 7 100       44 $f = Mgcd($Xi > $Xm ? $Xi-$Xm : $Xm-$Xi, $n);
10115             } while ($f == 1 && $r-- != 0);
10116 1 50 33     13 last if $f == 1 || $f == $n;
10117             }
10118 37         4092 return _found_factor($f, $n, "pbrent", @factors);
10119             }
10120              
10121             } else {
10122              
10123             # Doing the gcd batching as above works pretty well here, but it's a lot
10124             # of code for not much gain for general users.
10125 3         27 for my $i (1 .. $rounds) {
10126 416         740 $Xi = ($Xi * $Xi) % $n;
10127 416 50       699 $Xi += $pa; $Xi -= $n if $Xi >= $n;
  416         858  
10128 416 100       1031 my $f = _gcd_ui( ($Xi>$Xm) ? $Xi-$Xm : $Xm-$Xi, $n);
10129 416 100 66     1109 return _found_factor($f, $n, "pbrent-32",@factors) if $f != 1 && $f != $n;
10130 413 100       1061 $Xm = $Xi if ($i & ($i-1)) == 0; # i is a power of 2
10131             }
10132              
10133             }
10134 0         0 push @factors, $n;
10135 0         0 @factors;
10136             }
10137              
10138             sub pminus1_factor {
10139 8     8 0 4701 my($n, $B1, $B2, $skipbasic) = @_;
10140 8         76 validate_integer_nonneg($n);
10141 8 100       49 validate_integer_nonneg($B1) if defined $B1;
10142 8 100       37 validate_integer_nonneg($B2) if defined $B2;
10143              
10144 8         30 my @factors;
10145 8 50       47 if (!$skipbasic) {
10146 8         48 @factors = _basic_factor($n);
10147 8 50       57 return @factors if $n < 4;
10148             }
10149              
10150 8         1518 $n = tobigint($n) if OLD_PERL_VERSION && !ref($n) && $n > INTMAX;
10151              
10152 8 100       53 if (!ref($n)) {
10153             # Stage 1 only
10154 1         7 my $sqrtn = Msqrtint($n);
10155 1 50 33     34 $B1 = $sqrtn if !defined $B1 || $B1 > $sqrtn;
10156 1         5 my $sqrtb1 = int(sqrt($B1));
10157 1         5 my($pc_beg, $pc_end) = (2, 6_000-1);
10158 1         4 my $pa = 2;
10159              
10160 1         15 while (1) {
10161 1 50       14 $pc_end = $B1 if $pc_end > $B1;
10162 1         2 foreach my $q (@{Mprimes($pc_beg, $pc_end)}) {
  1         24  
10163 2         6 my $k = $q;
10164 2 50       19 if ($q <= $sqrtb1) {
10165 2         10 my $kmin = int($B1 / $q);
10166 2         9 while ($k <= $kmin) { $k *= $q; }
  4         10  
10167             }
10168 2         12 $pa = Mpowmod($pa, $k, $n);
10169 2 50       115 if ($pa == 0) { push @factors, $n; return @factors; }
  0         0  
  0         0  
10170 2         29 my $f = Mgcd($pa-1, $n);
10171 2 100       29 return _found_factor($f, $n, "pminus1-64", @factors) if $f != 1;
10172             }
10173 0 0       0 last if $pc_end >= $B1;
10174 0         0 ($pc_beg, $pc_end) = ($pc_end+1, $pc_end+18000);
10175             }
10176 0         0 push @factors, $n;
10177 0         0 return @factors;
10178             }
10179              
10180 7 100       33 if (!defined $B1) {
10181 2         22 for my $mul (1, 100, 1000, 10_000, 100_000, 1_000_000) {
10182 2         6 $B1 = 1000 * $mul;
10183 2         5 $B2 = 1*$B1;
10184             #warn "Trying p-1 with $B1 / $B2\n";
10185 2         24 my @nf = pminus1_factor($n, $B1, $B2);
10186 2 50       31 if (scalar @nf > 1) {
10187 2         7 push @factors, @nf;
10188 2         35 return @factors;
10189             }
10190             }
10191 0         0 push @factors, $n;
10192 0         0 return @factors;
10193             }
10194 5 50       23 $B2 = 1*$B1 unless defined $B2;
10195              
10196 5 50 33     71 $n = tobigint($n) if !ref($n) || (defined $_BIGINT && $_BIGINT ne ref($n));
      33        
10197             # bigints: n, pa, t, savea, [stage2] b, bm
10198              
10199 5         19 my ($j, $q, $saveq) = (32, 2, 2);
10200 5         41 my $pa = tobigint(2);
10201 5         16 my $t = tobigint(1);
10202 5         30 my $savea = $pa+0;
10203 5         1631 my $f = 1;
10204 5         18 my($pc_beg, $pc_end) = (2, 2+100_000);
10205              
10206 5         10 while (1) {
10207 5 50       37 $pc_end = $B1 if $pc_end > $B1;
10208 5         13 my @bprimes = @{ Mprimes($pc_beg, $pc_end) };
  5         36  
10209 5         86 foreach my $q (@bprimes) {
10210 3220         38646 my($k, $kmin) = ($q, int($B1 / $q));
10211 3220         10028 while ($k <= $kmin) { $k *= $q; }
  156         311  
10212 3220         10092 $t *= $k; # accumulate powers for a
10213 3220 100       1093200 if ( ($j++ % 64) == 0) {
10214 51 50 33     276 next if $pc_beg > 2 && ($j-1) % 256;
10215 51         347 $pa = _bi_powmod($pa, $t, $n);
10216 51         710 $t = tobigint(1);
10217 51 50       629 if ($pa == 0) { push @factors, $n; return @factors; }
  0         0  
  0         0  
10218 51         15118 $f = Mgcd($pa-1, $n);
10219 51 100       379 last if $f == $n;
10220 50 100       11486 return _found_factor($f, $n, "pminus1-bigint $B1", @factors) unless $f == 1;
10221 49         190 $saveq = $q;
10222 49         270 $savea = $pa+0;
10223             }
10224             }
10225 4         85 $q = $bprimes[-1];
10226 4 50 66     282 last if $f != 1 || $pc_end >= $B1;
10227 0         0 ($pc_beg, $pc_end) = (Madd1int($pc_end), Maddint($pc_end,500_000));
10228             }
10229 4         461 $pa = _bi_powmod($pa, $t, $n);
10230 4 50       37 if ($pa == 0) { push @factors, $n; return @factors; }
  0         0  
  0         0  
10231 4         1047 $f = Mgcd($pa-1, $n);
10232 4 100       29 if ($f == $n) {
10233 1         47 $q = $saveq;
10234 1         7 $pa = $savea+0;
10235 1         386 while ($q <= $B1) {
10236 4         24 my ($k, $kmin) = ($q, int($B1 / $q));
10237 4         16 while ($k <= $kmin) { $k *= $q; }
  18         33  
10238 4         27 $pa = _bi_powmod($pa, $k, $n);
10239 4         41 $f = Mgcd($pa-1, $n);
10240 4 50       28 if ($f == $n) { push @factors, $n; return @factors; }
  0         0  
  0         0  
10241 4 100       780 last if $f != 1;
10242 3         44 $q = Mnext_prime($q);
10243             }
10244             }
10245             # STAGE 2
10246 4 100 66     650 if ($f == 1 && $B2 > $B1) {
10247 3         16 my $bm = $pa + 0;
10248 3         932 my $b = tobigint(1);
10249 3         20 my @precomp_bm;
10250 3         16 $precomp_bm[0] = ($bm * $bm) % $n;
10251 3         2074 $precomp_bm[$_] = ($precomp_bm[$_-1] * $bm * $bm) % $n for 1..19;
10252 3         49787 $pa = _bi_powmod($pa, $q, $n);
10253              
10254 3         19 my $j = 1;
10255 3         9 $pc_beg = $q+1;
10256 3         23 $pc_end = Maddint($pc_beg, 100_000);
10257 3         16 while (1) {
10258 3 50       17 $pc_end = $B2 if $pc_end > $B2;
10259 3         10 my @bprimes = @{ Mprimes($pc_beg, $pc_end) };
  3         63  
10260 3         63 foreach my $i (0 .. $#bprimes) {
10261 1024         3095 my $diff = $bprimes[$i] - $q;
10262 1024         2030 $q = $bprimes[$i];
10263 1024         2076 my $qdiff = ($diff >> 1) - 1;
10264 1024 100       2907 $precomp_bm[$qdiff] = _bi_powmod($bm, $diff, $n)
10265             unless defined $precomp_bm[$qdiff];
10266 1024         3610 $pa = ($pa * $precomp_bm[$qdiff]) % $n;
10267 1024 50       641206 if ($pa == 0) { push @factors, $n; return @factors; }
  0         0  
  0         0  
10268 1024         256877 $b *= ($pa-1);
10269 1024 100       2716385 if (($j++ % 128) == 0) {
10270 8         72 $b %= $n;
10271 8         71625 $f = Mgcd($b, $n);
10272 8 100       50 last if $f != 1;
10273             }
10274             }
10275 3 50 33     91 last if $f != 1 || $pc_end >= $B2;
10276 0         0 ($pc_beg, $pc_end) = (Madd1int($pc_end), Maddint($pc_end,500_000));
10277             }
10278 3         13 $f = Mgcd($b, $n);
10279             }
10280 4         97 return _found_factor($f, $n, "pminus1-bigint $B1/$B2", @factors);
10281             }
10282              
10283             sub cheb_factor {
10284 1     1 0 958 my($n, $B1, $initx, $skipbasic) = @_;
10285 1         6 validate_integer_nonneg($n);
10286 1 50       4 validate_integer_nonneg($B1) if defined $B1;
10287 1 50       21 validate_integer_nonneg($initx) if defined $initx;
10288              
10289 1         4 my @factors;
10290 1 50       5 if (!$skipbasic) {
10291 1         5 @factors = _basic_factor($n);
10292 1 50       5 return @factors if $n < 4;
10293             }
10294              
10295 1 50 33     7 my $x = (defined $initx && $initx > 0) ? $initx : 72; # Arbitrary
10296 1 50 33     23 my $B = (defined $B1 && $B1 > 0) ? $B1 : Mmulint(Mpowint(Mlogint($n,2),2),8);
10297 1 50       21 $B = Msqrtint($n) if $B > Msqrtint($n);
10298 1         5 my $sqrtB = Msqrtint($B);
10299 1         8 my $inv = Minvmod(2,$n);
10300 1         4 my $f = 1;
10301              
10302 1         3 my @bprimes = @{ Mprimes(2, $B) };
  1         7  
10303 1         21 foreach my $p (@bprimes) {
10304 2         16 my $xx = Maddmod($x,$x,$n);
10305 2 50       10 if ($p <= $sqrtB) {
10306 2         21 my $plgp = Mpowint($p, Mlogint($B, $p));
10307 2         41 $x = Mmulmod(Math::Prime::Util::lucasvmod($xx, 1, $plgp, $n), $inv, $n);
10308             } else {
10309 0         0 $x = Mmulmod(Math::Prime::Util::lucasvmod($xx, 1, $p, $n), $inv, $n);
10310             }
10311 2         15 $f = Mgcd($x-1, $n);
10312 2 100       11 last if $f != 1;
10313             }
10314 1         8 return _found_factor($f, $n, "cheb", @factors);
10315             }
10316              
10317             sub holf_factor {
10318 3     3 0 1120 my($n, $rounds, $startrounds) = @_;
10319 3         29 validate_integer_nonneg($n);
10320 3 50       31 if (defined $rounds) { validate_integer_nonneg($rounds); }
  0         0  
10321 3         9 else { $rounds = 64*1024*1024; }
10322 3 50 33     22 $startrounds = 1 if (!defined $startrounds) || ($startrounds < 1);
10323              
10324 3         19 my @factors = _basic_factor($n);
10325 3 50       21 return @factors if $n < 4;
10326              
10327 3 100       1673 if (ref($n)) {
10328 2         11 for my $i ($startrounds .. $rounds) {
10329 2         16 my $ni = Mmulint($n,$i);
10330 2         600 my $s = Msqrtint($ni);
10331 2 50       28 if (Mmulint($s,$s) == $ni) {
10332             # s^2 = n*i, so m = s^2 mod n = 0. Hence f = GCD(n, s) = GCD(n, n*i)
10333 0         0 my $f = Mgcd($ni, $n);
10334 0         0 return _found_factor($f, $n, "HOLF", @factors);
10335             }
10336 2         701 $s = Madd1int($s);
10337 2         11 my $m = Msubint(Mmulint($s,$s),$ni);
10338 2 50       144 if (Mis_power($m, 2, \my $f)) {
10339 2 50       21 $f = Mgcd($n, $s > $f ? $s-$f : $f-$s);
10340 2         17 return _found_factor($f, $n, "HOLF ($i rounds)", @factors);
10341             }
10342             }
10343             } else {
10344 1         8 for my $i ($startrounds .. $rounds) {
10345 3         10 my $s = int(sqrt($n * $i));
10346 3 50       13 $s++ if ($s * $s) != ($n * $i);
10347 3 50       10 my $m = ($s < MPU_HALFWORD) ? ($s*$s) % $n : _mulmod($s, $s, $n);
10348             # Check for perfect square
10349 3         22 my $mc = $m & 31;
10350 3 50 33     50 next unless $mc==0||$mc==1||$mc==4||$mc==9||$mc==16||$mc==17||$mc==25;
      33        
      33        
      66        
      66        
      66        
10351 1         4 my $f = int(sqrt($m));
10352 1 50       5 next unless $f*$f == $m;
10353 1         32 $f = _gcd_ui($s - $f, $n);
10354 1         9 return _found_factor($f, $n, "HOLF ($i rounds)", @factors);
10355             }
10356             }
10357 0         0 push @factors, $n;
10358 0         0 @factors;
10359             }
10360              
10361             sub fermat_factor {
10362 2     2 0 3529 my($n, $rounds) = @_;
10363 2         21 validate_integer_nonneg($n);
10364 2 50       9 if (defined $rounds) { validate_integer_nonneg($rounds); }
  0         0  
10365 2         17 else { $rounds = 64*1024*1024; }
10366              
10367 2         20 my @factors = _basic_factor($n);
10368 2 50       25 return @factors if $n < 4;
10369              
10370 2 100       243 if (ref($n)) {
10371 1         25 my $pa = Msqrtint($n);
10372 1 50       10 return _found_factor($pa, $n, "Fermat", @factors) if Mmulint($pa,$pa) == $n;
10373 1         341 $pa = Madd1int($pa);
10374 1         5 my $b2 = Msubint(Mmulint($pa,$pa),$n);
10375 1         56 my $lasta = Maddint($pa,$rounds);
10376 1         7 while ($pa <= $lasta) {
10377 1 50       26 if (Mis_power($b2, 2, \my $s)) {
10378 1         19 my $i = Msubint($pa,($lasta-$rounds))+1;
10379 1         4 return _found_factor(Msubint($pa,$s), $n, "Fermat ($i rounds)", @factors);
10380             }
10381 0         0 $pa = Madd1int($pa);
10382 0         0 $b2 = Msubint(Mmulint($pa,$pa),$n);
10383             }
10384             } else {
10385 1         5 my $pa = int(sqrt($n));
10386 1 50       6 return _found_factor($pa, $n, "Fermat", @factors) if $pa*$pa == $n;
10387 1         2 $pa++;
10388 1         4 my $b2 = $pa*$pa - $n;
10389 1         5 my $lasta = $pa + $rounds;
10390 1         7 while ($pa <= $lasta) {
10391 2         7 my $mc = $b2 & 31;
10392 2 100 33     72 if ($mc==0||$mc==1||$mc==4||$mc==9||$mc==16||$mc==17||$mc==25) {
      33        
      33        
      33        
      66        
      66        
10393 1         5 my $s = int(sqrt($b2));
10394 1 50       7 if ($s*$s == $b2) {
10395 1         7 my $i = $pa-($lasta-$rounds)+1;
10396 1         21 return _found_factor($pa - $s, $n, "Fermat ($i rounds)", @factors);
10397             }
10398             }
10399 1         3 $pa++;
10400 1         5 $b2 = $pa*$pa-$n;
10401             }
10402             }
10403 0         0 push @factors, $n;
10404 0         0 @factors;
10405             }
10406              
10407              
10408             sub ecm_factor {
10409 5     5 0 4505 my($n, $B1, $B2, $ncurves) = @_;
10410 5         72 validate_integer_nonneg($n);
10411              
10412 5         32 my @factors = _basic_factor($n);
10413 5 50       49 return @factors if $n < 4;
10414              
10415 5 50       1027 if ($Math::Prime::Util::_GMPfunc{"ecm_factor"}) {
10416 0 0       0 $B1 = 0 if !defined $B1;
10417 0 0       0 $ncurves = 0 if !defined $ncurves;
10418 0         0 my @ef = Math::Prime::Util::GMP::ecm_factor($n, $B1, $ncurves);
10419 0 0       0 if (@ef > 1) {
10420 0         0 my $ecmfac = reftyped($n, $ef[-1]);
10421 0         0 return _found_factor($ecmfac, $n, "ECM (GMP) B1=$B1 curves $ncurves", @factors);
10422             }
10423 0         0 push @factors, $n;
10424 0         0 return @factors;
10425             }
10426              
10427 5         24 $n = tobigint($n) if OLD_PERL_VERSION && !ref($n) && $n > INTMAX;
10428              
10429 5 100       29 $ncurves = 10 unless defined $ncurves;
10430              
10431 5 100       23 if (!defined $B1) {
10432 1         6 for my $mul (1, 10, 100, 1000, 10_000, 100_000, 1_000_000) {
10433 1         5 $B1 = 100 * $mul;
10434 1         5 $B2 = 10*$B1;
10435             #warn "Trying ecm with $B1 / $B2\n";
10436 1         48 my @nf = ecm_factor($n, $B1, $B2, $ncurves);
10437 1 50       8 if (scalar @nf > 1) {
10438 1         5 push @factors, @nf;
10439 1         14 return @factors;
10440             }
10441             }
10442 0         0 push @factors, $n;
10443 0         0 return @factors;
10444             }
10445              
10446 4 50       17 $B2 = 10*$B1 unless defined $B2;
10447 4         18 my $sqrt_b1 = int(sqrt($B1)+1);
10448              
10449             # Affine code. About 3x slower than the projective, and no stage 2.
10450             #
10451             #if (!defined $Math::Prime::Util::ECAffinePoint::VERSION) {
10452             # eval { require Math::Prime::Util::ECAffinePoint; 1; }
10453             # or do { croak "Cannot load Math::Prime::Util::ECAffinePoint"; };
10454             #}
10455             #my @bprimes = @{ primes(2, $B1) };
10456             #my $irandf = Math::Prime::Util::_get_rand_func();
10457             #foreach my $curve (1 .. $ncurves) {
10458             # my $a = $irandf->($n-1);
10459             # my $b = 1;
10460             # my $ECP = Math::Prime::Util::ECAffinePoint->new($a, $b, $n, 0, 1);
10461             # foreach my $q (@bprimes) {
10462             # my $k = $q;
10463             # if ($k < $sqrt_b1) {
10464             # my $kmin = int($B1 / $q);
10465             # while ($k <= $kmin) { $k *= $q; }
10466             # }
10467             # $ECP->mul($k);
10468             # my $f = $ECP->f;
10469             # if ($f != 1) {
10470             # last if $f == $n;
10471             # warn "ECM found factors with B1 = $B1 in curve $curve\n";
10472             # return _found_factor($f, $n, "ECM B1=$B1 curve $curve", @factors);
10473             # }
10474             # last if $ECP->is_infinity;
10475             # }
10476             #}
10477              
10478 4         1910 require Math::Prime::Util::ECProjectivePoint;
10479 4         1111 require Math::Prime::Util::RandomPrimes;
10480              
10481             # With multiple curves, it's better to get all the primes at once.
10482             # The downside is this can kill memory with a very large B1.
10483 4         21 my @bprimes = @{ Mprimes(3, $B1) };
  4         37  
10484 4         22 foreach my $q (@bprimes) {
10485 11 100       41 last if $q > $sqrt_b1;
10486 7         25 my($k,$kmin) = ($q, int($B1/$q));
10487 7         32 while ($k <= $kmin) { $k *= $q; }
  6         12  
10488 7         11 $q = $k;
10489             }
10490 4 50       26 my @b2primes = ($B2 > $B1) ? @{Mprimes($B1+1, $B2)} : ();
  4         24  
10491              
10492 4         171 foreach my $curve (1 .. $ncurves) {
10493 4         60 my $sigma = tobigint(Murandomm($n-6)) + 6;
10494              
10495 4         1578 my ($u, $v) = ( ($sigma*$sigma - 5) % $n, (4 * $sigma) % $n );
10496 4         6476 my ($x, $z) = ( ($u*$u*$u) % $n, ($v*$v*$v) % $n );
10497 4         6672 my $cb = (4 * $x * $v) % $n;
10498 4         3795 my $ca = ( (($v-$u)**3) * (3*$u + $v) ) % $n;
10499              
10500 4         9454 my $f = Mgcd( $cb, $n );
10501 4 50       34 $f = Mgcd( $z, $n ) if $f == 1;
10502 4 50       41 next if $f == $n;
10503 4 50       673 return _found_factor($f,$n, "ECM B1=$B1 curve $curve", @factors) if $f != 1;
10504 4         42 $u = Minvmod($cb,$n);
10505 4         30 $ca = (($ca*$u) - 2) % $n;
10506              
10507 4         4305 my $ECP = Math::Prime::Util::ECProjectivePoint->new($ca, $n, $x, $z);
10508 4         16 my $fm = $n-$n+1;
10509 4         1724 my $i = 15;
10510              
10511 4         25 for (my $q = 2; $q < $B1; $q *= 2) { $ECP->double(); }
  13         71  
10512 4         19 foreach my $k (@bprimes) {
10513 25         161 $ECP->mul($k);
10514 25         225 $fm = ($fm * $ECP->x() ) % $n;
10515 25 100       12710 if ($i++ % 32 == 0) {
10516 1         12 $f = Mgcd($fm, $n);
10517 1 50       9 last if $f != 1;
10518             }
10519             }
10520 4         36 $f = Mgcd($fm, $n);
10521 4 50       25 next if $f == $n;
10522              
10523 4 100 66     762 if ($f == 1 && $B2 > $B1) { # BEGIN STAGE 2
10524 3 100       44 my $D = Msqrtint($B2 >> 1); $D++ if $D % 2;
  3         16  
10525 3         13 my $one = $n - $n + 1;
10526 3         1217 my $g = $one;
10527              
10528 3         43 my $S2P = $ECP->copy->normalize;
10529 3         21 $f = $S2P->f;
10530 3 50       16 if ($f != 1) {
10531 0 0       0 next if $f == $n;
10532             #warn "ECM S2 normalize f=$f\n" if $f != 1;
10533 0         0 return _found_factor($f, $n, "ECM S2 B1=$B1 curve $curve");
10534             }
10535 3         1167 my $S2x = $S2P->x;
10536 3         23 my $S2d = $S2P->d;
10537 3         29 my @nqx = ($n-$n, $S2x);
10538              
10539 3         437 foreach my $i (2 .. 2*$D) {
10540 156         108913 my($x2, $z2);
10541 156 100       653 if ($i % 2) {
10542 77         682 ($x2, $z2) = Math::Prime::Util::ECProjectivePoint::_addx($nqx[($i-1)/2], $nqx[($i+1)/2], $S2x, $n);
10543             } else {
10544 79         618 ($x2, $z2) = Math::Prime::Util::ECProjectivePoint::_double($nqx[$i/2], $one, $n, $S2d);
10545             }
10546 156         89528 $nqx[$i] = $x2;
10547             #($f, $u, undef) = _extended_gcd($z2, $n);
10548 156         1012 $f = Mgcd( $z2, $n );
10549 156 100       838 last if $f != 1;
10550 155         785 $u = Minvmod($z2,$n);
10551 155         933 $nqx[$i] = ($x2 * $u) % $n;
10552             }
10553 3 100       896 if ($f != 1) {
10554 1 50       6 next if $f == $n;
10555             #warn "ECM S2 1: B1 $B1 B2 $B2 curve $curve f=$f\n";
10556 1         8 return _found_factor($f, $n, "ECM S2 B1=$B1 curve $curve", @factors);
10557             }
10558              
10559 2         8 $x = $nqx[2*$D-1];
10560 2         10 my $m = 1;
10561 2         17 while ($m < ($B2+$D)) {
10562 37 100       135 if ($m != 1) {
10563 35         67 my $oldx = $S2x;
10564 35         266 my ($x1, $z1) = Math::Prime::Util::ECProjectivePoint::_addx($nqx[2*$D], $S2x, $x, $n);
10565 35         38072 $f = Mgcd( $z1, $n );
10566 35 50       183 last if $f != 1;
10567 35         130 $u = $z1->copy->bmodinv($n);
10568 35         185840 $S2x = ($x1 * $u) % $n;
10569 35         20347 $x = $oldx;
10570 35 50       288 last if $f != 1;
10571             }
10572 37 50       211 if ($m+$D > $B1) {
10573 37 100       235 my @p = grep { $_ >= $m-$D && $_ <= $m+$D } @b2primes;
  8652         21438  
10574 37         101 foreach my $i (@p) {
10575 194 100       119997 last if $i >= $m;
10576 157         713 $g = ($g * ($S2x - $nqx[$m+$D-$i])) % $n;
10577             }
10578 37         95 foreach my $i (@p) {
10579 335 100       57090 next unless $i > $m;
10580 166 100 100     766 next if $i > ($m+$m) || is_prime($m+$m-$i);
10581 101         475 $g = ($g * ($S2x - $nqx[$i-$m])) % $n;
10582             }
10583 37         19156 $f = Mgcd($g, $n);
10584             #warn "ECM S2 3: found $f in stage 2\n" if $f != 1;
10585 37 100       336 last if $f != 1;
10586             }
10587 35         193 $m += 2*$D;
10588             }
10589             } # END STAGE 2
10590              
10591 3 50       35 next if $f == $n;
10592 3 50       676 if ($f != 1) {
10593             #warn "ECM found factors with B1 = $B1 in curve $curve\n";
10594 3         1113 return _found_factor($f, $n, "ECM B1=$B1 curve $curve", @factors);
10595             }
10596             # end of curve loop
10597             }
10598 0         0 push @factors, $n;
10599 0         0 @factors;
10600             }
10601              
10602             sub divisors {
10603 40     40 0 4988 my($n,$k) = @_;
10604 40         220 validate_integer_nonneg($n);
10605 40 100       520 if (defined $k) {
10606 1         5 validate_integer_nonneg($k);
10607 1 50       3 $k = $n if $k > $n;
10608             } else {
10609 39         94 $k = $n;
10610             }
10611              
10612 40 50       362 if (!wantarray) {
10613             # In scalar context, returns sigma_0(n). Very fast.
10614 0 0       0 return Mdivisor_sum($n,0) if $k >= $n;
10615 0         0 my @div = divisors($n,$k);
10616 0         0 return scalar(@div);
10617             }
10618              
10619 40 50 33     271 return () if $n == 0 || $k == 0;
10620 40 100 66     3774 return (1) if $n == 1 || $k == 1;
10621              
10622 36         2987 my @d;
10623 36 50       157 if ($Math::Prime::Util::_GMPfunc{"divisors"}) {
10624             # This trips an erroneous compile time error without the eval.
10625 0 0 0     0 if ($k < $n && $Math::Prime::Util::GMP::VERSION >= 0.53) {
10626 0         0 eval "\@d = Math::Prime::Util::GMP::divisors(\"$n\",\"$k\"); "; ## no critic qw(ProhibitStringyEval)
10627             } else {
10628 0         0 eval "\@d = Math::Prime::Util::GMP::divisors(\"$n\"); "; ## no critic qw(ProhibitStringyEval)
10629 0 0       0 @d = grep { $_ <= $k } @d if $k < $n;
  0         0  
10630             }
10631 0         0 return maybetobigintall(@d);
10632             }
10633              
10634 36         195 my @pe = Mfactor_exp($n);
10635 36 100 100     350 return (1,$n) if @pe == 1 && $pe[0]->[1] == 1 && $n <= $k;
      66        
10636              
10637 31         97 @d = (1);
10638 31         83 for my $pe (@pe) {
10639 91         291 my($p,$e) = @$pe;
10640 91 100       290 last if $p > $k;
10641 90         2900 my @t;
10642 90         189 push @d, @t = map { Mmulint($_,$p) } @d; # multiply through
  404         9063  
10643 90         1679 push @d, @t = map { Mmulint($_,$p) } @t for 2 .. $e; # repeat
  19         49  
10644             }
10645              
10646 31 100       123 @d = grep { $_ <= $k } @d if $k < $n;
  96         268  
10647 31         527 Mvecsort(@d);
10648             }
10649              
10650              
10651             ################################################################################
10652              
10653              
10654             sub _chebyshev_theta {
10655 2     2   9 my($n,$low) = @_;
10656 2         7 my($sum,$high) = (0.0, 0);
10657 2         9 while ($low <= $n) {
10658 2         6 $high = $low + 1e6;
10659 2 50       20 $high = $n if $high > $n;
10660 2         5 $sum += log($_) for @{Mprimes($low,$high)};
  2         16  
10661 2         54 $low = $high+1;
10662             }
10663 2         19 $sum;
10664             }
10665             sub chebyshev_theta {
10666 1     1 0 4 my($n) = @_;
10667 1         6 validate_integer_nonneg($n);
10668 1         6 _chebyshev_theta($n,2);
10669             }
10670              
10671             sub chebyshev_psi {
10672 1     1 0 5 my($n) = @_;
10673 1         9 validate_integer_nonneg($n);
10674 1 50       6 return 0 if $n <= 1;
10675 1         10 my ($sum, $logn, $sqrtn) = (0.0, log($n), Msqrtint($n));
10676              
10677             # Sum the log of prime powers first
10678 1         4 for my $p (@{Mprimes($sqrtn)}) {
  1         7  
10679 22         47 my $logp = log($p);
10680 22         49 $sum += $logp * int($logn/$logp+1e-15);
10681             }
10682             # The rest all have exponent 1: add them in using the segmenting theta code
10683 1         9 $sum += _chebyshev_theta($n, $sqrtn+1);
10684              
10685 1         41 $sum;
10686             }
10687              
10688             sub hclassno {
10689 14     14 0 37 my($n) = @_;
10690 14         76 validate_integer($n);
10691              
10692 14 50       36 return -1 if $n == 0;
10693 14 50 33     123 return 0 if $n < 0 || ($n % 4) == 1 || ($n % 4) == 2;
      33        
10694 14 100       74 return 2 * (2,3,6,6,6,8,12,9,6,12,18,12,8,12,18,18,12,15,24,12,6,24,30,20,12,12,24,24,18,24)[($n>>1)-1] if $n <= 60;
10695              
10696 6         29 my ($h, $square, $b, $b2) = (0, 0, $n & 1, ($n+1) >> 2);
10697              
10698 6 50       16 if ($b == 0) {
10699 6         34 my $lim = Msqrtint($b2);
10700 6 100       22 if (_is_perfect_square($b2)) {
10701 2         6 $square = 1;
10702 2         36 $lim--;
10703             }
10704             #$h += scalar(grep { $_ <= $lim } divisors($b2));
10705 6 100       23 for my $i (1 .. $lim) { $h++ unless $b2 % $i; }
  32         105  
10706 6         28 ($b,$b2) = (2, ($n+4) >> 2);
10707             }
10708 6         29 while ($b2 * 3 < $n) {
10709 18 100       38 $h++ unless $b2 % $b;
10710 18         44 my $lim = Msqrtint($b2);
10711 18 100       50 if (_is_perfect_square($b2)) {
10712 3         6 $h++;
10713 3         9 $lim--;
10714             }
10715             #$h += 2 * scalar(grep { $_ > $b && $_ <= $lim } divisors($b2));
10716 18 100       48 for my $i ($b+1 .. $lim) { $h += 2 unless $b2 % $i; }
  37         103  
10717 18         28 $b += 2;
10718 18         66 $b2 = ($n+$b*$b) >> 2;
10719             }
10720 6 100       40 return (($b2*3 == $n) ? 2*(3*$h+1) : $square ? 3*(2*$h+1) : 6*$h) << 1;
    50          
10721             }
10722              
10723             # Ramanujan Tau using Cohen's method with Hurwitz class numbers.
10724             # Also see Lygeros (2010).
10725             # The two hclassno calls could be collapsed with some work
10726             sub _tauprime {
10727 11     11   27 my($p) = @_;
10728 11 100       29 return -24 if $p == 2;
10729              
10730 9         24 my $sum = 0;
10731 9         95 my($p9,$pp7) = (Mmulint(9,$p), Mvecprod(7,$p,$p));
10732 9         50 for my $t (1 .. Msqrtint($p)) {
10733 44         115 my $t2 = Mpowint($t,2);
10734 44         104 my $v = Msubint($p,$t2);
10735 44         102 my $T1 = Mpowint($t2,3);
10736 44         185 my $T2 = Maddint( Msubint(Mvecprod(4,$t2,$t2), Mmulint($p9,$t2)), $pp7);
10737 44         94 my $T3;
10738 44         83 my $v4 = $v % 4;
10739 44 100       121 if ($v4 == 0) {
    100          
10740 18         102 $T3 = Maddint(Mmulint(2,Mhclassno($v)), Mhclassno(Mmulint(4,$v)) );
10741             } elsif ($v4 == 3) {
10742 3 100       38 $T3 = Mmulint( $v%8 == 3 ? 6 : 4, Mhclassno($v) );
10743             } else {
10744 23         86 $T3 = Mhclassno(Mmulint(4,$v));
10745             }
10746              
10747 44         188 $sum = Maddint($sum, Mvecprod($T1, $T2, $T3));
10748             }
10749 9         99 Mvecsum( Mmulint( 28, Mpowint($p,6)),
10750             Mmulint(-28, Mpowint($p,5)),
10751             Mmulint(-90, Mpowint($p,4)),
10752             Mmulint(-35, Mpowint($p,3)),
10753             -1,
10754             Mmulint(-32,Mdivint($sum,3)) );
10755             }
10756              
10757             # Recursive method for handling prime powers
10758             sub _taupower {
10759 13     13   35 my($p, $e, $tp) = @_;
10760 13 50       36 return 1 if $e <= 0;
10761 13 100       65 $tp = _tauprime($p) unless defined $tp;
10762              
10763 13 100       352 return $tp if $e == 1;
10764              
10765 4         14 my $p11 = Mpowint($p,11);
10766 4 100       26 return Msubint(Mpowint($tp,2), $p11) if $e == 2;
10767 2 50       42 return Msubint(Mpowint($tp,3), Mvecprod(2,$tp,$p11)) if $e == 3;
10768 2 100       12 return Mvecsum(Mpowint($tp,4), Mvecprod(-3,Mpowint($tp,2),$p11), Mpowint($p11,2)) if $e == 4;
10769              
10770             # Recurse -3
10771 1         6 my $F3 = Msubint(Mpowint($tp,3),Mvecprod(2,$tp,$p11));
10772 1         6 my $F4 = Msubint(Mmulint($p11,$p11),Mvecprod($tp,$tp,$p11));
10773 1         7 Maddint( Mmulint($F3,_taupower($p,$e-3,$tp)),
10774             Mmulint($F4,_taupower($p,$e-4,$tp)) );
10775             }
10776              
10777             sub ramanujan_tau {
10778 7     7 0 5254 my($n) = @_;
10779 7         48 validate_integer_nonneg($n);
10780 7 50       23 return 0 if $n <= 0;
10781              
10782             # Use GMP if we have no XS or if size is small
10783 7 50 33     33 if ($n < 100000 || !getconfig()->{'xs'}) {
10784 7 50       44 if ($Math::Prime::Util::_GMPfunc{"ramanujan_tau"}) {
10785 0         0 return reftyped($_[0], Math::Prime::Util::GMP::ramanujan_tau($n));
10786             }
10787             }
10788 7         75 Mvecprod(map { _taupower($_->[0],$_->[1]) } Mfactor_exp($n));
  11         69  
10789             }
10790              
10791             sub _Euler {
10792 82     82   205 my($dig) = @_;
10793             return Math::Prime::Util::GMP::Euler($dig)
10794 82 0 33     272 if $dig > 70 && $Math::Prime::Util::_GMPfunc{"Euler"};
10795 82         915 '0.57721566490153286060651209008240243104215933593992359880576723488486772677766467';
10796             }
10797             sub _Li2 {
10798 1     1   6 my($dig) = @_;
10799             return Math::Prime::Util::GMP::li(2,$dig)
10800 1 0 33     6 if $dig > 70 && $Math::Prime::Util::_GMPfunc{"li"};
10801 1         12 '1.04516378011749278484458888919461313652261557815120157583290914407501320521';
10802             }
10803              
10804             sub ExponentialIntegral {
10805 57     57 0 116 my($x) = @_;
10806 57 50       170 return - MPU_INFINITY if $x == 0;
10807 57 50       134 return 0 if $x == - MPU_INFINITY;
10808 57 50       152 return MPU_INFINITY if $x == MPU_INFINITY;
10809              
10810             # We are going to ignore bignum, as it's:
10811             # 1) unclear what we should do different
10812             # 2) hard to tell if it's active in scope
10813             # We do have to care in regards to giving correct results. But we're not
10814             # going to actively promote things based on it.
10815              
10816 57 50       140 if ($Math::Prime::Util::_GMPfunc{"ei"}) {
10817 0 0       0 my $r = _try_real_gmp_func(\&Math::Prime::Util::GMP::ei, $x<100?0.49:0.53, $x);
10818 0 0       0 return $r if defined $r;
10819             }
10820 57 0 33     163 $x=_bigint_to_int($x) if ref($x)eq'Math::BigInt' && $x<=INTMAX && $x>=INTMIN;
      33        
10821 57 50 33     151 $x=_upgrade_to_float($x) if ref($x) && ref($x) ne 'Math::BigFloat';
10822              
10823 57         117 my $tol = 1e-16;
10824 57         113 my $sum = 0.0;
10825 57         94 my($y, $t);
10826 57         94 my $c = 0.0;
10827 57         88 my $val; # The result from one of the four methods
10828              
10829 57 100       268 if ($x < -1) {
    100          
    100          
10830             # Continued fraction
10831 1         3 my $lc = 0;
10832 1         4 my $ld = 1 / (1 - $x);
10833 1         6 $val = $ld * (-exp($x));
10834 1         4 for my $n (1 .. 100000) {
10835 15         33 $lc = 1 / (2*$n + 1 - $x - $n*$n*$lc);
10836 15         31 $ld = 1 / (2*$n + 1 - $x - $n*$n*$ld);
10837 15         25 my $old = $val;
10838 15         25 $val *= $ld/$lc;
10839 15 100       40 last if abs($val - $old) <= ($tol * abs($val));
10840             }
10841             } elsif ($x < 0) {
10842             # Rational Chebyshev approximation
10843 5         18 my @C6p = ( -148151.02102575750838086,
10844             150260.59476436982420737,
10845             89904.972007457256553251,
10846             15924.175980637303639884,
10847             2150.0672908092918123209,
10848             116.69552669734461083368,
10849             5.0196785185439843791020);
10850 5         16 my @C6q = ( 256664.93484897117319268,
10851             184340.70063353677359298,
10852             52440.529172056355429883,
10853             8125.8035174768735759866,
10854             750.43163907103936624165,
10855             40.205465640027706061433,
10856             1.0000000000000000000000);
10857 5         15 my $sumn = $C6p[0]-$x*($C6p[1]-$x*($C6p[2]-$x*($C6p[3]-$x*($C6p[4]-$x*($C6p[5]-$x*$C6p[6])))));
10858 5         11 my $sumd = $C6q[0]-$x*($C6q[1]-$x*($C6q[2]-$x*($C6q[3]-$x*($C6q[4]-$x*($C6q[5]-$x*$C6q[6])))));
10859 5         26 $val = log(-$x) - ($sumn / $sumd);
10860             } elsif ($x < -log($tol)) {
10861             # Convergent series
10862 48         82 my $fact_n = 1;
10863 48         125 $y = _Euler(18)-$c; $t = $sum+$y; $c = ($t-$sum)-$y; $sum = $t;
  48         114  
  48         112  
  48         73  
10864 48         94 $y = log($x)-$c; $t = $sum+$y; $c = ($t-$sum)-$y; $sum = $t;
  48         93  
  48         78  
  48         76  
10865 48         143 for my $n (1 .. 200) {
10866 4298         6956 $fact_n *= $x/$n;
10867 4298         7056 my $term = $fact_n / $n;
10868 4298         6723 $y = $term-$c; $t = $sum+$y; $c = ($t-$sum)-$y; $sum = $t;
  4298         6560  
  4298         6634  
  4298         6317  
10869 4298 100       9281 last if $term < $tol;
10870             }
10871 48         117 $val = $sum;
10872             } else {
10873             # Asymptotic divergent series
10874 3         13 my $invx = 1.0 / $x;
10875 3         8 my $term = $invx;
10876 3         6 $sum = 1.0 + $term;
10877 3         30 for my $n (2 .. 200) {
10878 81         124 my $last_term = $term;
10879 81         144 $term *= $n * $invx;
10880 81 100       161 last if $term < $tol;
10881 78 50       145 if ($term < $last_term) {
10882 78         114 $y = $term-$c; $t = $sum+$y; $c = ($t-$sum)-$y; $sum = $t;
  78         138  
  78         117  
  78         152  
10883             } else {
10884 0         0 $y = (-$last_term/3)-$c; $t = $sum+$y; $c = ($t-$sum)-$y; $sum = $t;
  0         0  
  0         0  
  0         0  
10885 0         0 last;
10886             }
10887             }
10888 3         12 $val = exp($x) * $invx * $sum;
10889             }
10890 57         493 $val;
10891             }
10892              
10893             sub LogarithmicIntegral {
10894 56     56 0 150 my($x) = @_;
10895 56 50       250 return 0 if $x == 0;
10896 56 50       11483 return - MPU_INFINITY if $x == 1;
10897 56 50       10454 return MPU_INFINITY if $x == MPU_INFINITY;
10898 56 50       8520 croak "Invalid input to LogarithmicIntegral: x must be > 0" if $x <= 0;
10899              
10900 56 50       10753 if ($Math::Prime::Util::_GMPfunc{"li"}) {
10901 0         0 my $r = _try_real_gmp_func(\&Math::Prime::Util::GMP::li, 0.49, $x);
10902 0 0       0 return $r if defined $r;
10903             }
10904              
10905 56 100       212 if ($x == 2) {
10906 1 50       42 my $li2const = (ref($x) eq 'Math::BigFloat') ? Math::BigFloat->new(_Li2(_find_big_acc($x))) : 0.0+_Li2(30);
10907 1         19 return $li2const;
10908             }
10909              
10910 55 0 33     11429 $x=_bigint_to_int($x) if ref($x)eq'Math::BigInt' && $x<=INTMAX && $x>=INTMIN;
      33        
10911 55 50 66     265 $x=_upgrade_to_float($x) if ref($x) && ref($x) ne 'Math::BigFloat';
10912              
10913             # Make sure we preserve whatever accuracy setting the input was using.
10914 55 100 66     533 $x->accuracy($_[0]->accuracy) if ref($x) && ref($_[0]) =~ /^Math::Big/ && $_[0]->accuracy;
      100        
10915              
10916             # Do divergent series here for big inputs. Common for big pc approximations.
10917             # Why is this here?
10918             # 1) exp(log(x)) results in a lot of lost precision
10919             # 2) exp(x) with lots of precision turns out to be really slow, and in
10920             # this case it was unnecessary.
10921 55         1545 my $tol = 1e-16;
10922 55         95 my $xdigits = 0;
10923 55         161 my $finalacc = 0;
10924 55 100       223 if (ref($x) =~ /^Math::Big/) {
10925 24         116 $xdigits = _find_big_acc($x);
10926 24         118 my $xlen = length($x->copy->bfloor->bstr());
10927 24 100       5913 $xdigits = $xlen if $xdigits < $xlen;
10928 24         56 $finalacc = $xdigits;
10929 24         108 $xdigits += length(int(log(0.0+"$x"))) + 1;
10930 24         1536 $tol = Math::BigFloat->new(10)->bpow(-$xdigits);
10931 24         55038 $x->accuracy($xdigits);
10932             }
10933 55 100       2937 my $logx = $xdigits ? $x->copy->blog(undef,$xdigits) : log($x);
10934              
10935             # TODO: See if we can tune this
10936 55         3600284 if (0 && $x >= 1) {
10937             _upgrade_to_float();
10938             my $sum = Math::BigFloat->new(0);
10939             my $inner_sum = Math::BigFloat->new(0);
10940             my $p = Math::BigFloat->new(-1);
10941             my $factorial = 1;
10942             my $power2 = 1;
10943             my $q;
10944             my $k = 0;
10945             my $neglogx = -$logx;
10946             for my $n (1 .. 1000) {
10947             $factorial = mulint($factorial, $n);
10948             $q = mulint($factorial, $power2);
10949             $power2 = mulint(2, $power2);
10950             while ($k <= ($n-1)>>1) {
10951             $inner_sum += Math::BigFloat->bone / (2*$k+1);
10952             $k++;
10953             }
10954             $p->bmul($neglogx);
10955             my $term = $p->copy->bdiv("$q", $xdigits)->bmul($inner_sum);
10956             $term->bround($xdigits) if $xdigits;
10957             $sum->badd($term);
10958             last if $term->copy->babs < $tol;
10959             }
10960             $sum *= sqrt($x);
10961             return 0.0+_Euler(18) + log($logx) + $sum unless ref($x)=~/^Math::Big/;
10962             my $val = Math::BigFloat->new(_Euler(40))->badd("".log($logx))->badd("$sum");
10963             $val->accuracy($finalacc) if $xdigits;
10964             return $val;
10965             }
10966              
10967 55 100       250 if ($x > 1e16) {
10968 21 100       12822 my $invx = ref($logx) ? Math::BigFloat->bone / $logx : 1.0/$logx;
10969             # n = 0 => 0!/(logx)^0 = 1/1 = 1
10970             # n = 1 => 1!/(logx)^1 = 1/logx
10971 21         29431 my $term = $invx;
10972 21         174 my $sum = 1.0 + $term;
10973 21         19814 for my $n (2 .. 1000) {
10974 1030         85178 my $last_term = $term;
10975 1030         4054 $term *= $n * $invx;
10976 1030 100       1665491 last if $term < $tol;
10977 1029 100       298696 if ($term < $last_term) {
10978 1009         283598 $sum += $term;
10979             } else {
10980 20         6973 $sum -= ($last_term/3);
10981 20         45965 last;
10982             }
10983 1009 100       885113 $term->bround($xdigits) if $xdigits;
10984             }
10985 21         102 $invx *= $sum;
10986 21         19851 $invx *= $x;
10987 21 100 66     13066 $invx->accuracy($finalacc) if ref($invx) && $xdigits;
10988 21         9059 return $invx;
10989             }
10990             # Convergent series.
10991 34 50       2857 if ($x >= 1) {
10992 34         2188 my $fact_n = 1.0;
10993 34         58 my $nfac = 1.0;
10994 34         65 my $sum = 0.0;
10995 34         119 for my $n (1 .. 200) {
10996 2004         45963 $fact_n *= $logx/$n;
10997 2004         1023412 my $term = $fact_n / $n;
10998 2004         614134 $sum += $term;
10999 2004 100       414604 last if $term < $tol;
11000 1970 100       164846 $term->bround($xdigits) if $xdigits;
11001             }
11002              
11003 34 100       1494 return 0.0+_Euler(18) + log($logx) + $sum unless ref($x) =~ /^Math::Big/;
11004              
11005 4         29 my $val = Math::BigFloat->new(_Euler(40))->badd("".log($logx))->badd("$sum");
11006 4 50       538525 $val->accuracy($finalacc) if $xdigits;
11007 4         1994 return $val;
11008             }
11009              
11010 0         0 ExponentialIntegral($logx);
11011             }
11012              
11013             # Riemann Zeta function for native integers.
11014             my @_Riemann_Zeta_Table = (
11015             0.6449340668482264364724151666460251892, # zeta(2) - 1
11016             0.2020569031595942853997381615114499908,
11017             0.0823232337111381915160036965411679028,
11018             0.0369277551433699263313654864570341681,
11019             0.0173430619844491397145179297909205279,
11020             0.0083492773819228268397975498497967596,
11021             0.0040773561979443393786852385086524653,
11022             0.0020083928260822144178527692324120605,
11023             0.0009945751278180853371459589003190170,
11024             0.0004941886041194645587022825264699365,
11025             0.0002460865533080482986379980477396710,
11026             0.0001227133475784891467518365263573957,
11027             0.0000612481350587048292585451051353337,
11028             0.0000305882363070204935517285106450626,
11029             0.0000152822594086518717325714876367220,
11030             0.0000076371976378997622736002935630292,
11031             0.0000038172932649998398564616446219397,
11032             0.0000019082127165539389256569577951013,
11033             0.0000009539620338727961131520386834493,
11034             0.0000004769329867878064631167196043730,
11035             0.0000002384505027277329900036481867530,
11036             0.0000001192199259653110730677887188823,
11037             0.0000000596081890512594796124402079358,
11038             0.0000000298035035146522801860637050694,
11039             0.0000000149015548283650412346585066307,
11040             0.0000000074507117898354294919810041706,
11041             0.0000000037253340247884570548192040184,
11042             0.0000000018626597235130490064039099454,
11043             0.0000000009313274324196681828717647350,
11044             0.0000000004656629065033784072989233251,
11045             0.0000000002328311833676505492001455976,
11046             0.0000000001164155017270051977592973835,
11047             0.0000000000582077208790270088924368599,
11048             0.0000000000291038504449709968692942523,
11049             0.0000000000145519218910419842359296322,
11050             0.0000000000072759598350574810145208690,
11051             0.0000000000036379795473786511902372363,
11052             0.0000000000018189896503070659475848321,
11053             0.0000000000009094947840263889282533118,
11054             );
11055              
11056              
11057             sub RiemannZeta {
11058 627     627 0 949 my($x) = @_;
11059              
11060             # Try our GMP code if possible.
11061 627 50       1123 if ($Math::Prime::Util::_GMPfunc{"zeta"}) {
11062 0         0 my($wantbf,$xdigits) = _bfdigits($x);
11063             # If we knew the *exact* number of zero digits, we could let GMP zeta
11064             # handle the correct rounding. But we don't, so we have to go over.
11065 0         0 my $zero_dig = "".int($x / 3) - 1;
11066 0         0 my $strval = Math::Prime::Util::GMP::zeta($x, $xdigits + 8 + $zero_dig);
11067 0 0       0 if ($strval =~ s/^(1\.0*)/./) {
11068 0 0       0 $strval .= "e-".(length($1)-2) if length($1) > 2;
11069             } else {
11070 0         0 $strval =~ s/^(-?\d+)/$1-1/e;
  0         0  
11071             }
11072              
11073 0 0       0 return ($wantbf) ? Math::BigFloat->new($strval,$wantbf) : 0.0 + $strval;
11074             }
11075              
11076             # If we need a bigfloat result, then call our PP routine.
11077 627 100       1185 if (ref($x) =~ /^Math::Big/) {
11078 4         1354 require Math::Prime::Util::ZetaBigFloat;
11079 4         33 return Math::Prime::Util::ZetaBigFloat::RiemannZeta($x);
11080             }
11081              
11082             # Native float results
11083 623 100 100     1860 return 0.0 + $_Riemann_Zeta_Table[int($x)-2]
11084             if $x == int($x) && defined $_Riemann_Zeta_Table[int($x)-2];
11085 596         750 my $tol = 1.11e-16;
11086              
11087             # Series based on (2n)! / B_2n.
11088             # This is a simplification of the Cephes zeta function.
11089 596         1162 my @A = (
11090             12.0,
11091             -720.0,
11092             30240.0,
11093             -1209600.0,
11094             47900160.0,
11095             -1892437580.3183791606367583212735166426,
11096             74724249600.0,
11097             -2950130727918.1642244954382084600497650,
11098             116467828143500.67248729113000661089202,
11099             -4597978722407472.6105457273596737891657,
11100             181521054019435467.73425331153534235290,
11101             -7166165256175667011.3346447367083352776,
11102             282908877253042996618.18640556532523927,
11103             );
11104 596         825 my $s = 0.0;
11105 596         753 my $rb = 0.0;
11106 596         922 foreach my $i (2 .. 10) {
11107 2124         3174 $rb = $i ** -$x;
11108 2124         2687 $s += $rb;
11109 2124 100       4691 return $s if abs($rb/$s) < $tol;
11110             }
11111 4         9 my $w = 10.0;
11112 4         13 $s = $s + $rb*$w/($x-1.0) - 0.5*$rb;
11113 4         9 my $ra = 1.0;
11114 4         9 foreach my $i (0 .. 12) {
11115 29         41 my $k = 2*$i;
11116 29         79 $ra *= $x + $k;
11117 29         49 $rb /= $w;
11118 29         57 my $t = $ra*$rb/$A[$i];
11119 29         41 $s += $t;
11120 29         47 $t = abs($t/$s);
11121 29 100       61 last if $t < $tol;
11122 25         42 $ra *= $x + $k + 1.0;
11123 25         46 $rb /= $w;
11124             }
11125 4         72 return $s;
11126             }
11127              
11128             # Riemann R function
11129             sub RiemannR {
11130 29     29 0 65 my($x) = @_;
11131              
11132 29 50       71 croak "Invalid input to RiemannR: x must be > 0" if $x <= 0;
11133              
11134 29 50       110 if ($Math::Prime::Util::_GMPfunc{"riemannr"}) {
11135 0         0 my $r = _try_real_gmp_func(\&Math::Prime::Util::GMP::riemannr, 0.41, $x);
11136 0 0       0 return $r if defined $r;
11137             }
11138 29 0 33     97 $x=_bigint_to_int($x) if ref($x)eq'Math::BigInt' && $x<=INTMAX && $x>=INTMIN;
      33        
11139 29 50 33     85 $x=_upgrade_to_float($x) if ref($x) && ref($x) ne 'Math::BigFloat';
11140              
11141              
11142             # TODO: look into this as a generic solution
11143 29         42 if (0 && $Math::Prime::Util::_GMPfunc{"zeta"}) {
11144             my($wantbf,$xdigits) = _bfdigits($x);
11145             $x = _upgrade_to_float($x);
11146              
11147             my $extra_acc = 4;
11148             $xdigits += $extra_acc;
11149             $x->accuracy($xdigits);
11150              
11151             my $logx = log($x);
11152             my $part_term = $x->copy->bone;
11153             my $sum = $x->copy->bone;
11154             my $tol = $x->copy->bone->brsft($xdigits-1, 10);
11155             my $bigk = $x->copy->bone;
11156             my $term;
11157             for my $k (1 .. 10000) {
11158             $part_term *= $logx / $bigk;
11159             my $zarg = $bigk->copy->binc;
11160             my $zeta = (RiemannZeta($zarg) * $bigk) + $bigk;
11161             #my $strval = Math::Prime::Util::GMP::zeta($k+1, $xdigits + int(($k+1) / 3));
11162             #my $zeta = Math::BigFloat->new($strval)->bdec->bmul($bigk)->badd($bigk);
11163             $term = $part_term / $zeta;
11164             $sum += $term;
11165             last if $term < ($tol * $sum);
11166             $bigk->binc;
11167             }
11168             $sum->bround($xdigits-$extra_acc);
11169             my $strval = "$sum";
11170             return ($wantbf) ? Math::BigFloat->new($strval,$wantbf) : 0.0 + $strval;
11171             }
11172              
11173 29 50       69 if (ref($x) =~ /^Math::Big/) {
11174 0         0 require Math::Prime::Util::ZetaBigFloat;
11175 0         0 return Math::Prime::Util::ZetaBigFloat::RiemannR($x);
11176             }
11177              
11178 29         51 my $sum = 0.0;
11179 29         45 my $tol = 1e-18;
11180 29         60 my($c, $y, $t) = (0.0);
11181 29 100       128 if ($x > 10**17) {
11182 1         11 my @mob = Mmoebius(0,300);
11183 1         8 for my $k (1 .. 300) {
11184 19 100       50 next if $mob[$k] == 0;
11185 13         78 my $term = $mob[$k] / $k * MLi($x**(1.0/$k));
11186 13         32 $y = $term-$c; $t = $sum+$y; $c = ($t-$sum)-$y; $sum = $t;
  13         24  
  13         24  
  13         23  
11187 13 100       73 last if abs($term) < ($tol * abs($sum));
11188             }
11189             } else {
11190 28         52 $y = 1.0-$c; $t = $sum+$y; $c = ($t-$sum)-$y; $sum = $t;
  28         68  
  28         55  
  28         46  
11191 28         69 my $flogx = log($x);
11192 28         55 my $part_term = 1.0;
11193 28         96 for my $k (1 .. 10000) {
11194 1614 100       2943 my $zeta = ($k <= $#_Riemann_Zeta_Table)
11195             ? $_Riemann_Zeta_Table[$k+1-2] # Small k from table
11196             : RiemannZeta($k+1); # Large k from function
11197 1614         2369 $part_term *= $flogx / $k;
11198 1614         2492 my $term = $part_term / ($k + $k * $zeta);
11199 1614         2049 $y = $term-$c; $t = $sum+$y; $c = ($t-$sum)-$y; $sum = $t;
  1614         2027  
  1614         2055  
  1614         2073  
11200 1614 100       3034 last if $term < ($tol * $sum);
11201             }
11202             }
11203 29         196 return $sum;
11204             }
11205              
11206             sub LambertW {
11207 1     1 0 4 my($x) = @_;
11208 1 50       7 croak "Invalid input to LambertW: x must be >= -1/e" if $x < -0.36787944118;
11209              
11210 1 50       5 if ($Math::Prime::Util::_GMPfunc{"lambertw"}) {
11211 0         0 my $r = _try_real_gmp_func(\&Math::Prime::Util::GMP::lambertw, 0.42, $x);
11212 0 0       0 return $r if defined $r;
11213             }
11214 1 0 33     7 $x=_bigint_to_int($x) if ref($x)eq'Math::BigInt' && $x<=INTMAX && $x>=INTMIN;
      33        
11215 1 50 33     7 $x=_upgrade_to_float($x) if ref($x) && ref($x) ne 'Math::BigFloat';
11216              
11217 1 50       5 my $xacc = ref($x) ? _find_big_acc($x) : 0;
11218 1         3 my $w;
11219              
11220             # Approximation
11221 1 50       7 if ($x < -0.06) {
    50          
    50          
11222 0         0 my $ti = $x * 2 * exp($x-$x+1) + 2;
11223 0 0       0 return -1 if $ti <= 0;
11224 0         0 my $t = sqrt($ti);
11225 0         0 $w = (-1 + 1/6*$t + (257/720)*$t*$t + (13/720)*$t*$t*$t) / (1 + (5/6)*$t + (103/720)*$t*$t);
11226             } elsif ($x < 1.363) {
11227 0         0 my $l1 = log($x + 1);
11228 0         0 $w = $l1 * (1 - log(1+$l1) / (2+$l1));
11229             } elsif ($x < 3.7) {
11230 0         0 my $l1 = log($x);
11231 0         0 my $l2 = log($l1);
11232 0         0 $w = $l1 - $l2 - log(1 - $l2/$l1)/2.0;
11233             } else {
11234 1         4 my $l1 = log($x);
11235 1         3 my $l2 = log($l1);
11236 1         4 my $d1 = 2 * $l1 * $l1;
11237 1         3 my $d2 = 3 * $l1 * $d1;
11238 1         3 my $d3 = 2 * $l1 * $d2;
11239 1         5 my $d4 = 5 * $l1 * $d3;
11240 1         12 $w = $l1 - $l2 + $l2/$l1 + $l2*($l2-2)/$d1
11241             + $l2*(6+$l2*(-9+2*$l2))/$d2
11242             + $l2*(-12+$l2*(36+$l2*(-22+3*$l2)))/$d3
11243             + $l2*(60+$l2*(-300+$l2*(350+$l2*(-125+12*$l2))))/$d4;
11244             }
11245              
11246             # Now iterate to get the answer
11247             #
11248             # Newton:
11249             # $w = $w*(log($x) - log($w) + 1) / ($w+1);
11250             # Halley:
11251             # my $e = exp($w);
11252             # my $f = $w * $e - $x;
11253             # $w -= $f / ($w*$e+$e - ($w+2)*$f/(2*$w+2));
11254             #
11255             # Also see https://arxiv.org/pdf/2008.06122
11256             # https://people.eecs.berkeley.edu/~wkahan/Math273/LmbrtsW.pdf
11257              
11258             # Fritsch converges quadratically, so tolerance could be 4x smaller. Use 2x.
11259 1         2 my $tol = 1.054e-8; # sqrt(double eps)
11260 1 50       7 if ($xacc) {
11261 0         0 $tol = 10**(-int(1+$xacc/2));
11262 0         0 $w->accuracy($xacc+15);
11263             }
11264 1         4 for (1 .. 200) {
11265 2 50       9 last if $w == 0;
11266 2         5 my $w1 = $w + 1;
11267 2         5 my $zn = log($x/$w) - $w;
11268 2         6 my $qn = $w1 * 2 * ($w1+(2*$zn/3));
11269 2         6 my $en = ($zn/$w1) * ($qn-$zn)/($qn-$zn*2);
11270 2         5 my $wen = $w * $en;
11271 2         4 $w += $wen;
11272 2 100       8 last if abs($wen) < $tol;
11273             }
11274 1 50       4 $w->accuracy($xacc) if $xacc;
11275 1         10 return $w;
11276             }
11277              
11278             my $_Pi = "3.141592653589793238462643383279503";
11279             sub Pi {
11280 986     986 0 1459537 my($digits) = @_;
11281 986 50       4700 return 0.0+$_Pi unless $digits;
11282 986 50       4896 return 0.0+sprintf("%.*lf", $digits-1, $_Pi) if $digits < 15;
11283 986 100       5110 return _upgrade_to_float($_Pi, $digits) if $digits < 30;
11284              
11285             # Performance ranking:
11286             # MPU::GMP Uses AGM or Ramanujan/Chudnosky with binary splitting
11287             # MPFR Uses AGM, from 1x to 1/4x the above
11288             # Perl AGM w/GMP also AGM, nice growth rate, but slower than above
11289             # C pidigits much worse than above, but faster than the others
11290             # Perl AGM without Math::BigInt::GMP, it's sluggish
11291             # Math::BigFloat new versions use AGM, old ones are *very* slow
11292             #
11293             # With a few thousand digits, any of the top 4 are fine.
11294             # At 10k digits, the first two are pulling away.
11295             # At 50k digits, the first three are 5-20x faster than C pidigits, and
11296             # pray you're not having to the Perl BigFloat methods without GMP.
11297             # At 100k digits, the first two are 15x faster than the third, C pidigits
11298             # is 200x slower, and the rest thousands of times slower.
11299             # At 1M digits, the first is under 1 second, MPFR under 2 seconds,
11300             # Perl AGM (Math::BigInt::GMP) over a minute, C pidigits 1.5 hours.
11301             #
11302             # Interestingly, Math::BigInt::Pari, while greatly faster than Calc, is
11303             # *much* slower than GMP for these operations (both AGM and Machin). While
11304             # Perl AGM with the Math::BigInt::GMP backend will pull away from C pidigits,
11305             # using it with the other backends doesn't do so.
11306             #
11307             # The GMP program at https://gmplib.org/download/misc/gmp-chudnovsky.c
11308             # will run ~4x faster than MPFR and ~1.5x faster than MPU::GMP.
11309              
11310 972         6858 my $have_bigint_gmp = Math::BigInt->config()->{lib} =~ /GMP/;
11311 972         204604 my $have_xdigits = getconfig()->{'xs'};
11312 972         4118 my $_verbose = getconfig()->{'verbose'};
11313              
11314 972 50       5230 if ($Math::Prime::Util::_GMPfunc{"Pi"}) {
11315 0 0       0 print " using MPUGMP for Pi($digits)\n" if $_verbose;
11316 0         0 return _upgrade_to_float( Math::Prime::Util::GMP::Pi($digits) );
11317             }
11318              
11319             # We could consider looking for Math::MPFR or Math::Pari
11320              
11321             # This has a *much* better growth rate than the later solutions.
11322 972 100 33     6249 if ( !$have_xdigits || ($have_bigint_gmp && $digits > 100) ) {
      66        
11323 1 50       4 print " using Perl AGM for Pi($digits)\n" if $_verbose;
11324             # Brent-Salamin (aka AGM or Gauss-Legendre)
11325 1         4 $digits += 8;
11326 1         5 my $HALF = _upgrade_to_float(0.5);
11327 1         577 my ($an, $bn, $tn, $pn) = ($HALF->copy->bone, $HALF->copy->bsqrt($digits),
11328             $HALF->copy->bmul($HALF), $HALF->copy->bone);
11329 1         12013 while ($pn < $digits) {
11330 7         8388 my $prev_an = $an->copy;
11331 7         346 $an->badd($bn)->bmul($HALF, $digits);
11332 7         9825 $bn->bmul($prev_an)->bsqrt($digits);
11333 7         79080 $prev_an->bsub($an);
11334 7         6970 $tn->bsub($pn * $prev_an * $prev_an);
11335 7         22953 $pn->badd($pn);
11336             }
11337 1         1286 $an->badd($bn);
11338 1         753 $an->bmul($an,$digits)->bdiv(4*$tn, $digits-8);
11339 1         4039 return $an;
11340             }
11341              
11342             # Spigot method in C. Low overhead but not good growth rate.
11343 971 50       3071 if ($have_xdigits) {
11344 971 50       2571 print " using XS spigot for Pi($digits)\n" if $_verbose;
11345 971         3774270 return _upgrade_to_float(Math::Prime::Util::_pidigits($digits));
11346             }
11347              
11348             # We're going to have to use the Math::BigFloat code.
11349             # 1) it rounds incorrectly (e.g. 761, 1372, 1509,...).
11350             # Fix by adding some digits and rounding.
11351             # 2) AGM is *much* faster once past ~2000 digits
11352             # 3) It is very slow without the GMP backend. The Pari backend helps
11353             # but it still pretty bad. With Calc it's glacial for large inputs.
11354              
11355             # Math::BigFloat AGM spigot AGM
11356             # Size GMP Pari Calc GMP Pari Calc C C+GMP
11357             # 500 0.04 0.60 0.30 0.08 0.10 0.47 0.09 0.06
11358             # 1000 0.04 0.11 1.82 0.09 0.14 1.82 0.09 0.06
11359             # 2000 0.07 0.37 13.5 0.09 0.34 9.16 0.10 0.06
11360             # 4000 0.14 2.17 107.8 0.12 1.14 39.7 0.20 0.06
11361             # 8000 0.52 15.7 0.22 4.63 186.2 0.56 0.08
11362             # 16000 2.73 121.8 0.52 19.2 2.00 0.08
11363             # 32000 15.4 1.42 7.78 0.12
11364             # ^ ^ ^
11365             # | use this THIRD ---+ |
11366             # use this SECOND ---+ |
11367             # use this FIRST ---+
11368             # approx
11369             # growth 5.6x 7.6x 8.0x 2.7x 4.1x 4.7x 3.9x 2.0x
11370              
11371 0 0       0 print " using BigFloat for Pi($digits)\n" if $_verbose;
11372 0         0 _upgrade_to_float(0);
11373 0         0 return Math::BigFloat::bpi($digits+10)->round($digits);
11374             }
11375              
11376             ################################################################################
11377              
11378             sub forprimes {
11379 878     878 0 91043 my($sub, $beg, $end) = @_;
11380 878 100       1922 if (defined $end) { validate_integer_nonneg($beg); }
  863         1890  
11381 15         48 else { ($beg,$end) = (2, $beg); }
11382 878         2426 validate_integer_nonneg($end);
11383 878 50       1947 $beg = 2 if $beg < 2;
11384              
11385 878         3018 my $oldforexit = Math::Prime::Util::_start_for_loop();
11386             {
11387 878         1625 my $pp;
  878         1237  
11388 878         2302 local *_ = \$pp;
11389 878         2634 for (my $p = Mnext_prime($beg-1); $p <= $end; $p = Mnext_prime($p)) {
11390 3181         6039 $pp = $p;
11391 3181         7351 $sub->();
11392 3181 100       8700 last if Math::Prime::Util::_get_forexit();
11393             }
11394             }
11395 878         2567 Math::Prime::Util::_end_for_loop($oldforexit);
11396             }
11397              
11398              
11399             sub _forcomp_sub {
11400 4     4   18 my($what, $sub, $beg, $end) = @_;
11401 4 50       17 if (defined $end) { validate_integer_nonneg($beg); }
  4         32  
11402 0         0 else { ($beg,$end) = (0, $beg); }
11403 4         23 validate_integer_nonneg($end);
11404              
11405 4         9 my $cinc = 1;
11406 4 100       28 if ($what eq 'oddcomposites') {
11407 2 50       12 $beg = 9 if $beg < 9;
11408 2 50       119 $beg++ unless $beg % 2 == 1;
11409 2         397 $cinc = 2;
11410             } else {
11411 2 50       10 $beg = 4 if $beg < 4;
11412             }
11413 4 50 33     264 $end = tobigint(~0) if $end == ~0 && !ref($end);
11414 4         434 my $oldforexit = Math::Prime::Util::_start_for_loop();
11415             {
11416 4         11 my $pp;
  4         8  
11417 4         12 local *_ = \$pp;
11418 4         28 for (my $p = Mnext_prime($beg-1); $beg <= $end; $p = Mnext_prime($p)) {
11419 14   100     294 for ( ; $beg < $p && $beg <= $end ; $beg += $cinc ) {
11420 14         941 $pp = $beg;
11421 14         66 $sub->();
11422 14 50       304 last if Math::Prime::Util::_get_forexit();
11423             }
11424 14         1473 $beg += $cinc;
11425 14 50       1176 last if Math::Prime::Util::_get_forexit();
11426             }
11427             }
11428 4         135 Math::Prime::Util::_end_for_loop($oldforexit);
11429             }
11430             sub forcomposites {
11431 2     2 0 1427 _forcomp_sub('composites', @_);
11432             }
11433             sub foroddcomposites {
11434 2     2 0 902 _forcomp_sub('oddcomposites', @_);
11435             }
11436             sub forsemiprimes {
11437 3     3 0 1409 foralmostprimes($_[0], 2, $_[1], $_[2]);
11438             }
11439              
11440             sub _forfac_sub {
11441 15     15   58 my($sf, $sub, $beg, $end) = @_;
11442 15 100       45 if (defined $end) { validate_integer_nonneg($beg); }
  7         62  
11443 8         18 else { ($beg,$end) = (1, $beg); }
11444 15         175 validate_integer_nonneg($end);
11445 15 50       164 $beg = 1 if $beg < 1;
11446              
11447 15         1309 my $oldforexit = Math::Prime::Util::_start_for_loop();
11448             {
11449 15         33 my $pp;
  15         28  
11450 15         41 local *_ = \$pp;
11451 15         47 while ($beg <= $end) {
11452 174 100 100     3098 if (!$sf || Mis_square_free($beg)) {
11453 123         183 $pp = $beg;
11454 123 100       275 if ($sf == 2) {
11455 14         31 $sub->();
11456             } else {
11457 109         314 my @f = Mfactor($beg);
11458 109         320 $sub->(@f);
11459             }
11460 123 50       1204 last if Math::Prime::Util::_get_forexit();
11461             }
11462 174         4121 $beg++;
11463             }
11464             }
11465 15         1509 Math::Prime::Util::_end_for_loop($oldforexit);
11466             }
11467             sub forfactored {
11468 4     4 0 1604 _forfac_sub(0, @_);
11469             }
11470             sub forsquarefree {
11471 9     9 0 1395 _forfac_sub(1, @_);
11472             }
11473             sub forsquarefreeint {
11474 2     2 0 2057 _forfac_sub(2, @_);
11475             }
11476              
11477             sub fordivisors {
11478 17     17 0 1563 my($sub, $n) = @_;
11479 17         65 validate_integer_nonneg($n);
11480 17         69 my @divisors = Mdivisors($n);
11481 17         116 my $oldforexit = Math::Prime::Util::_start_for_loop();
11482             {
11483 17         30 my $pp;
  17         29  
11484 17         48 local *_ = \$pp;
11485 17         44 foreach my $d (@divisors) {
11486 80         124 $pp = $d;
11487 80         193 $sub->();
11488 80 50       367 last if Math::Prime::Util::_get_forexit();
11489             }
11490             }
11491 17         76 Math::Prime::Util::_end_for_loop($oldforexit);
11492             }
11493              
11494             sub forpart {
11495 1     1 0 5 my($sub, $n, $rhash) = @_;
11496 1         5 _forcompositions(1, $sub, $n, $rhash);
11497             }
11498             sub forcomp {
11499 1     1 0 16 my($sub, $n, $rhash) = @_;
11500 1         6 _forcompositions(0, $sub, $n, $rhash);
11501             }
11502             sub _forcompositions {
11503 2     2   8 my($ispart, $sub, $n, $rhash) = @_;
11504 2         19 validate_integer_nonneg($n);
11505 2         17 my($mina, $maxa, $minn, $maxn, $primeq) = (1,$n,1,$n,-1);
11506 2 100       17 if (defined $rhash) {
11507 1 50       7 croak "forpart second argument must be a hash reference"
11508             unless ref($rhash) eq 'HASH';
11509 1 50       6 if (defined $rhash->{amin}) {
11510 1         3 $mina = $rhash->{amin};
11511 1         5 validate_integer_nonneg($mina);
11512             }
11513 1 50       6 if (defined $rhash->{amax}) {
11514 0         0 $maxa = $rhash->{amax};
11515 0         0 validate_integer_nonneg($maxa);
11516             }
11517 1 50       5 $minn = $maxn = $rhash->{n} if defined $rhash->{n};
11518 1 50       32 $minn = $rhash->{nmin} if defined $rhash->{nmin};
11519 1 50       5 $maxn = $rhash->{nmax} if defined $rhash->{nmax};
11520 1         6 validate_integer_nonneg($minn);
11521 1         5 validate_integer_nonneg($maxn);
11522 1 50       5 if (defined $rhash->{prime}) {
11523 0         0 $primeq = $rhash->{prime};
11524 0         0 validate_integer_nonneg($primeq);
11525             }
11526 1 50       4 $mina = 1 if $mina < 1;
11527 1 50       5 $maxa = $n if $maxa > $n;
11528 1 50       6 $minn = 1 if $minn < 1;
11529 1 50       4 $maxn = $n if $maxn > $n;
11530 1 50 33     18 $primeq = 2 if $primeq != -1 && $primeq != 0;
11531             }
11532              
11533 2 50 33     10 $sub->() if $n == 0 && $minn <= 1;
11534 2 50 33     40 return if $n < $minn || $minn > $maxn || $mina > $maxa || $maxn <= 0 || $maxa <= 0;
      33        
      33        
      33        
11535              
11536 2         10 my $oldforexit = Math::Prime::Util::_start_for_loop();
11537 2         5 my ($x, $y, $r, $k);
11538 2         12 my @a = (0) x ($n);
11539 2         3 $k = 1;
11540 2         15 $a[0] = $mina - 1;
11541 2         6 $a[1] = $n - $mina + 1;
11542 2         34 while ($k != 0) {
11543 37         129 $x = $a[$k-1]+1;
11544 37         76 $y = $a[$k]-1;
11545 37         69 $k--;
11546 37 100       82 $r = $ispart ? $x : 1;
11547 37         99 while ($r <= $y) {
11548 35         68 $a[$k] = $x;
11549 35         87 $x = $r;
11550 35         63 $y -= $x;
11551 35         110 $k++;
11552             }
11553 37         79 $a[$k] = $x + $y;
11554             # Restrict size
11555 37         92 while ($k+1 > $maxn) {
11556 0         0 $a[$k-1] += $a[$k];
11557 0         0 $k--;
11558             }
11559 37 100       99 next if $k+1 < $minn;
11560             # Restrict values
11561 31 100 66     116 if ($mina > 1 || $maxa < $n) {
11562 26 50       58 last if $a[0] > $maxa;
11563 26 50       54 if ($ispart) {
11564 0 0       0 next if $a[$k] > $maxa;
11565             } else {
11566 26 100   64   149 next if Mvecany(sub{ $_ < $mina || $_ > $maxa }, @a[0..$k]);
  64 100       373  
11567             }
11568             }
11569 8 50 33 0   27 next if $primeq == 0 && Mvecany(sub{ Mis_prime($_) }, @a[0..$k]);
  0         0  
11570 8 50 33 0   24 next if $primeq == 2 && Mvecany(sub{ !Mis_prime($_) }, @a[0..$k]);
  0         0  
11571 8 50       31 last if Math::Prime::Util::_get_forexit();
11572 8         28 $sub->(@a[0 .. $k]);
11573             }
11574 2         12 Math::Prime::Util::_end_for_loop($oldforexit);
11575             }
11576             sub forcomb {
11577 1     1 0 15 my($sub, $n, $k) = @_;
11578 1         6 validate_integer_nonneg($n);
11579              
11580 1         3 my($begk, $endk);
11581 1 50       9 if (defined $k) {
11582 1         4 validate_integer_nonneg($k);
11583 1 50       5 return if $k > $n;
11584 1         4 $begk = $endk = $k;
11585             } else {
11586 0         0 $begk = 0;
11587 0         0 $endk = $n;
11588             }
11589              
11590 1         5 my $oldforexit = Math::Prime::Util::_start_for_loop();
11591 1         5 for my $k ($begk .. $endk) {
11592 1 50       5 if ($k == 0) {
11593 0         0 $sub->();
11594             } else {
11595 1         7 my @c = 0 .. $k-1;
11596 1         2 while (1) {
11597 3         13 $sub->(@c);
11598 3 50       20 last if Math::Prime::Util::_get_forexit();
11599 3 100       12 next if $c[-1]++ < $n-1;
11600 2         5 my $i = $k-2;
11601 2   100     18 $i-- while $i >= 0 && $c[$i] >= $n-($k-$i);
11602 2 100       9 last if $i < 0;
11603 1         21 $c[$i]++;
11604 1         4 while (++$i < $k) { $c[$i] = $c[$i-1] + 1; }
  1         18  
11605             }
11606             }
11607 1 50       36 last if Math::Prime::Util::_get_forexit();
11608             }
11609 1         4 Math::Prime::Util::_end_for_loop($oldforexit);
11610             }
11611             sub _forperm {
11612 2     2   8 my($sub, $n, $all_perm) = @_;
11613 2 50       11 if ($n <= 1) {
11614 0         0 my $oldforexit = Math::Prime::Util::_start_for_loop();
11615 0 0       0 if ($n == 0) { $sub->(); } else { $sub->(0); }
  0         0  
  0         0  
11616 0         0 Math::Prime::Util::_end_for_loop($oldforexit);
11617 0         0 return;
11618             }
11619 2         12 my $k = $n;
11620 2         10 my @c = reverse 0 .. $k-1;
11621 2         6 my $inc = 0;
11622 2         5 my $send = 1;
11623 2         44 my $oldforexit = Math::Prime::Util::_start_for_loop();
11624 2         19 while (1) {
11625 30 100       70 if (!$all_perm) { # Derangements via simple filtering.
11626 24         37 $send = 1;
11627 24         46 for my $p (0 .. $#c) {
11628 67 100       164 if ($c[$p] == $k-$p-1) {
11629 15         21 $send = 0;
11630 15         30 last;
11631             }
11632             }
11633             }
11634 30 100       83 if ($send) {
11635 15         49 $sub->(reverse @c);
11636 15 50       78 last if Math::Prime::Util::_get_forexit();
11637             }
11638 30 100       66 if (++$inc & 1) {
11639 15         37 @c[0,1] = @c[1,0];
11640 15         28 next;
11641             }
11642 15         29 my $j = 2;
11643 15   100     71 $j++ while $j < $k && $c[$j] > $c[$j-1];
11644 15 100       36 last if $j >= $k;
11645 13         25 my $m = 0;
11646 13         67 $m++ while $c[$j] > $c[$m];
11647 13         32 @c[$j,$m] = @c[$m,$j];
11648 13         47 @c[0..$j-1] = reverse @c[0..$j-1];
11649             }
11650 2         19 Math::Prime::Util::_end_for_loop($oldforexit);
11651             }
11652             sub forperm {
11653 1     1 0 6 my($sub, $n, $k) = @_;
11654 1         7 validate_integer_nonneg($n);
11655 1 50       5 croak "Too many arguments for forperm" if defined $k;
11656 1         32 _forperm($sub, $n, 1);
11657             }
11658             sub forderange {
11659 1     1 0 3 my($sub, $n, $k) = @_;
11660 1         5 validate_integer_nonneg($n);
11661 1 50       4 croak "Too many arguments for forderange" if defined $k;
11662 1 50       4 return if $n == 1;
11663 1         4 _forperm($sub, $n, 0);
11664             }
11665              
11666             sub _multiset_permutations {
11667 78     78   154 my($sub, $prefix, $ar, $sum) = @_;
11668              
11669 78 100       166 return if $sum == 0;
11670              
11671             # Remove any values with 0 occurances
11672 77         140 my @n = grep { $_->[1] > 0 } @$ar;
  238         536  
11673              
11674 77 50       186 if ($sum == 1) { # A single value
    100          
11675 0         0 $sub->(@$prefix, $n[0]->[0]);
11676             } elsif ($sum == 2) { # Optimize the leaf case
11677 51         110 my($n0,$n1) = map { $_->[0] } @n;
  97         220  
11678 51 100       111 if (@n == 1) {
11679 5         15 $sub->(@$prefix, $n0, $n0);
11680             } else {
11681 46         136 $sub->(@$prefix, $n0, $n1);
11682 46 100       325 $sub->(@$prefix, $n1, $n0) unless Math::Prime::Util::_get_forexit();
11683             }
11684             } elsif (0 && $sum == scalar(@n)) { # All entries have 1 occurance
11685             # TODO: Figure out a way to use this safely. We need to capture any
11686             # lastfor that was seen in the forperm.
11687             my @i = map { $_->[0] } @n;
11688 0     0   0 Math::Prime::Util::forperm(sub { $sub->(@$prefix, @i[@_]) }, 1+$#i);
11689             } else { # Recurse over each leading value
11690 26         54 for my $v (@n) {
11691 73         124 $v->[1]--;
11692 73         136 push @$prefix, $v->[0];
11693 77     77   4983435 no warnings 'recursion';
  77         305  
  77         138116  
11694 73         212 _multiset_permutations($sub, $prefix, \@n, $sum-1);
11695 73         296 pop @$prefix;
11696 73         147 $v->[1]++;
11697 73 100       216 last if Math::Prime::Util::_get_forexit();
11698             }
11699             }
11700             }
11701              
11702             sub numtoperm {
11703 1     1 0 12 my($n,$k) = @_;
11704 1         7 validate_integer_nonneg($n);
11705 1         5 validate_integer($k);
11706 1 50       5 return () if $n == 0;
11707 1 50       4 return (0) if $n == 1;
11708 1         8 my $f = Mfactorial($n-1);
11709 1 50 33     11 $k %= Mmulint($f,$n) if $k < 0 || int($k/$f) >= $n;
11710 1         4 my @S = map { $_ } 0 .. $n-1;
  11         21  
11711 1         16 my @V;
11712 1         7 while ($n-- > 0) {
11713 11         21 my $i = int($k/$f);
11714 11         52 push @V, splice(@S,$i,1);
11715 11 100       24 last if $n == 0;
11716 10         15 $k -= $i*$f;
11717 10         24 $f /= $n;
11718             }
11719 1         14 @V;
11720             }
11721              
11722             sub permtonum {
11723 3     3 0 27652 my($A) = @_;
11724 3 50       49 croak "permtonum argument must be an array reference"
11725             unless ref($A) eq 'ARRAY';
11726 3         9 my $n = scalar(@$A);
11727 3 100       20 return 0 if $n == 0;
11728             {
11729 2         5 my %S;
  2         6  
11730 2         25 for my $v (@$A) {
11731             croak "permtonum invalid permutation array"
11732 37 50 33     308 if !defined $v || $v < 0 || $v >= $n || $S{$v}++;
      33        
      33        
11733             }
11734             }
11735 2         13 my $f = factorial($n-1);
11736 2         18 my $rank = 0;
11737 2         11 for my $i (0 .. $n-2) {
11738 35         15701 my $k = 0;
11739 35         127 for my $j ($i+1 .. $n-1) {
11740 380 100       1063 $k++ if $A->[$j] < $A->[$i];
11741             }
11742 35         266 $rank = Maddint($rank, Mmulint($k,$f));
11743 35         7067 $f /= $n-$i-1;
11744             }
11745 2         426 $rank;
11746             }
11747              
11748             sub randperm {
11749 4     4 0 695 my($n,$k) = @_;
11750 4         17 validate_integer_nonneg($n);
11751 4 50       13 if (defined $k) {
11752 4         22 validate_integer_nonneg($k);
11753             }
11754 4 50 33     21 $k = $n if !defined($k) || $k > $n;
11755 4 50       11 return () if $k == 0;
11756              
11757 4         17 my @S;
11758 4 100       39 if ("$k"/"$n" <= 0.30) {
11759 2         7 my %seen;
11760             my $v;
11761 2         7 for my $i (1 .. $k) {
11762 8         12 do { $v = Murandomm($n); } while $seen{$v}++;
  8         21  
11763 8         24 push @S,$v;
11764             }
11765             } else {
11766 2         10 @S = (0..$n-1);
11767 2         8 for my $i (0 .. $n-2) {
11768 14 100       57 last if $i >= $k;
11769 12         27 my $j = Murandomm($n-$i);
11770 12         42 @S[$i,$i+$j] = @S[$i+$j,$i];
11771             }
11772 2         11 $#S = $k-1;
11773             }
11774 4         41 return @S;
11775             }
11776              
11777             sub shuffle {
11778 1     1 0 23 my @S=@_;
11779             # Note: almost all the time is spent in urandomm.
11780 1         8 for (my $i = $#S; $i >= 1; $i--) {
11781 127         177 my $j = Murandomm($i+1);
11782 127         219 @S[$i,$j] = @S[$j,$i];
11783             }
11784 1         13 @S;
11785             }
11786              
11787             sub vecsample {
11788 1     1 0 4 my $k = shift;
11789 1 50 33     10 return () if $k == 0 || @_ == 0;
11790 1         3 my $R = $_[0];
11791 1   33     13 my $isarr = (@_ > 1 || !ref($R) || ref($R) ne 'ARRAY');
11792 1 50       4 my $len = $isarr ? scalar(@_) : scalar(@$R);
11793              
11794 1 50       3 $k = $len if $k > $len;
11795 1         5 my @I = ($len-1, 0 .. $len-2);
11796 1         14 my $j;
11797 1         2 my @O = map { $j = Murandomm(scalar(@I)); # random index from remaining
  4         8  
11798 4         6 @I[0,$j] = @I[$j,0]; # move to front
11799 4         7 shift @I; # take it off
11800             } 1 .. $k;
11801 1 50       9 return $isarr ? @_[@O] : @$R[@O];
11802             }
11803              
11804             ###############################################################################
11805              
11806             sub vecsort {
11807 62     62 0 16665 my(@s) = @_;
11808             # If we have a single array reference, unpack it.
11809 62 100 100     396 @s = @{$s[0]} if scalar(@s) == 1 && (ref($s[0]) || '') eq 'ARRAY';
  3   100     12  
11810              
11811             # Validate and convert everything into a native int or bigint
11812 62         366 validate_integer($_) for @s;
11813              
11814             # See https://github.com/perl/perl5/issues/12803 for various discussion.
11815             # Optimize to skip the sorting.
11816 62 100       2267 return scalar(@s) unless wantarray;
11817              
11818             # Before Perl 5.26, numerical sort used doubles (sigh).
11819 61 50       209 if ($] < 5.026) {
11820 0         0 @s = sort { 0+($a<=>$b) } @s; # Prevent sort from using built-in compare
  0         0  
11821             } else {
11822 61         458 @s = sort { $a<=>$b } @s;
  1232         12302  
11823             }
11824 61         2206 return @s;
11825             }
11826              
11827             # In-place sort.
11828             sub vecsorti {
11829 53     53 0 603 my($r) = @_;
11830 53 50 50     297 croak 'Not an array reference' unless (ref($r) || '') eq 'ARRAY';
11831 53         345 validate_integer($_) for @$r;
11832 53 50       1412 if ($] < 5.026) { @$r = sort { 0+($a<=>$b) } @$r; }
  0         0  
  0         0  
11833 53         306 else { @$r = sort { $a<=>$b } @$r; }
  444         10971  
11834 53         1695 return $r;
11835             }
11836              
11837             sub setbinop (&$;$) { ## no critic qw(ProhibitSubroutinePrototypes)
11838 6     6 0 6346 my($sub, $ra, $rb) = @_;
11839 6 50 50     40 croak 'Not a subroutine reference' unless (ref($sub) || '') eq 'CODE';
11840 6 50 50     29 croak 'Not an array reference' unless (ref($ra) || '') eq 'ARRAY';
11841 6 50       24 if (defined $rb) {
11842 6 50 50     41 croak 'Not an array reference' unless (ref($rb) || '') eq 'ARRAY';
11843             } else {
11844 0         0 $rb = $ra;
11845             }
11846              
11847 6         21 my $caller = caller();
11848 77     77   793 no strict 'refs'; ## no critic(strict)
  77         208  
  77         736200  
11849 6         29 local(*{$caller.'::a'}) = \my $a;
  6         33  
11850 6         16 local(*{$caller.'::b'}) = \my $b;
  6         20  
11851              
11852             # Typically faster and less memory to push them all instead of hashing here.
11853 6         19 my @set;
11854 6         19 for my $ia (@$ra) {
11855 16         331 for my $ib (@$rb) {
11856             # Set both here in case they modified $a in their function.
11857 43         383 $a = $ia;
11858 43         78 $b = $ib;
11859 43         87 push @set, $sub->();
11860             }
11861             }
11862 6         1415 Mtoset(@set);
11863             }
11864              
11865             sub sumset {
11866 12     12 0 17565 my($ra,$rb) = @_;
11867 12 50 50     71 croak 'Not an array reference' unless (ref($ra) || '') eq 'ARRAY';
11868 12 100       46 if (defined $rb) {
11869 11 50 50     46 croak 'Not an array reference' unless (ref($rb) || '') eq 'ARRAY';
11870             } else {
11871 1         8 $rb = $ra;
11872             }
11873 12 50 33     81 return [] if scalar(@$ra) == 0 || scalar(@$rb) == 0;
11874              
11875 12         69 validate_integer($_) for @$ra;
11876 12 100       47 if ($ra != $rb) { validate_integer($_) for @$rb; }
  11         62  
11877              
11878 12         33 my @set;
11879 12         30 for my $x (@$ra) {
11880 29         673 for my $y (@$rb) {
11881 74         1048 push @set, Maddint($x,$y);
11882             }
11883             }
11884 12         1854 Mtoset(@set);
11885             }
11886              
11887             sub vecuniq {
11888 3     3 0 10 my %seen = ();
11889 3         7 my $k;
11890             # Validation means about 1.4x slower.
11891             #my @T = @_; return grep { validate_integer($_) && not $seen{$k = $_}++; } @T;
11892             # We have decided to skip validation and not support undefined values.
11893 3         12 return grep { not $seen{$k = $_}++; } @_;
  14         74  
11894             }
11895              
11896             sub vecfreq {
11897 5     5 0 18202 my %count = ();
11898 5         15 my $countundef = 0;
11899 5         11 my $k;
11900 5         17 for (@_) {
11901 32 100       84 if (defined $_) { $count{$k = $_}++; } else { $countundef++; }
  30         85  
  2         3  
11902             }
11903 5 100       54 return wantarray ? %count : scalar(keys %count) if !$countundef;
    100          
11904 1 50       5 return 1 + scalar(keys %count) if !wantarray;
11905 1         3 undef $k;
11906 1         8 return (%count, (\$k => $countundef));
11907             }
11908              
11909             sub vecsingleton {
11910 5     5 0 53940 my %count = ();
11911 5         33 my ($countundef,$k) = (0);
11912             # Filter later duplicates during the count stage for a ~10% speedup.
11913             # Idea from List::MoreUtil.
11914 23 100       116 return grep { (defined $_ ? $count{$k=$_} : $countundef) == 1 }
11915 5 100       17 grep { ! (defined $_ ? $count{$k = $_}++ : $countundef++) }
  36         126  
11916             @_;
11917             }
11918              
11919             # SET/VEC generic.
11920              
11921             # Assume two (sorted,uniqed,validated) sets as input, merge $T into $S.
11922             sub _merge_sets_inplace {
11923 1     1   4 my($S,$T) = @_;
11924              
11925             # 1 Push set over to make room at the front.
11926 1         34 unshift @$S, (0) x scalar(@$T);
11927             # 2 walk the two arrays merging values
11928 1         4 my($it,$nt) = (0, scalar(@$T));
11929 1         3 my($is,$ns) = ($nt, scalar(@$S));
11930 1         3 my $i = 0;
11931 1   66     17 while ($it < $nt && $is < $ns) {
11932 95         120 my($SV,$TV) = ($S->[$is], $T->[$it]);
11933 95 100       95 if ($SV == $TV) { $S->[$i++] = $SV; $is++; $it++; }
  93 50       87  
  93         83  
  93         156  
11934 0         0 elsif ($SV < $TV) { $S->[$i++] = $SV; $is++; }
  0         0  
11935 2         4 else { $S->[$i++] = $TV; $it++; }
  2         4  
11936             }
11937             # 3 splice the remainder onto the end of the set
11938 1 50       6 if ($is < $ns) { # slide the last part over
    50          
11939 0         0 splice(@$S, $i, $is-$i);
11940             } elsif ($it < $nt) { # replace everything at the end with the new values
11941 1         25 splice(@$S, $i, @$S-$i, @{$T}[$it..$nt-1]);
  1         33  
11942             } else {
11943 0         0 $#$S = $i-1;
11944             }
11945 1         9 $S;
11946             }
11947             sub setunion {
11948 5     5 0 11335 my($ra,$rb) = @_;
11949 5 50 50     42 croak 'Not an array reference' unless (ref($ra) || '') eq 'ARRAY'
      50        
      33        
11950             && (ref($rb) || '') eq 'ARRAY';
11951             # return toset(@$ra,@$rb);
11952 5         9 my(%seen,$k);
11953 5         12 Mtoset(grep { not $seen{$k = $_}++ } @$ra,@$rb);
  28         273  
11954             }
11955             sub setintersect {
11956 9     9 0 16915 my($ra,$rb) = @_;
11957 9 50 50     90 croak 'Not an array reference' unless (ref($ra) || '') eq 'ARRAY'
      50        
      33        
11958             && (ref($rb) || '') eq 'ARRAY';
11959 9 100       33 ($ra,$rb) = ($rb,$ra) if scalar(@$ra) > scalar(@$rb); # Performance
11960 9 50       28 return [] if scalar(@$ra) == 0;
11961 9         17 my %ina;
11962 9         39 undef @ina{@$ra};
11963 9         129 Mtoset(grep { exists $ina{$_} } @$rb);
  26         255  
11964             }
11965             sub setminus {
11966 6     6 0 16027 my($ra,$rb) = @_;
11967 6 50 50     96 croak 'Not an array reference' unless (ref($ra) || '') eq 'ARRAY'
      50        
      33        
11968             && (ref($rb) || '') eq 'ARRAY';
11969 6 50       22 return $ra if scalar(@$rb) == 0;
11970 6         15 my %inb;
11971 6         27 undef @inb{@$rb};
11972 6         118 Mtoset(grep { !exists $inb{$_} } @$ra);
  19         191  
11973             }
11974             sub setdelta {
11975 5     5 0 17124 my($ra,$rb) = @_;
11976 5 50 50     57 croak 'Not an array reference' unless (ref($ra) || '') eq 'ARRAY'
      50        
      33        
11977             && (ref($rb) || '') eq 'ARRAY';
11978 5 50       20 return $ra if scalar(@$rb) == 0;
11979 5 50       13 return $rb if scalar(@$ra) == 0;
11980 5         13 my(%ina, %inb);
11981 5         113 undef @ina{@$ra};
11982 5         123 undef @inb{@$rb};
11983 5         123 my @s = grep { !exists $inb{$_} } @$ra;
  15         92  
11984 5         55 push @s, grep { !exists $ina{$_} } @$rb;
  13         88  
11985 5         157 Mtoset(@s);
11986             }
11987              
11988             # Can do setminus([$min..$max],\@L) albeit 2x slower
11989             sub _setcomplement {
11990 0     0   0 my($ra, $min, $max) = @_;
11991 0 0 0     0 croak 'Not an array reference' unless (ref($ra) || '') eq 'ARRAY';
11992 0         0 validate_integer($min);
11993 0         0 validate_integer($max);
11994 0         0 my %ina;
11995 0         0 $ina{$_} = undef for @$ra;
11996 0         0 my @s;
11997 0 0 0     0 if ((ref($min) && !ref($max)) || (!ref($min) && ref($max))) {
      0        
      0        
11998 0         0 while ($min <= $max) {
11999 0 0       0 push @s, $min unless exists $ina{$min};
12000 0         0 $min = Madd1int($min);
12001             }
12002             } else {
12003 0         0 while ($min <= $max) {
12004 0 0       0 push @s, $min unless exists $ina{$min};
12005 0         0 $min++;
12006             }
12007             }
12008 0         0 @s;
12009             }
12010              
12011             sub toset {
12012 442     442 0 25991 my(@list) = @_;
12013 442         1511 validate_integer($_) for @list;
12014 442 100       3000 return \@list if scalar(@list) <= 1;
12015 38         86 my($k,%seen);
12016 38         100 @list = grep { not $seen{$k = $_}++; } @list;
  192         1480  
12017 38         1150 Mvecsorti(\@list);
12018             }
12019              
12020             # Is the second set a subset of the first set?
12021             sub setcontains {
12022 18     18 0 16846 my $set = shift @_;
12023 18         46 my $iset;
12024 18 100 100     144 if (@_ == 1 && ref($_[0]) eq 'ARRAY') {
12025 7         14 $iset = $_[0];
12026             } else {
12027 11         76 $iset = Mtoset(@_);
12028             }
12029 18 50       120 return 1 if @$iset == 0;
12030 18 100 33     187 return 0 if @$set == 0 || @$iset > @$set || $iset->[-1] > $set->[-1] || $iset->[0] < $set->[0];
      66        
      100        
12031              
12032 12 100 33     1150 if (@$set <= 150 || (@$set <= 250 && @$iset > 2)) { # Linear search
      66        
12033 11         20 my $i = 0;
12034 11         35 for my $sv (@$set) {
12035 95 100       591 if ($sv >= $iset->[$i]) {
12036 13 100       348 return 0 if $sv > $iset->[$i];
12037 10 100       328 return 1 if $i == $#$iset;
12038 2         4 $i++;
12039             }
12040             }
12041 0         0 return 0;
12042             }
12043              
12044 1         3 my $newlo = 0;
12045             # The next value is probably in this range. Can save a lot of steps.
12046 1         9 my $range = Mcdivint(scalar(@$set),(scalar(@$iset)+1) >> 1);
12047 1         35 for my $v (@$iset) {
12048 4         11 my($lo,$hi) = ($newlo,$#$set);
12049 4 100 66     22 $hi = $lo + $range if $hi-$lo > $range && $set->[$lo+$range] >= $v;
12050 4         12 while ($lo < $hi) {
12051 32         77 my $mid = $lo + (($hi-$lo) >> 1);
12052 32 100       60 if ($set->[$mid] < $v) { $lo = $mid+1; }
  8         17  
12053 24         50 else { $hi = $mid; }
12054             }
12055 4 50       12 return 0 if $set->[$hi] != $v;
12056 4         12 $newlo = $hi+1;
12057             }
12058 1         33 1;
12059             }
12060              
12061             sub setcontainsany {
12062 2     2 0 10 my($set,@in) = @_;
12063 2         16 my $iset;
12064 2 50 33     19 if (@in == 1 && ref($in[0]) eq 'ARRAY') {
12065 2         6 $iset = $in[0];
12066             } else {
12067 0         0 $iset = \@in;
12068             }
12069             # For better performance, make iset the larger
12070 2 50       10 ($set,$iset) = ($iset,$set) if scalar(@$set) > scalar(@$iset);
12071 2 50       8 return 0 if @$set == 0;
12072              
12073 2         4 my %ina;
12074 2         12 undef @ina{@$set};
12075 2 100       6 for (@$iset) { return 1 if exists $ina{$_} }
  12         38  
12076 1         9 return 0;
12077             }
12078              
12079              
12080             sub _setinsert1 { # UNUSED
12081 0     0   0 my($rset, $v) = @_;
12082 0         0 validate_integer($v);
12083              
12084 0 0 0     0 if (scalar(@$rset) == 0 || $v > $rset->[-1]) {
    0          
    0          
12085 0         0 push @$rset, $v;
12086             } elsif ($v < $rset->[0]) {
12087 0         0 unshift @$rset, $v;
12088             } elsif (scalar(@$rset) > 1) {
12089 0         0 my($lo,$hi) = (0,$#$rset);
12090 0         0 while ($lo < $hi) {
12091 0         0 my $mid = $lo + (($hi-$lo) >> 1);
12092 0 0       0 if ($rset->[$mid] < $v) { $lo = $mid+1; }
  0         0  
12093 0         0 else { $hi = $mid; }
12094             }
12095 0 0       0 return 0 if $rset->[$hi] == $v;
12096 0 0 0     0 croak "internal too high" if $hi > 0 && $rset->[$hi-1] >= $v;
12097 0 0       0 croak "internal too low" if $rset->[$hi] <= $v;
12098 0         0 splice @$rset, $hi, 0, $v;
12099             } else {
12100 0         0 return 0; # Single element already in list.
12101             }
12102 0         0 1;
12103             }
12104              
12105             sub setinsert {
12106 390     390 0 3364 my($set, @in) = @_;
12107 390         550 my $iset;
12108 390 100 66     1669 if (@in == 1 && ref($in[0]) eq 'ARRAY') {
12109 2         28 $iset = $in[0];
12110             } else {
12111 388         1087 $iset = Mtoset(@in);
12112             }
12113 390 50       976 return 0 if @$iset == 0;
12114 390         689 my $setsize = scalar(@$set);
12115 390 100 100     1785 if ($setsize == 0 || $iset->[0] > $set->[-1]) {
    100          
    100          
12116 119         296 push @$set, @$iset;
12117             } elsif ($iset->[-1] < $set->[0]) {
12118 53         156 unshift @$set, @$iset;
12119             } elsif (@$iset > 400) {
12120             # $set is required to be in proper form as input.
12121             # @newset was run through toset() earlier, so it is in proper form.
12122             # Times from the 20x50k insert operation in xt/test-sets.
12123              
12124             # 17.09 In theory efficient, but too much redundant work
12125             #@$set = @{Msetunion($set,$iset)};
12126              
12127             # 12.48 Better but still ignores all input structure
12128             #@$set = @{Mtoset([@$set,@$iset])};
12129              
12130             # 6.04 toset inlined and with all unnecessary work removed
12131             #my($k,%seen);
12132             #@$set = grep { not $seen{$k=$_}++ } @$set,@$iset;
12133             #if ($] < 5.026) { @$set = sort { 0+($a<=>$b) } @$set; }
12134             #else { @$set = sort { $a<=>$b } @$set; }
12135              
12136             # 5.64 as above but assume $set has no duplicates
12137             #my($k,%seen);
12138             #undef @seen{@$set};
12139             #push @$set, grep { !exists $seen{$k=$_} } @$iset;
12140             #if ($] < 5.026) { @$set = sort { 0+($a<=>$b) } @$set; }
12141             #else { @$set = sort { $a<=>$b } @$set; }
12142              
12143             # 4.12 Merge two proper-form sets
12144 1         33 _merge_sets_inplace($set, $iset);
12145              
12146             } else {
12147             # 1. values in front and back.
12148 217         430 my($nbeg,$nend) = (0,0);
12149 217         393 my(@sbeg,@send);
12150 217   66     997 $nend++ while $nend < scalar(@$iset) && $iset->[-1 - $nend] > $set->[-1];
12151 217 100       449 @send = splice(@$iset,-$nend) if $nend > 0;
12152 217   33     903 $nbeg++ while $nbeg < scalar(@$iset) && $iset->[$nbeg] < $set->[0];
12153 217 50       503 @sbeg = splice(@$iset,0,$nbeg) if $nbeg > 0;
12154             # 2. values in the middle.
12155 217         382 my $start = 0;
12156 217         1039 my $range = Mcdivint(scalar(@$set),(scalar(@$iset)+2) >> 1);
12157 217         556 for my $v (@$iset) {
12158 219         519 my($lo,$hi) = ($start,$#$set);
12159 219 100 66     619 $hi = $lo + $range if $hi-$lo > $range && $set->[$lo+$range] >= $v;
12160 219         498 while ($lo < $hi) {
12161 353         689 my $mid = $lo + (($hi-$lo) >> 1);
12162 353 100       774 if ($set->[$mid] < $v) { $lo = $mid+1; }
  155         370  
12163 198         451 else { $hi = $mid; }
12164             }
12165 219 100       592 splice @$set, $hi, 0, $v if $set->[$hi] != $v;
12166 219         470 $start = $hi+1;
12167             }
12168             # 3. bulk insert the front and back values we saved earlier
12169 217 50       441 unshift @$set, @sbeg if @sbeg;
12170 217 100       546 push @$set, @send if @send;
12171             }
12172 390         1967 return scalar(@$set) - $setsize;
12173             }
12174              
12175             sub _setremove1 {
12176 2     2   6 my($rset, $v) = @_;
12177             #validate_integer($v);
12178              
12179 2 50 33     15 return 0 if scalar(@$rset) == 0 || $v > $rset->[-1] || $v < $rset->[0];
      33        
12180              
12181 2         8 my($lo,$hi) = (0,$#$rset);
12182 2         6 while ($lo < $hi) {
12183 6         13 my $mid = $lo + (($hi-$lo) >> 1);
12184 6 100       13 if ($rset->[$mid] < $v) { $lo = $mid+1; }
  2         6  
12185 4         9 else { $hi = $mid; }
12186             }
12187 2 100       9 return 0 if $rset->[$hi] != $v;
12188 1         5 splice @$rset, $hi, 1;
12189 1         5 1;
12190             }
12191              
12192             sub setremove {
12193 3     3 0 3142 my $set = shift;
12194 3         8 my $iset;
12195 3 100 66     53 if (@_ == 1 && ref($_[0]) eq 'ARRAY') {
12196 1         5 $iset = $_[0];
12197             } else {
12198 2         10 $iset = Mtoset(@_);
12199             }
12200 3         10 my $setsize = scalar(@$set);
12201 3 50 33     18 return 0 if $setsize == 0 || @$iset == 0;
12202              
12203 3         10 my($SMIN,$SMAX) = ($set->[0],$set->[-1]);
12204 3   33     20 pop @$iset while @$iset && $iset->[-1] > $SMAX;
12205 3   33     20 shift @$iset while @$iset && $iset->[0] < $SMIN;
12206              
12207             # Try to decide the most performant of the two methods.
12208 3 0       17 my $fitmin = $setsize < 170 ? 1 + ($setsize>=35) + int($setsize/30)
    50          
12209             : $setsize < 75000 ? int(2.7*sqrt($setsize)-28)
12210             : 700;
12211 3 100       23 if (@$iset <= $fitmin) {
12212 2         12 _setremove1($set,$_) for @$iset;
12213             } else {
12214 1         3 my(%remove, $k);
12215 1         9 $remove{$k=$_}=undef for @$iset;
12216 1         4 my $remsize = scalar(keys(%remove));
12217 1 50       4 return 0 if $remsize == 0;
12218 1         4 @$set = grep { !exists $remove{$k=$_} } @$set;
  7         19  
12219             }
12220 3         14 return $setsize - scalar(@$set);
12221             }
12222              
12223             sub _setinvert1 {
12224 4     4   10 my($rset, $v) = @_;
12225             # No validate here.
12226              
12227 4 50 33     30 if (scalar(@$rset) == 0 || $v > $rset->[-1]) {
    50          
12228 0         0 push @$rset, $v;
12229             } elsif ($v < $rset->[0]) {
12230 0         0 unshift @$rset, $v;
12231             } else {
12232 4         19 my($lo,$hi) = (0,$#$rset);
12233 4         14 while ($lo < $hi) {
12234 12         60 my $mid = $lo + (($hi-$lo) >> 1);
12235 12 100       25 if ($rset->[$mid] < $v) { $lo = $mid+1; }
  5         13  
12236 7         18 else { $hi = $mid; }
12237             }
12238 4 100       13 if ($rset->[$hi] == $v) {
12239 2         5 splice @$rset, $hi, 1;
12240 2         8 return -1;
12241             }
12242 2         10 splice @$rset, $hi, 0, $v;
12243             }
12244 2         6 1;
12245             }
12246              
12247             sub setinvert {
12248 3     3 0 3150 my($set, @in) = @_;
12249 3 50       14 return 0 if @in == 0;
12250 3         10 my $iset;
12251 3 100 66     21 if (@in == 1 && ref($in[0]) eq 'ARRAY') {
12252 1         4 $iset = $in[0];
12253             } else {
12254 2         8 $iset = Mtoset(@in);
12255             }
12256 3         11 my $setsize = scalar(@$set);
12257 3 50       22 if ($setsize == 0) {
12258 0         0 @$set = @$iset;
12259 0         0 return scalar(@$set);
12260             }
12261             # Like setinsert and setremove, we assume the input set is in set form.
12262              
12263 3 50       11 if (@$iset <= 100) {
12264 3         22 _setinvert1($set,$_) for @$iset;
12265             } else {
12266 0         0 my @S;
12267 0         0 for my $sv (@$set) {
12268 0   0     0 push @S, shift @$iset while @$iset && $iset->[0] < $sv;
12269 0 0 0     0 if (@$iset && $iset->[0] == $sv) {
12270 0         0 shift @$iset;
12271             } else {
12272 0         0 push @S, $sv;
12273             }
12274             }
12275 0         0 push @S, @$iset;
12276 0         0 @$set = @S;
12277             }
12278 3         14 return scalar(@$set) - $setsize;
12279             }
12280              
12281             # For these set_is_ functions, the inputs can be unordered but no duplicates.
12282              
12283             sub set_is_disjoint {
12284 4     4 0 17245 my($s,$t) = @_;
12285 4 50 50     48 croak 'Not an array reference' unless (ref($s) || '') eq 'ARRAY'
      50        
      33        
12286             && (ref($t) || '') eq 'ARRAY';
12287 4 100       22 ($s,$t) = ($t,$s) if scalar(@$s) > scalar(@$t);
12288 4 50 33     25 return 1 if @$s == 0 || @$t == 0;
12289 4         9 my($k,%ins);
12290 4         26 $ins{$k=$_}=undef for @$s;
12291 4 100       11 for my $v (@$t) { return 0 if exists $ins{$k=$v} }
  8         50  
12292 2         17 1;
12293             }
12294             sub set_is_equal {
12295 3     3 0 13449 my($s,$t) = @_;
12296 3 50 50     42 croak 'Not an array reference' unless (ref($s) || '') eq 'ARRAY'
      50        
      33        
12297             && (ref($t) || '') eq 'ARRAY';
12298 3 50       12 return 0 unless @$s == @$t;
12299 3         10 my %ins;
12300 3         21 $ins{$_} = 0 for @$s;
12301 3         9 for my $v (@$t) {
12302 8 100       34 return 0 unless exists $ins{$v};
12303 6         12 $ins{$v}++;
12304             }
12305 1 50       4 for (values %ins) { return 0 unless $_ }
  4         10  
12306 1         6 1;
12307             }
12308             sub set_is_subset {
12309 16     16 0 38600 my($s,$t) = @_;
12310 16 50 50     159 croak 'Not an array reference' unless (ref($s) || '') eq 'ARRAY'
      50        
      33        
12311             && (ref($t) || '') eq 'ARRAY';
12312 16 50       55 return 1 if @$t == 0;
12313 16 50       50 return 0 if @$s < @$t;
12314 16         60 my %ins;
12315 16         84 undef @ins{@$s};
12316 16 100       65 for my $v (@$t) { return 0 unless exists $ins{$v} }
  30         210  
12317 10         72 1;
12318             }
12319             sub set_is_proper_subset {
12320 6     6 0 19145 my($s,$t) = @_;
12321 6 50 50     73 croak 'Not an array reference' unless (ref($s) || '') eq 'ARRAY'
      50        
      33        
12322             && (ref($t) || '') eq 'ARRAY';
12323 6 100       52 return 0 if @$s <= @$t;
12324 4         17 set_is_subset($s,$t);
12325             }
12326             sub set_is_superset {
12327 5     5 0 22194 set_is_subset($_[1],$_[0]);
12328             }
12329             sub set_is_proper_superset {
12330 3     3 0 14284 set_is_proper_subset($_[1],$_[0]);
12331             }
12332             sub set_is_proper_intersection {
12333 4     4 0 10813 my($s,$t) = @_;
12334 4 50 50     42 croak 'Not an array reference' unless (ref($s) || '') eq 'ARRAY'
      50        
      33        
12335             && (ref($t) || '') eq 'ARRAY';
12336 4 50       18 my $minsize = (scalar(@$s) < scalar(@$t)) ? scalar(@$s) : scalar(@$t);
12337 4         8 my $intersize = scalar(@{Msetintersect($s,$t)});
  4         119  
12338 4 100 100     58 return ($intersize > 0 && $intersize < $minsize) ? 1 : 0;
12339             }
12340              
12341             sub is_sidon_set {
12342 4     4 0 5898 my($ra) = @_;
12343 4 50 50     26 croak 'Not an array reference' unless (ref($ra) || '') eq 'ARRAY';
12344              
12345 4         10 my %sums;
12346 4         7 my @S = @{Mtoset(@$ra)}; # Validated, sorted, deduped.
  4         22  
12347 4         18 while (@S) {
12348 16         129 my $x = pop @S;
12349 16 50       39 return 0 if $x < 0;
12350 16         36 for my $y ($x, @S) {
12351 49         787 my $s = Maddint($x, $y);
12352 49 100       1894 return 0 if exists $sums{$s};
12353 48         515 $sums{$s} = undef;
12354             }
12355             }
12356 3         102 1;
12357             }
12358              
12359             sub is_sumfree_set {
12360 4     4 0 6255 my($ra) = @_;
12361 4 50 50     27 croak 'Not an array reference' unless (ref($ra) || '') eq 'ARRAY';
12362              
12363 4         10 my %ina;
12364 4         10 my @S = @{Mtoset(@$ra)}; # Validated, sorted, deduped.
  4         24  
12365 4         29 $ina{$_}=undef for @S;
12366 4         14 while (@S) {
12367 12         26 my $x = pop @S;
12368 12         28 for my $y ($x, @S) {
12369 25 100       590 return 0 if exists $ina{Maddint($x,$y)};
12370             }
12371             }
12372 3         653 1;
12373             }
12374              
12375              
12376             ###############################################################################
12377              
12378             sub foralmostprimes {
12379 4     4 0 1440 my($sub, $k, $lo, $hi) = @_;
12380 4         32 validate_integer_nonneg($k);
12381 4 50       17 return if $k == 0;
12382 4 50       29 if (defined $hi) { validate_integer_nonneg($lo); }
  4         30  
12383 0         0 else { ($lo,$hi) = (1, $lo); }
12384 4         28 validate_integer_nonneg($hi);
12385              
12386 4         38 $lo = Mvecmax($lo, Mpowint(2, $k));
12387 4 50       18 return if $lo > $hi;
12388              
12389             #return Math::Prime::Util::forprimes($sub,$lo,$hi) if $k == 1;
12390              
12391 4         246 my $estcount = almost_prime_count_approx($k,$hi) - almost_prime_count_approx($k,$lo);
12392 4         19 my $nsegs = "$estcount" / 1e6;
12393 4         26 my $len = Madd1int(Msubint($hi,$lo));
12394 4 50       143 my $segsize = ($nsegs <= 1.1) ? $len : int("$len"/$nsegs);
12395 4 50       18 if ($segsize < 5*1e6) { $segsize = 5e6; }
  4         11  
12396             # warn " estcount $estcount nsegs $nsegs segsize $segsize\n";
12397              
12398 4         47 my $oldforexit = Math::Prime::Util::_start_for_loop();
12399 4         19 while ($lo <= $hi) {
12400 4         199 my $seghi = Mvecmin($hi, Maddint($lo,$segsize)-1);
12401 4         58 my $ap = Math::Prime::Util::almost_primes($k, $lo, $seghi);
12402             #my $ap = []; _genkap($lo, $seghi, $k, 1, 2, sub { push @$ap,$_[0]; });
12403             # warn " from $lo to $seghi found ",scalar(@$ap), " $k-almost-primes\n";
12404             {
12405 4         29 my $pp;
  4         10  
12406 4         23 local *_ = \$pp;
12407 4         13 for my $kap (@$ap) {
12408 22         57 $pp = $kap;
12409 22         97 $sub->();
12410 22 50       229 last if Math::Prime::Util::_get_forexit();
12411             }
12412             }
12413 4         30 $lo = Madd1int($seghi);
12414 4 50       813 last if Math::Prime::Util::_get_forexit();
12415             }
12416 4         185 Math::Prime::Util::_end_for_loop($oldforexit);
12417             }
12418              
12419              
12420              
12421             ###############################################################################
12422             # Random numbers
12423             ###############################################################################
12424              
12425             # PPFE: irand irand64 drand random_bytes csrand srand _is_csprng_well_seeded
12426             sub urandomb {
12427 27     27 0 108 my($n) = @_;
12428 27 50       133 return 0 if $n <= 0;
12429 27 50       114 return ( Math::Prime::Util::irand() >> (32-$n) ) if $n <= 32;
12430 27 50       87 return ( Math::Prime::Util::irand64() >> (64-$n) ) if MPU_MAXBITS >= 64 && $n <= 64;
12431 27         365 my $bytes = Math::Prime::Util::random_bytes(($n+7)>>3);
12432 27         283 return _frombinary( substr(unpack("B*",$bytes),0,$n) );
12433             }
12434             sub urandomm {
12435 179     179 0 1862 my($n) = @_;
12436             # validate_integer_nonneg($n);
12437             return reftyped($_[0], Math::Prime::Util::GMP::urandomm($n))
12438 179 50       395 if $Math::Prime::Util::_GMPfunc{"urandomm"};
12439 179 100       342 return 0 if $n <= 1;
12440 178         6431 my $r;
12441 178 100       325 if ($n <= 4294967295) {
    50          
12442 152         201 my $rmin = (4294967295 - ($n-1)) % $n;
12443 152         158 do { $r = Math::Prime::Util::irand(); } while $r < $rmin;
  152         277  
12444             } elsif (!ref($n)) {
12445 0         0 my $rmin = (~0 - ($n-1)) % $n;
12446 0         0 do { $r = Math::Prime::Util::irand64(); } while $r < $rmin;
  0         0  
12447             } else {
12448             # TODO: verify and try to optimize this
12449 26         6384 my $bytes = 1 + length(todigitstring($n,16));
12450 26         2058 my $rmax = Msub1int(Mpowint(2,$bytes*8));
12451 26         6638 my $overflow = $rmax - ($rmax % $n);
12452 26         15559 do { $r = Murandomb($bytes*8); } while $r >= $overflow;
  26         2093  
12453             }
12454 178         29656 return $r % $n;
12455             }
12456              
12457             sub random_prime {
12458 2     2 0 23677 my($low, $high) = @_;
12459 2 50       11 if (scalar(@_) == 1) { ($low,$high) = (2,$low); }
  0         0  
12460 2         11 else { validate_integer_nonneg($low); }
12461 2         43 validate_integer_nonneg($high);
12462              
12463             return reftyped($_[0], Math::Prime::Util::GMP::random_prime($low, $high))
12464 2 50       32 if $Math::Prime::Util::_GMPfunc{"random_prime"};
12465              
12466 2         850 require Math::Prime::Util::RandomPrimes;
12467 2         12 return Math::Prime::Util::RandomPrimes::random_prime($low,$high);
12468             }
12469              
12470             sub random_ndigit_prime {
12471 3     3 0 964 my($digits) = @_;
12472 3         23 validate_integer_nonneg($digits);
12473 3 50       111 croak "random_ndigit_prime digits must be >= 1" unless $digits >= 1;
12474             return reftyped($_[0], Math::Prime::Util::GMP::random_ndigit_prime($digits))
12475 3 50 33     18 if $Math::Prime::Util::_GMPfunc{"random_ndigit_prime"} && !getconfig()->{'nobigint'};
12476 3         1235 require Math::Prime::Util::RandomPrimes;
12477 3         23 return Math::Prime::Util::RandomPrimes::random_ndigit_prime($digits);
12478             }
12479             sub random_nbit_prime {
12480 9     9 0 71693 my($bits) = @_;
12481 9         52 validate_integer_nonneg($bits);
12482 9 50       249 croak "random_nbit_prime bits must be >= 2" unless $bits >= 2;
12483             return reftyped($_[0], Math::Prime::Util::GMP::random_nbit_prime($bits))
12484 9 50       38 if $Math::Prime::Util::_GMPfunc{"random_nbit_prime"};
12485 9         64 require Math::Prime::Util::RandomPrimes;
12486 9         46 return Math::Prime::Util::RandomPrimes::random_nbit_prime($bits);
12487             }
12488             sub random_safe_prime {
12489 2     2 0 9597 my($bits) = @_;
12490 2         16 validate_integer_nonneg($bits);
12491 2 50       139 croak "random_safe_prime bits must be >= 3" unless $bits >= 3;
12492             return reftyped($_[0], eval "Math::Prime::Util::GMP::random_safe_prime($bits)") ## no critic qw(ProhibitStringyEval)
12493 2 50       10 if $Math::Prime::Util::_GMPfunc{"random_safe_prime"};
12494 2         16 require Math::Prime::Util::RandomPrimes;
12495 2         14 return Math::Prime::Util::RandomPrimes::random_safe_prime($bits);
12496             }
12497             sub random_strong_prime {
12498 1     1 0 172 my($bits) = @_;
12499 1         10 validate_integer_nonneg($bits);
12500 1 50       99 croak "random_strong_prime bits must be >= 128" unless $bits >= 128;
12501             return reftyped($_[0], eval "Math::Prime::Util::GMP::random_strong_prime($bits)") ## no critic qw(ProhibitStringyEval)
12502 1 50       6 if $Math::Prime::Util::_GMPfunc{"random_strong_prime"};
12503 1         9 require Math::Prime::Util::RandomPrimes;
12504 1         7 return Math::Prime::Util::RandomPrimes::random_strong_prime($bits);
12505             }
12506              
12507             sub random_proven_prime {
12508 0     0 0 0 random_maurer_prime(@_);
12509             }
12510              
12511             sub random_maurer_prime {
12512 1     1 0 111 my($bits) = @_;
12513 1         5 validate_integer_nonneg($bits);
12514 1 50       53 croak "random_maurer_prime bits must be >= 2" unless $bits >= 2;
12515              
12516             return reftyped($_[0], Math::Prime::Util::GMP::random_maurer_prime($bits))
12517 1 50       4 if $Math::Prime::Util::_GMPfunc{"random_maurer_prime"};
12518              
12519 1         6 require Math::Prime::Util::RandomPrimes;
12520 1         8 my ($n, $cert) = Math::Prime::Util::RandomPrimes::random_maurer_prime_with_cert($bits);
12521 1 50       7 croak "maurer prime $n failed certificate verification!"
12522             unless Math::Prime::Util::verify_prime($cert);
12523              
12524 1         12 return $n;
12525             }
12526              
12527             sub random_shawe_taylor_prime {
12528 0     0 0 0 my($bits) = @_;
12529 0         0 validate_integer_nonneg($bits);
12530 0 0       0 croak "random_shawe_taylor_prime bits must be >= 2" unless $bits >= 2;
12531              
12532             return reftyped($_[0], Math::Prime::Util::GMP::random_shawe_taylor_prime($bits))
12533 0 0       0 if $Math::Prime::Util::_GMPfunc{"random_shawe_taylor_prime"};
12534              
12535 0         0 require Math::Prime::Util::RandomPrimes;
12536 0         0 my ($n, $cert) = Math::Prime::Util::RandomPrimes::random_shawe_taylor_prime_with_cert($bits);
12537 0 0       0 croak "shawe-taylor prime $n failed certificate verification!"
12538             unless Math::Prime::Util::verify_prime($cert);
12539              
12540 0         0 return $n;
12541             }
12542              
12543             sub miller_rabin_random {
12544 3     3 0 2192 my($n, $k, $seed) = @_;
12545 3         36 validate_integer($n);
12546 3 50       134 if (scalar(@_) == 1 ) { $k = 1; } else { validate_integer_nonneg($k); }
  0         0  
  3         17  
12547              
12548 3 50       141 return 0 if $n < 2;
12549 3 50       410 return 1 if $k <= 0;
12550              
12551 3 50       17 if ($Math::Prime::Util::_GMPfunc{"miller_rabin_random"}) {
12552 0 0       0 return Math::Prime::Util::GMP::miller_rabin_random($n, $k, $seed) if defined $seed;
12553 0         0 return Math::Prime::Util::GMP::miller_rabin_random($n, $k);
12554             }
12555              
12556             # getconfig()->{'assume_rh'}) ==> 2*log(n)^2
12557 3 50       14 if ($k >= int(3*$n/4) ) {
12558 0         0 for (2 .. int(3*$n/4)+2) {
12559 0 0       0 return 0 unless Math::Prime::Util::is_strong_pseudoprime($n, $_);
12560             }
12561 0         0 return 1;
12562             }
12563 3         2026 my $brange = $n-2;
12564 3 100       691 return 0 unless Math::Prime::Util::is_strong_pseudoprime($n, Murandomm($brange)+2 );
12565 1         11 $k--;
12566 1         5 while ($k > 0) {
12567 1 50       9 my $nbases = ($k >= 20) ? 20 : $k;
12568 1 50       6 return 0 unless is_strong_pseudoprime($n, map { Murandomm($brange)+2 } 1 .. $nbases);
  19         13238  
12569 1         32 $k -= $nbases;
12570             }
12571 1         12 1;
12572             }
12573              
12574             sub random_semiprime {
12575 1     1 0 17355 my($b) = @_;
12576 1         7 validate_integer_nonneg($b);
12577 1 50       5 croak "random_semiprime bits must be >= 4" unless $b >= 4;
12578              
12579 1         3 my $n;
12580 1         80 my $min = Mpowint(2,$b-1);
12581 1         272 my $max = $min + ($min - 1);
12582 1         656 my $L = $b >> 1;
12583 1         4 my $N = $b - $L;
12584 1   66     3 do {
12585 3         631 $n = Mmulint(random_nbit_prime($L), random_nbit_prime($N));
12586             } while $n < $min || $n > $max;
12587 1         359 $n;
12588             }
12589              
12590             sub random_unrestricted_semiprime {
12591 1     1 0 21 my($b) = @_;
12592 1         6 validate_integer_nonneg($b);
12593 1 50       5 croak "random_unrestricted_semiprime bits must be >= 3" unless $b >= 3;
12594              
12595 1         3 my $n;
12596 1         70 my $min = Mpowint(2,$b-1);
12597 1         255 my $max = Maddint($min, $min - 1);
12598              
12599 1 50       298 if ($b <= MPU_MAXBITS) {
12600 0         0 do {
12601 0         0 $n = $min + Murandomb($b-1);
12602             } while !Mis_semiprime($n);
12603             } else {
12604             # Try to get probabilities right for small divisors
12605 1         95 my %M = (
12606             2 => 1.91218397452243,
12607             3 => 1.33954826555021,
12608             5 => 0.854756717114822,
12609             7 => 0.635492301836862,
12610             11 => 0.426616792046787,
12611             13 => 0.368193843118344,
12612             17 => 0.290512701603111,
12613             19 => 0.263359264658156,
12614             23 => 0.222406328935102,
12615             29 => 0.181229250520242,
12616             31 => 0.170874199059434,
12617             37 => 0.146112155735473,
12618             41 => 0.133427839963585,
12619             43 => 0.127929010905662,
12620             47 => 0.118254609086782,
12621             53 => 0.106316418106489,
12622             59 => 0.0966989675438643,
12623             61 => 0.0938833658008547,
12624             67 => 0.0864151823151671,
12625             71 => 0.0820822953188297,
12626             73 => 0.0800964416340746,
12627             79 => 0.0747060914833344,
12628             83 => 0.0714973706654851,
12629             89 => 0.0672115468436284,
12630             97 => 0.0622818892486191,
12631             101 => 0.0600855891549939,
12632             103 => 0.0590613570015407,
12633             107 => 0.0570921135626976,
12634             109 => 0.0561691667641485,
12635             113 => 0.0544330141081874,
12636             127 => 0.0490620204315701,
12637             );
12638 1         4 my ($p,$r);
12639 1         5 $r = Math::Prime::Util::drand();
12640 1         5 for my $prime (2..113,127) {
12641 113 100       275 next unless defined $M{$prime};
12642 31         63 my $PR = $M{$prime} / $b + 0.19556 / $prime;
12643 31 50       64 if ($r <= $PR) {
12644 0         0 $p = $prime;
12645 0         0 last;
12646             }
12647 31         87 $r -= $PR;
12648             }
12649 1 50       5 if (!defined $p) {
12650             # Idea from Charles Greathouse IV, 2010. The distribution is right
12651             # at the high level (small primes weighted more and not far off what
12652             # we get with the uniform selection), but there is a noticeable skew
12653             # toward primes with a large gap after them. For instance 3 ends up
12654             # being weighted as much as 2, and 7 more than 5.
12655             #
12656             # Since we handled small divisors earlier, this is less bothersome.
12657 1         2 my $M = 0.26149721284764278375542683860869585905;
12658 1         5 my $weight = $M + log($b * log(2)/2);
12659 1         2 my $minr = log(log(131));
12660 1         3 do {
12661 1         8 $r = Math::Prime::Util::drand($weight) - $M;
12662             } while $r < $minr;
12663 1         3 my $a;
12664 1 50       5 if ($r <= 3.54) {
    0          
12665             # result under 10^15, can do directly
12666 1         5 $a = int( exp(exp($r)) + 0.5 );
12667             } elsif ($Math::Prime::Util::_GMPfunc{"expreal"}) {
12668             # Use our fast arbitrary precision expreal.
12669 0 0       0 my $digits = $r < 4.45 ? 40 : int(exp($r)/2.2 + 2); # overestimate
12670 0         0 my $re = Math::Prime::Util::GMP::expreal($r,$digits);
12671 0         0 $a = Math::Prime::Util::GMP::expreal($re,$digits);
12672 0         0 $a = Mtoint($a); #_upgrade_to_float($a)->as_int;
12673             } else {
12674             # exp(x)=exp(x/n)^n
12675             # We could use Math::BigFloat but it's sooooooooooo slow.
12676 0         0 my $re = exp($r);
12677 0         0 my $redd = 1+int($re/34.5);
12678 0         0 $a = Mpowint(int(exp($re/$redd)+0.5), $redd);
12679             }
12680 1 50       14 $p = $a < 2 ? 2 : Mprev_prime($a+1);
12681             }
12682 1         9 my $ranmin = Mcdivint($min, $p);
12683 1         6 my $ranmax = Mdivint($max, $p);
12684 1         7 my $q = random_prime($ranmin, $ranmax);
12685 1         93 $n = Mmulint($p,$q);
12686             }
12687 1         254 $n;
12688             }
12689              
12690             sub random_factored_integer {
12691 0     0 0 0 my($n) = @_;
12692 0         0 validate_integer_positive($n);
12693              
12694 0         0 while (1) {
12695 0         0 my @S = ($n);
12696             # make s_i chain
12697 0         0 push @S, 1 + Murandomm($S[-1]) while $S[-1] > 1;
12698             # first is n, last is 1
12699 0         0 @S = grep { Mis_prime($_) } @S[1 .. $#S-1];
  0         0  
12700 0         0 my $r = Mvecprod(@S);
12701 0 0 0     0 return ($r, [@S]) if $r <= $n && (1+Murandomm($n)) <= $r;
12702             }
12703             }
12704              
12705             ################################################################################
12706              
12707             sub prime_precalc {
12708 2     2 0 22 my($n) = @_;
12709 2 50       9 croak "Parameter '$n' must be a non-negative integer" unless _is_nonneg_int($n);
12710 2         10 _expand_prime_cache($n);
12711             }
12712             my @_free_subs;
12713             sub _register_free_sub {
12714 308     308   798 push @_free_subs, shift;
12715             }
12716             sub prime_memfree {
12717             # Make the internal callbacks that reset cached data.
12718 11     11 0 116 $_->() for @_free_subs;
12719             # Call GMP's free if we have it
12720 11 50 33     70 eval { Math::Prime::Util::GMP::_GMP_memfree(); }
  0         0  
12721             if defined $Math::Prime::Util::GMP::VERSION && $Math::Prime::Util::GMP::VERSION >= 0.49;
12722             }
12723 80     80   302 sub _get_prime_cache_size { $_precalc_size }
12724 0     0     sub _prime_memfreeall { prime_memfree; }
12725              
12726             1;
12727              
12728             __END__