The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Math::Prime::Util::PP - Pure Perl version of Math::Prime::Util

VERSION

Version 0.29

SYNOPSIS

The functionality is basically identical to Math::Prime::Util, as this module is just the Pure Perl implementation.

  # Normally you would just import the functions you are using.
  # Nothing is exported by default.
  use Math::Prime::Util ':all';


  # Get a big array reference of many primes
  my $aref = primes( 100_000_000 );

  # All the primes between 5k and 10k inclusive
  my $aref = primes( 5_000, 10_000 );

  # If you want them in an array instead
  my @primes = @{primes( 500 )};


  # is_prime returns 0 for composite, 2 for prime
  say "$n is prime"  if is_prime($n);

  # is_prob_prime returns 0 for composite, 2 for prime, and 1 for maybe prime
  say "$n is ", qw(composite maybe_prime? prime)[is_prob_prime($n)];


  # step to the next prime (returns 0 if the next one is more than ~0)
  $n = next_prime($n);

  # step back (returns 0 if given input less than 2)
  $n = prev_prime($n);


  # Return Pi(n) -- the number of primes E<lt>= n.
  $primepi = prime_count( 1_000_000 );
  $primepi = prime_count( 10**14, 10**14+1000 );  # also does ranges

  # Quickly return an approximation to Pi(n)
  my $approx_number_of_primes = prime_count_approx( 10**17 );

  # Lower and upper bounds.  lower <= Pi(n) <= upper for all n
  die unless prime_count_lower($n) <= prime_count($n);
  die unless prime_count_upper($n) >= prime_count($n);


  # Return p_n, the nth prime
  say "The ten thousandth prime is ", nth_prime(10_000);

  # Return a quick approximation to the nth prime
  say "The one trillionth prime is ~ ", nth_prime_approx(10**12);

  # Lower and upper bounds.   lower <= nth_prime(n) <= upper for all n
  die unless nth_prime_lower($n) <= nth_prime($n);
  die unless nth_prime_upper($n) >= nth_prime($n);


  # Get the prime factors of a number
  @prime_factors = factor( $n );


  # Precalculate a sieve, possibly speeding up later work.
  prime_precalc( 1_000_000_000 );

  # Free any memory used by the module.
  prime_memfree;

  # Alternate way to free.  When this leaves scope, memory is freed.
  my $mf = Math::Prime::Util::MemFree->new;


  # Random primes
  my $small_prime = random_prime(1000);      # random prime <= limit
  my $rand_prime = random_prime(100, 10000); # random prime within a range
  my $rand_prime = random_ndigit_prime(6);   # random 6-digit prime

DESCRIPTION

Pure Perl implementations of prime number utilities that are normally handled with XS or GMP. Having the Perl implementations (1) provides examples, (2) allows the functions to run even if XS isn't available, and (3) gives big number support if Math::Prime::Util::GMP isn't available. This is a subset of Math::Prime::Util's functionality.

All routines should work with native integers or multi-precision numbers. To enable big numbers, use bigint or bignum:

    use bigint;
    say prime_count_approx(1000000000000000000000000)'
    # says 18435599767347543283712

This is still experimental, and some functions will be very slow. The Math::Prime::Util::GMP module has much faster versions of many of these functions. Alternately, Math::Pari has a lot of these types of functions.

FUNCTIONS

is_prime

  print "$n is prime" if is_prime($n);

Returns 2 if the number is prime, 0 if not. For numbers larger than 2^64 it will return 0 for composite and 1 for probably prime, using an extra-strong BPSW test. Also note there are probabilistic prime testing functions available.

primes

Returns all the primes between the lower and upper limits (inclusive), with a lower limit of 2 if none is given.

An array reference is returned (with large lists this is much faster and uses less memory than returning an array directly).

  my $aref1 = primes( 1_000_000 );
  my $aref2 = primes( 1_000_000_000_000, 1_000_000_001_000 );

  my @primes = @{ primes( 500 ) };

  print "$_\n" for (@{primes( 20, 100 )});

Sieving will be done if required. The algorithm used will depend on the range and whether a sieve result already exists. Possibilities include trial division (for ranges with only one expected prime), a Sieve of Eratosthenes using wheel factorization, or a segmented sieve.

next_prime

  $n = next_prime($n);

Returns the next prime greater than the input number. If the input is not a bigint, then 0 is returned if the next prime is larger than a native integer type (the last representable primes being 4,294,967,291 in 32-bit Perl and 18,446,744,073,709,551,557 in 64-bit).

prev_prime

  $n = prev_prime($n);

Returns the prime smaller than the input number. 0 is returned if the input is 2 or lower.

prime_count

  my $primepi = prime_count( 1_000 );
  my $pirange = prime_count( 1_000, 10_000 );

Returns the Prime Count function Pi(n), also called primepi in some math packages. When given two arguments, it returns the inclusive count of primes between the ranges (e.g. (13,17) returns 2, 14,17 and 13,16 return 1, and 14,16 returns 0).

The Lehmer method is used for large values, which greatly speeds up results.

nth_prime

  say "The ten thousandth prime is ", nth_prime(10_000);

Returns the prime that lies in index n in the array of prime numbers. Put another way, this returns the smallest p such that Pi(p) >= n.

The Lehmer prime count is used to speed up results for large inputs, but both methods take quite a bit of time and space. Think abut whether a bound or approximation would be acceptable instead.

is_pseudoprime

Takes a positive number n and a base a as input, and returns 1 if n is a probable prime to base a. This is the simple Fermat primality test. Removing primes, given base 2 this produces the sequence OEIS A001567.

is_strong_pseudoprime

miller_rabin

  my $maybe_prime = is_strong_pseudoprime($n, 2);
  my $probably_prime = is_strong_pseudoprime($n, 2, 3, 5, 7, 11, 13, 17);

Takes a positive number as input and one or more bases. The bases must be greater than 1. Returns 1 if the input is a strong probable prime to all of the bases, and 0 if not.

If 0 is returned, then the number really is a composite. If 1 is returned, then it is either a prime or a strong pseudoprime to all the given bases. Given enough distinct bases, the chances become very, very strong that the number is actually prime.

This is usually used in combination with other tests to make either stronger tests (e.g. the strong BPSW test) or deterministic results for numbers less than some verified limit.

is_lucas_pseudoprime

Takes a positive number as input, and returns 1 if the input is a standard Lucas probable prime using the Selfridge method of choosing D, P, and Q (some sources call this a Lucas-Selfridge pseudoprime).

is_strong_lucas_pseudoprime

Takes a positive number as input, and returns 1 if the input is a strong Lucas pseudoprime using the Selfridge method of choosing D, P, and Q (some sources call this a strong Lucas-Selfridge pseudoprime). This is one half of the BPSW primality test (the Miller-Rabin strong pseudoprime test with base 2 being the other half).

is_extra_strong_lucas_pseudoprime

Takes a positive number as input, and returns 1 if the input passes the extra strong Lucas test (as defined in Grantham 2000). This has slightly more restrictive conditions than the strong Lucas test, but uses different starting parameters so is not directly comparable.

is_almost_extra_strong_lucas_pseudoprime

Takes a positive number as input, and returns 1 if the input passes the extra strong Lucas test, ignoring the U_n = 0 condition. This produces about 5% more pseudoprimes than the extra strong test, but 66% fewer than the strong test.

An optional second argument (an integer between 1 and 256) indicates the increment used when selecting the P parameter. A default value of 1 creates the same parameters as the extra strong test, so the pseudoprime sequence from this function will contain all the extra strong Lucas pseudoprimes. A value of 2 yields the method used by Pari.

is_frobenius_underwood_pseudoprime

Takes a positive number as input, and returns 1 if the input passes the minimal lambda+2 test (see Underwood 2012 "Quadratic Compositeness Tests"), where (L+2)^(n-1) = 5 + 2x mod (n, L^2 - Lx + 1). The computational cost for this is between the cost of 2 and 3 strong pseudoprime tests. There are no known counterexamples, but this is not a well studied test.

is_aks_prime

Takes a positive number as input, and returns 1 if the input can be proven prime using the AKS primality test. This code is included for completeness and as an example, but is impractically slow.

lucas_sequence

  my($U, $V, $Qk) = lucas_sequence($n, $P, $Q, $k)

Computes U_k, V_k, and Q_k for the Lucas sequence defined by P,Q, modulo n. The modular Lucas sequence is used in a number of primality tests and proofs.

The following conditions must hold: - D = P*P - 4*Q != 0 - P > 0 - P < n - Q < n - k >= 0 - n >= 2

UTILITY FUNCTIONS

prime_precalc

  prime_precalc( 1_000_000_000 );

Let the module prepare for fast operation up to a specific number. It is not necessary to call this, but it gives you more control over when memory is allocated and gives faster results for multiple calls in some cases. In the current implementation this will calculate a sieve for all numbers up to the specified number.

prime_memfree

  prime_memfree;

Frees any extra memory the module may have allocated. Like with prime_precalc, it is not necessary to call this, but if you're done making calls, or want things cleanup up, you can use this. The object method might be a better choice for complicated uses.

FACTORING FUNCTIONS

factor

  my @factors = factor(3_369_738_766_071_892_021);
  # returns (204518747,16476429743)

Produces the prime factors of a positive number input, in numerical order. The special cases of n = 0 and n = 1 will return n, which guarantees multiplying the factors together will always result in the input value, though those are the only cases where the returned factors are not prime.

trial_factor

  my @factors = trial_factor($n);

Produces the prime factors of a positive number input. The factors will be in numerical order. The special cases of n = 0 and n = 1 will return n, while with all other inputs the factors are guaranteed to be prime. For large inputs this will be very slow.

fermat_factor

  my @factors = fermat_factor($n);

Produces factors, not necessarily prime, of the positive number input. This uses Fermat's classic algorithm, without any special improvements (e.g. Lehman or McKee). This is typically slow and usually "holf_factor" will be faster.

holf_factor

  my @factors = holf_factor($n);

Produces factors, not necessarily prime, of the positive number input. An optional number of rounds can be given as a second parameter. It is possible the function will be unable to find a factor, in which case a single element, the input, is returned. This uses Hart's One Line Factorization with no premultiplier. It is an interesting alternative to Fermat's algorithm, and there are some inputs it can rapidly factor. In the long run it has the same advantages and disadvantages as Fermat's method.

squfof_factor

  my @factors = squfof_factor($n);

Currently not implemented in Perl.

prho_factor

pbrent_factor

  my @factors = prho_factor($n);

  # Use a very small number of rounds
  my @factors = prho_factor($n, 1000);

Produces factors, not necessarily prime, of the positive number input. An optional number of rounds can be given as a second parameter. An optional additive factor may be given as a third parameter (default 3). These methods attempt to find a single factor using Pollard's Rho algorithm (or Brent's alternative which is typically faster). These methods can quickly find small factors. If the input is prime or they run out of rounds, they will return the single input value. On some inputs they will take a very long time, while on others they succeed in a remarkably short time.

pminus1_factor

  my @factors = pminus1_factor($n);
  my @factors = pminus1_factor($n, 1_000);          # set B1 smoothness
  my @factors = pminus1_factor($n, 1_000, 50_000);  # set B1 and B2

Produces factors, not necessarily prime, of the positive number input. This is Pollard's p-1 method, using two stages. The default with no B1 or B2 given is to run with increasing B1 factors. This method can rapidly find a factor p of n where p-1 is smooth (i.e. p-1 has no large factors).

ecm_factor

  my @factors = ecm_factor($n);
  my @factors = ecm_factor($n, 1000);           # B1 = B2 = 1000, curves = 10
  my @factors = ecm_factor($n, 1000, 5000, 10); # Set B1, B2, and ncurves

Given a positive number input, tries to discover a factor using ECM. The resulting array will contain either two factors (it succeeded) or the original number (no factor was found). In either case, multiplying @factors yields the original input. The B1 and B2 smoothness factors for stage 1 and stage 2 respectively may be supplied, as can be number of curves to try.

MATHEMATICAL FUNCTIONS

ExponentialIntegral

  my $Ei = ExponentialIntegral($x);

Given a non-zero floating point input x, this returns the real-valued exponential integral of x, defined as the integral of e^t/t dt from -infinity to x.

If the bignum module has been loaded, all inputs will be treated as if they were Math::BigFloat objects.

We first check to see if the Math::MPFR module is installed. If so, then it is used, as it will return results much faster and can be more accurate. Accuracy when using MPFR will be 17 digits for non-BigInt/BigFloats, and for BigInt/BigFloat inputs will be equal to the accuracy() value of the input (or the default BigFloat accuracy, which is 40 by default).

MPFR is used for positive inputs only. If Math::MPFR is not installed or the input is negative, then other methods are used: continued fractions (x < -1), rational Chebyshev approximation ( -1 < x < 0), a convergent series (small positive x), or an asymptotic divergent series (large positive x). Accuracy should be at least 14 digits.

LogarithmicIntegral

  my $li = LogarithmicIntegral($x)

Given a positive floating point input, returns the floating point logarithmic integral of x, defined as the integral of dt/ln t from 0 to x. If given a negative input, the function will croak. The function returns 0 at x = 0, and -infinity at x = 1.

This is often known as li(x). A related function is the offset logarithmic integral, sometimes known as Li(x) which avoids the singularity at 1. It may be defined as Li(x) = li(x) - li(2).

We first check to see if the Math::MPFR module is installed. If so, then it is used, as it will return results much faster and can be more accurate. Accuracy when using MPFR will be 17 digits for non-BigInt/BigFloats, and for BigInt/BigFloat inputs will be equal to the accuracy() value of the input (or the default BigFloat accuracy, which is 40 by default).

MPFR is used for inputs greater than 1 only. If Math::MPFR is not installed or the input is less than 1, results will be calculated as Ei(ln x).

RiemannZeta

  my $z = RiemannZeta($s);

Given a floating point input s where s >= 0.5, returns the floating point value of ζ(s)-1, where ζ(s) is the Riemann zeta function. One is subtracted to ensure maximum precision for large values of s. The zeta function is the sum from k=1 to infinity of 1 / k^s

If the bignum module has been loaded, all inputs will be treated as if they were Math::BigFloat objects.

We first check to see if the Math::MPFR module is installed. If so, then it is used, as it will return results much faster and can be more accurate. Accuracy when using MPFR will be 17 digits for non-BigInt/BigFloats, and for BigInt/BigFloat inputs will be equal to the accuracy() value of the input (or the default BigFloat accuracy, which is 40 by default).

If Math::MPFR is not installed, then results are calculated either from a table, rational Chebyshev approximation, or via a series.

RiemannR

  my $r = RiemannR($x);

Given a positive non-zero floating point input, returns the floating point value of Riemann's R function. Riemann's R function gives a very close approximation to the prime counting function.

If the bignum module has been loaded, all inputs will be treated as if they were Math::BigFloat objects.

We first check to see if the Math::MPFR module is installed. If so, then it is used, as it will return results much faster and can be more accurate. Accuracy when using MPFR will be 17 digits for non-BigInt/BigFloats, and for BigInt/BigFloat inputs will be equal to the accuracy() value of the input (or the default BigFloat accuracy, which is 40 by default).

LIMITATIONS

The SQUFOF and Fermat factoring algorithms are not implemented yet.

Some of the prime methods use more memory than they should, as the segmented sieve is not properly used in primes and prime_count.

PERFORMANCE

Performance compared to the XS/C code is quite poor for many operations. Some operations that are relatively close for small and medium-size values:

  next_prime / prev_prime
  is_prime / is_prob_prime
  miller_rabin
  ExponentialIntegral / LogarithmicIntegral / RiemannR
  primearray

Operations that are slower include:

  primes
  random_prime / random_ndigit_prime
  factor / all_factors
  nth_prime
  primecount

Performance improvement in this code is still possible. The prime sieve is over 2x faster than anything I was able to find online, but it is still has room for improvement.

Math::Prime::Util::GMP offers C+XS+GMP support for most of the important functions, and will be vastly faster for most operations. If you install that module, Math::Prime::Util will load it automatically, meaning you should not have to think about what code is actually being used (C, GMP, or Perl).

Memory use will generally be higher for the PP code, and in some cases much higher. Some of this may be addressed in a later release.

For small values (e.g. primes and prime counts under 10M) most of this will not matter.

SEE ALSO

Math::Prime::Util

Math::Prime::Util::GMP

AUTHORS

Dana Jacobsen <dana@acm.org>

COPYRIGHT

Copyright 2012-2013 by Dana Jacobsen <dana@acm.org>

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.