diff --git a/lib/primesieve/include/primesieve/StorePrimes.hpp b/lib/primesieve/include/primesieve/StorePrimes.hpp index 7a28a194f..60bad7d3f 100644 --- a/lib/primesieve/include/primesieve/StorePrimes.hpp +++ b/lib/primesieve/include/primesieve/StorePrimes.hpp @@ -33,8 +33,8 @@ namespace primesieve { -/// primeCountApprox(x) >= pi(x) -inline std::size_t prime_count_approx(uint64_t start, uint64_t stop) +/// prime_count_upper(x) >= pi(x) +inline std::size_t prime_count_upper(uint64_t start, uint64_t stop) { if (start > stop) return 0; @@ -83,7 +83,7 @@ inline void store_primes(uint64_t start, if (stop > std::numeric_limits::max()) throw primesieve_error("store_primes(): " + getTypeName() + " is too narrow for generating primes up to " + std::to_string(stop)); - std::size_t size = primes.size() + prime_count_approx(start, stop); + std::size_t size = primes.size() + prime_count_upper(start, stop); primes.reserve(size); primesieve::iterator it(start, stop); diff --git a/lib/primesieve/include/primesieve/pmath.hpp b/lib/primesieve/include/primesieve/pmath.hpp index 16924fce6..d59f64a0d 100644 --- a/lib/primesieve/include/primesieve/pmath.hpp +++ b/lib/primesieve/include/primesieve/pmath.hpp @@ -138,15 +138,15 @@ inline B inBetween(A min, B x, C max) return x; } -/// primeCountApprox(x) >= pi(x). +/// primeCountUpper(x) >= pi(x). /// In order to prevent having to resize vectors with prime numbers /// (which would incur additional overhead) it is important that -/// primeCountApprox(x) >= pi(x). Also for our purpose, it is -/// actually beneficial if primeCountApprox(x) is a few percent +/// primeCountUpper(x) >= pi(x). Also for our purpose, it is +/// actually beneficial if primeCountUpper(x) is a few percent /// larger (e.g. 3%) than pi(x), this reduces the number of memory /// allocations in PrimeGenerator::fillPrevPrimes(). /// -inline std::size_t primeCountApprox(uint64_t start, uint64_t stop) +inline std::size_t primeCountUpper(uint64_t start, uint64_t stop) { if (start > stop) return 0; @@ -163,9 +163,9 @@ inline std::size_t primeCountApprox(uint64_t start, uint64_t stop) return (std::size_t) pix; } -inline std::size_t primeCountApprox(uint64_t stop) +inline std::size_t primeCountUpper(uint64_t stop) { - return primeCountApprox(0, stop); + return primeCountUpper(0, stop); } /// Approximation of the maximum prime gap near n diff --git a/lib/primesieve/src/EratSmall.cpp b/lib/primesieve/src/EratSmall.cpp index 7be6feef3..a473c38dd 100644 --- a/lib/primesieve/src/EratSmall.cpp +++ b/lib/primesieve/src/EratSmall.cpp @@ -41,7 +41,7 @@ void EratSmall::init(uint64_t stop, stop_ = stop; maxPrime_ = maxPrime; l1CacheSize_ = (std::size_t) l1CacheSize; - std::size_t count = primeCountApprox(maxPrime); + std::size_t count = primeCountUpper(maxPrime); primes_.reserve(count); } diff --git a/lib/primesieve/src/PrimeGenerator.cpp b/lib/primesieve/src/PrimeGenerator.cpp index 029a90141..ed6701789 100644 --- a/lib/primesieve/src/PrimeGenerator.cpp +++ b/lib/primesieve/src/PrimeGenerator.cpp @@ -164,7 +164,7 @@ void PrimeGenerator::initPrevPrimes(Vector& primes, // When sieving backwards the number of primes inside [start, stop] // slowly increases in each new segment as there are more small // than large primes. Our new size has been calculated using - // primeCountApprox(start, stop) which is usually too large by 4% + // primeCountUpper(start, stop) which is usually too large by 4% // near 10^12 and by 2.5% near 10^19. Hence if the new size is less // than 1% larger than the old size we do not increase the primes // buffer as it will likely be large enough to fit all primes. @@ -177,7 +177,7 @@ void PrimeGenerator::initPrevPrimes(Vector& primes, } }; - std::size_t pix = primeCountApprox(start_, stop_); + std::size_t pix = primeCountUpper(start_, stop_); if (start_ <= maxCachedPrime()) { @@ -235,7 +235,7 @@ void PrimeGenerator::initNextPrimes(Vector& primes, // algorithm aborts as soon as there is not // enough space to store 64 more primes. std::size_t minSize = *size + 64; - std::size_t pix = primeCountApprox(start_, stop_) + 64; + std::size_t pix = primeCountUpper(start_, stop_) + 64; pix = inBetween(minSize, pix, maxSize); pix = std::max(*size, pix); resize(primes, pix); @@ -252,7 +252,7 @@ void PrimeGenerator::initNextPrimes(Vector& primes, // algorithm aborts as soon as there is not // enough space to store 64 more primes. std::size_t minSize = 64; - std::size_t pix = primeCountApprox(start_, stop_) + 64; + std::size_t pix = primeCountUpper(start_, stop_) + 64; pix = inBetween(minSize, pix, maxSize); resize(primes, pix); } diff --git a/lib/primesieve/src/nthPrimeApprox.cpp b/lib/primesieve/src/nthPrimeApprox.cpp index 09cd93e3d..757acb5d7 100644 --- a/lib/primesieve/src/nthPrimeApprox.cpp +++ b/lib/primesieve/src/nthPrimeApprox.cpp @@ -267,6 +267,12 @@ uint64_t Ri_inverse(uint64_t x) return (uint64_t) res; } +/// primePiApprox(x) is a very accurate approximation of PrimePi(x) +/// with |PrimePi(x) - primePiApprox(x)| < sqrt(x). +/// Since primePiApprox(x) may be smaller than PrimePi(x) it +/// cannot be used to calculate the size of a primes array, for +/// this use case primeCountUpper() should be used. +/// uint64_t primePiApprox(uint64_t x) { // Li(x) is faster but less accurate than Ri(x). @@ -277,6 +283,11 @@ uint64_t primePiApprox(uint64_t x) return Ri(x); } +/// nthPrimeApprox(n) is a very accurate approximation of the nth +/// prime with |nth prime - nthPrimeApprox(n)| < sqrt(nth prime). +/// Please note that nthPrimeApprox(n) may be smaller or larger than +/// the actual nth prime. +/// uint64_t nthPrimeApprox(uint64_t n) { // Li_inverse(n) is faster but less accurate than Ri_inverse(n).