This is a C++ implementation of J. P. Sorenson's Pseudosquares Prime Sieve algorithm, which is one of the few prime sieving algorithms that is well suited for generating primes >
The performance of the Pseudosquares Prime Sieve algorithm relies heavily on fast modular exponentiation of 128-bit integers, for which we are using the hurchalla/modular_arithmetic C++ library. For fast generation of sieving primes we are using the primesieve C/C++ library. Both libraries have been vendored (included directly) into the Pseudosquares-Prime-Sieve repository to simplify building the project and eliminate any external dependencies!
You need to have installed a C++ compiler which supports 128-bit integers (either GNU GCC or LLVM/Clang) and CMake โฅ 3.10.
Arch Linux: | sudo pacman -S gcc cmake |
Debian/Ubuntu: | sudo apt install g++ cmake |
Fedora: | sudo dnf install gcc-c++ cmake |
macOS: | brew install cmake |
openSUSE: | sudo zypper install gcc-c++ cmake |
cmake .
cmake --build . --parallel
# Run tests
./tests
The pseudosquares_prime_sieve
program can generate primes โค
# Count primes inside [1e15 1e15+1e8] using all CPU cores
./pseudosquares_prime_sieve 1e15 1e15+1e8
# Count primes inside [1e15 1e15+1e8] using 4 threads
./pseudosquares_prime_sieve 1e15 -d1e8 --threads=4
# Print primes inside [1e25, 1e25+1e4] to stdout
./pseudosquares_prime_sieve 1e25 -d1e4 --print
# Store primes inside [1e25, 1e25+1e4] in a text file
./pseudosquares_prime_sieve 1e25 -d1e4 --print > primes.txt
Usage: pseudosquares_prime_sieve [START] STOP
Sieve the primes inside [START, STOP] (<= 10^33) using
J. P. Sorenson's Pseudosquares Prime Sieve.
Options:
-d, --dist=DIST Sieve the interval [START, START + DIST].
-h, --help Print this help menu.
-p, --print Print primes to the standard output.
-t, --threads=NUM Set the number of threads, NUM <= CPU cores.
Default setting: use all available CPU cores.
-v, --version Print version and license information.
J. P. Sorenson's original 2006 paper on the Pseudosquares Prime Sieve algorithm contains two minor errors, which Sorenson confirmed to me in a private communication. Below are fixes suggested by Sorenson for these two errors. Both of these fixes have been implemented in our pseudosquares_prime_sieve
program.
//** Sieve by integers d up to s, gcd(d,m)=1
int d, m=W.size();
// m is the size of the wheel
for(d=W[p%m].next; d<=min(s,sqrt(l)); d=d+W[d%m].next)
// Loop through multiples of d:
for(x=B.first(d); x<=r; x=x+d)
B.clear(x);
In the code snippet above from Sorenson's paper, one sieves using the integers โค min(s,sqrt(l))
. The variable l
(left) corresponds to the lower bound of the current segment, but its use is incorrect here. One needs to use the current segment's upper bound instead, which is named r
(right) in Sorenson's paper:
//** Sieve by integers d up to s, gcd(d,m)=1
int d, m=W.size();
// m is the size of the wheel
for(d=W[p%m].next; d<=min(s,sqrt(r)); d=d+W[d%m].next)
// Loop through multiples of d:
for(x=B.first(d); x<=r; x=x+d)
B.clear(x);
Some numbers
Start testing
- You get a -1 result, in which case
$n$ is prime or a prime power. - You get something other than a ยฑ1 result, in which case
$n$ is not prime. - You can't keep getting +1 results forever, unless
$n$ is a perfect power. According to Sorenson's paper this case can only occur if$n > 6.4 \cdot 10^{37}$ . - You stop once
$n > L_p$ , in which case$n$ is a prime or a prime power.