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!
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
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
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
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].
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.
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.
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
To build primecount simply open a Visual Studio Command Prompt and execute:
> nmake -f Makefile.msvc
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);
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
- A. M. Legendre, Théorie des nombres, Third edition, Paris, 1830. Vol. 2, p. 65.
- D. H. Lehmer, On the exact number of primes less than a given limit, Illinois J. Math. 3 (1959), pp. 381–388.
- 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.
- 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.
- Hans Riesel, Prime Numbers and Computer Methods for Factorization, 2nd ed., Birkhäuser, Boston, 1994. pp. 10-38.
- Raymond Séroul, Programming for Mathematicians, Springer-Verlag, Berlin (2000), pp. 175-181.
- R. Crandall and C. Pomerance, Prime numbers: a computational perspective, 2nd ed., Springer, New York, 2005. pp. 152-162.
- Tomás Oliveira e Silva, Computing pi(x): the combinatorial method, Revista do DETUA, vol. 4, no. 6, March 2006, pp. 759-768.
- Douglas B. Staple, The combinatorial algorithm for computing pi(x), arXiv:1503.01839, 6 March 20015.