Skip to content

WilliamAufort/primecount

 
 

Repository files navigation

primecount

Build Status

primecount is a command-line program and C++ library that counts the primes below an integer x ≤ 1027 using highly optimized implementations of the prime counting function (combinatorial methods). primecount includes implementations of the algorithms of Legendre, Meissel, Lehmer, Lagarias-Miller-Odlyzko and Deleglise-Rivat all of which have been parallelized using OpenMP.

primecount contains the first ever parallel open source implementation of the Deleglise-Rivat algorithm and it features a novel load balancer which scales up to hundreds of CPU cores. As of December 2014 primecount counts primes faster than any other program on the web!

Binaries

Below are the latest precompiled binaries for Windows 64-bit and Linux x86-64. These binaries are statically linked and require a CPU (2010 or later) which supports the POPCNT instruction.

SHA1 checksums of the files:

f9281e39abe5c27be53d6ff72e332e6d4d7714d1  primecount-2.1-win64.zip
77b98c4db15f6bb625bf4fca18def272e65cc919  primecount-2.1-linux-x64.tar.gz

Usage examples

Open a terminal and run the primecount command-line application using e.g.:

# Count the primes below 10^14
$ ./primecount 1e14

# Print progress and status information during computation
$ ./primecount 1e20 --status

# Count primes using Meissel's algorithm
$ ./primecount 2**32 --meissel

# Find the 10^14th prime using 4 threads
$ ./primecount 1e14 --nthprime --threads=4 --time

Command-line options

Usage: primecount x [OPTION]...
Count the primes below x <= 10^27 using the prime counting function,
by default the Deleglise-Rivat algorithm (-d) is used.

Options:

  -d,    --deleglise_rivat  Count primes using Deleglise-Rivat algorithm
         --legendre         Count primes using Legendre's formula
         --lehmer           Count primes using Lehmer's formula
  -l,    --lmo              Count primes using Lagarias-Miller-Odlyzko
  -m,    --meissel          Count primes using Meissel's formula
         --Li               Approximate pi(x) using the logarithmic integral
         --Li_inverse       Approximate the nth prime using Li^-1(x)
  -n,    --nthprime         Calculate the nth prime
  -p,    --primesieve       Count primes using the sieve of Eratosthenes
  -s,    --status           Print status info during computation
         --test             Run various correctness tests and exit
         --time             Print the time elapsed in seconds
  -t<N>, --threads=<N>      Set the number of threads, 1 <= N <= CPU cores
  -v,    --version          Print version and license information
  -h,    --help             Print this help menu

Advanced Deleglise-Rivat options:

  -a<N>, --alpha=<N>        Tuning factor, 1 <= alpha <= x^(1/6)
         --p2               Only compute the 2nd partial sieve function
         --s1               Only compute the ordinary leaves
         --s2_trivial       Only compute the trivial special leaves
         --s2_easy          Only compute the easy special leaves
         --s2_hard          Only compute the hard special leaves

Algorithms

Legendre's Formula
Meissel's Formula
Lehmer's Formula
LMO Formula

Up until the early 19th century the most efficient known method for counting primes was the sieve of Eratosthenes which has a running time of operations. The first improvement to this bound was Legendre's formula (1830) which uses the inclusion-exclusion principle to calculate the number of primes below x without enumerating the individual primes. Legendre's formula has a running time of operations and uses space. In 1870 E. D. F. Meissel improved Legendre's formula by setting and by adding the correction term . Meissel's formula has a running time of operations and uses space. In 1959 D. H. Lehmer extended Meissel's formula and slightly improved the running time to operations and space. In 1985 J. C. Lagarias, V. S. Miller and A. M. Odlyzko published a new algorithm based on Meissel's formula which has a lower runtime complexity of operations and which uses only space.

For more information on Legendre's, Meissel's and Lehmer's formulas Hans Riesel's book [4] is probably the best source of information. For the Lagarias-Miller-Odlyzko algorithm I recommend reading their original paper [3] as well as Tomás Oliveira's paper [7].

Fast nth prime calculation

The most efficient known method for calculating the nth prime is a combination of the prime counting function and a prime sieve. The idea is to closely approximate the nth prime using e.g. the inverse logarithmic integral and then count the primes up to this guess using the prime counting function. Once this is done one starts sieving (e.g. using the segmented sieve of Eratosthenes) from there on until one finds the actual nth prime. The author has implemented primecount::nth_prime(n) this way, it finds the nth prime in operations using space.

Timings

x Prime Count Legendre Lehmer Lagarias
Miller
Odlyzko
Deleglise
Rivat
1010 455,052,511 0.03s 0.02s 0.01s 0.00s
1011 4,118,054,813 0.08s 0.06s 0.01s 0.01s
1012 37,607,912,018 0.32s 0.27s 0.04s 0.03s
1013 346,065,536,839 1.58s 1.14s 0.16s 0.08s
1014 3,204,941,750,802 9.73s 5.13s 0.70s 0.31s
1015 29,844,570,422,669 62.95s 28.55s 2.94s 1.18s
1016 279,238,341,033,925 447.11s 176.84s 13.62s 4.57s
1017 2,623,557,157,654,233 3,920.29s 1,349.95s 63.97s 18.10s
1018 24,739,954,287,740,860 31,897.66s 9,885.71s 305.28s 76.06s

The benchmarks above were run on an Intel Core i7-4770 CPU (4 x 3.4 GHz) from 2013 using a 64-bit Linux operating system and primecount was compiled using GCC 4.8.

Build instructions (Unix-like OSes)

To build primecount you need to have installed a C++ compiler and GNU make. primecount depends on the author's primesieve library, download it from http://primesieve.org/downloads and install it using:

$ ./configure
$ make
$ sudo make install

If you are not using Linux then you need to export these variables:

export LIBRARY_PATH=/usr/local/lib:$LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
export CPLUS_INCLUDE_PATH=/usr/local/include:$CPLUS_INCLUDE_PATH

Finally download the latest primecount-2.1.tar.gz release tarball and build it using:

$ ./configure
$ make
$ sudo make install

If you have cloned primecount or downloaded a zip archive from GitHub then the GNU Build System (a.k.a. Autotools) must be installed and autogen.sh must be executed once. To install the GNU Build System install GNU Autoconf, GNU Automake and GNU Libtool using your package manager.

$ ./autogen.sh
$ ./configure
$ make
$ sudo make install

If your CPU supports the POPCNT instruction then it is enabled in the build process. POPCNT speeds up primecount by about 10 percent. If you need maximum portability you can disable POPCNT:

$ ./configure --disable-popcnt

Build instructions (Microsoft Visual C++)

To build primecount simply open a Visual Studio Command Prompt and execute:

> nmake -f Makefile.msvc

C++ API

Below is a list of the functions declared in the primecount.hpp header file. A short description of each function including its run-time and space complexity can be read here.

/// @file  primecount.hpp

int64_t primecount::pi                 (int64_t x);
int64_t primecount::pi_deleglise_rivat (int64_t x);
int64_t primecount::pi_legendre        (int64_t x);
int64_t primecount::pi_lehmer          (int64_t x);
int64_t primecount::pi_lmo             (int64_t x);
int64_t primecount::pi_meissel         (int64_t x);
int64_t primecount::pi_primesieve      (int64_t x);
int64_t primecount::nth_prime          (int64_t n);

/// 128-bit prime counting function.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
/// @param expr  Integer arithmetic expression e.g. "1000", "10^22"
/// @pre   expr  <= primecount::max()
std::string primecount::pi(const std::string& expr);

/// @return  Largest integer supported by pi(const std::string&)
std::string primecount::max();

int  primecount::get_num_threads();
void primecount::set_num_threads(int threads);

C++ library usage

Below is an example program that counts the primes below 1000.

#include <primecount.hpp>
#include <iostream>

int main()
{
  int64_t prime_count = primecount::pi(1000);
  std::cout << "primes below 1000 = " << prime_count << std::endl;

  return 0;
}

On Unix-like OSes compile using:

$ c++ -O2 primes.cpp -lprimecount

References

  1. A. M. Legendre, Théorie des nombres, Third edition, Paris, 1830. Vol. 2, p. 65.
  2. D. H. Lehmer, On the exact number of primes less than a given limit, Illinois J. Math. 3 (1959), pp. 381–388.
  3. J. C. Lagarias, V. S. Miller, and A. M. Odlyzko, Computing pi(x): The Meissel-Lehmer method, Mathematics of Computation, 44 (1985), pp. 537–560.
  4. M. Deleglise and J. Rivat, "Computing pi(x): The Meissel, Lehmer, Lagarias, Miller, Odlyzko Method", Mathematics of Computation, Volume 65, Number 213, 1996, pp 235–245.
  5. Hans Riesel, Prime Numbers and Computer Methods for Factorization, 2nd ed., Birkhäuser, Boston, 1994. pp. 10-38.
  6. Raymond Séroul, Programming for Mathematicians, Springer-Verlag, Berlin (2000), pp. 175-181.
  7. R. Crandall and C. Pomerance, Prime numbers: a computational perspective, 2nd ed., Springer, New York, 2005. pp. 152-162.
  8. Tomás Oliveira e Silva, Computing pi(x): the combinatorial method, Revista do DETUA, vol. 4, no. 6, March 2006, pp. 759-768.
  9. Douglas B. Staple, The combinatorial algorithm for computing pi(x), arXiv:1503.01839, 6 March 20015.

About

Fast C++ library for counting primes

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C++ 99.5%
  • Shell 0.5%