Skip to content

Commit

Permalink
Use vector::insert() in StorePrimes.hpp (#124)
Browse files Browse the repository at this point in the history
  • Loading branch information
kimwalisch authored Jun 26, 2022
1 parent 1bc5746 commit f78ddd5
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 25 deletions.
4 changes: 3 additions & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Changes in version 8.0, 10/06/2022
Changes in version 8.0, 26/06/2022
==================================

There has been a minor change in the ABI (Application binary interface) of
Expand All @@ -25,6 +25,8 @@ https://github.com/kimwalisch/primesieve/wiki/libprimesieve-8.0-ABI-changes
memory to store all sieving primes.
* CpuInfo.cpp: Detect AVX512 using CPUID.
* pmath.hpp: Use compiler instrinsics for ilog2() & floorPow2().
* StorePrimes.hpp: Use vector::insert() instead of vector::push_back(),
see: https://github.com/kimwalisch/primesieve/issues/123.
* CMakeLists.txt: Automatically enable expensive debug assertions in debug
mode (if CMAKE_BUILD_TYPE=Debug).

Expand Down
12 changes: 4 additions & 8 deletions include/primesieve.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ namespace primesieve {

/// Store the primes <= stop in the primes vector.
/// @vect: std::vector or other vector type that is API compatible
/// with std::vector (must implement size(), reserve(),
/// push_back() and value_type).
/// with std::vector.
///
template <typename vect>
inline void generate_primes(uint64_t stop, vect* primes)
Expand All @@ -41,8 +40,7 @@ inline void generate_primes(uint64_t stop, vect* primes)

/// Store the primes within the interval [start, stop] in the primes vector.
/// @vect: std::vector or other vector type that is API compatible
/// with std::vector (must implement size(), reserve(),
/// push_back() and value_type).
/// with std::vector.
///
template <typename vect>
inline void generate_primes(uint64_t start, uint64_t stop, vect* primes)
Expand All @@ -53,8 +51,7 @@ inline void generate_primes(uint64_t start, uint64_t stop, vect* primes)

/// Store the first n primes in the primes vector.
/// @vect: std::vector or other vector type that is API compatible
/// with std::vector (must implement size(), reserve(),
/// push_back() and value_type).
/// with std::vector.
///
template <typename vect>
inline void generate_n_primes(uint64_t n, vect* primes)
Expand All @@ -65,8 +62,7 @@ inline void generate_n_primes(uint64_t n, vect* primes)

/// Store the first n primes >= start in the primes vector.
/// @vect: std::vector or other vector type that is API compatible
/// with std::vector (must implement size(), reserve(),
/// push_back() and value_type).
/// with std::vector.
///
template <typename vect>
inline void generate_n_primes(uint64_t n, uint64_t start, vect* primes)
Expand Down
57 changes: 41 additions & 16 deletions include/primesieve/StorePrimes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,30 @@ inline void store_primes(uint64_t start,
start--;
if (~stop == 0)
stop--;
if (start >= stop)
return;

using V = typename T::value_type;
std::size_t size = primes.size() + prime_count_approx(start, stop);
primes.reserve(size);

primesieve::iterator it(start, stop);
it.generate_next_primes();

#if defined(_MSC_VER)
// Disable warning C4244: conversion from X to Y, possible loss of data
#pragma warning(push)
#pragma warning(disable : 4244)
#endif

for (; it.primes_[it.size_ - 1] <= stop; it.generate_next_primes())
primes.insert(primes.end(), it.primes_, it.primes_ + it.size_);
for (; it.primes_[it.i_] <= stop; it.i_++)
primes.push_back((V) it.primes_[it.i_]);

if (start < stop)
{
using V = typename T::value_type;
std::size_t size = primes.size() + prime_count_approx(start, stop);
primes.reserve(size);

primesieve::iterator it(start, stop);
uint64_t prime = it.next_prime();
for (; prime <= stop; prime = it.next_prime())
primes.push_back((V) prime);
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
}

template <typename T>
Expand All @@ -69,9 +81,9 @@ inline void store_n_primes(uint64_t n,
if (start > 0)
start--;

using V = typename T::value_type;
std::size_t size = primes.size() + (std::size_t) n;
primes.reserve(size);
using V = typename T::value_type;

// nthPrime < n(log n + log log n), for n >= 6.
// https://en.wikipedia.org/wiki/Prime_number_theorem#Approximations_for_the_nth_prime_number
Expand All @@ -82,11 +94,24 @@ inline void store_n_primes(uint64_t n,
uint64_t stop = start + nthPrime;

primesieve::iterator it(start, stop);
uint64_t prime = it.next_prime();
for (; n > 0; n--, prime = it.next_prime())
primes.push_back((V) prime);
it.generate_next_primes();

#if defined(_MSC_VER)
// Disable warning C4244: conversion from X to Y, possible loss of data
#pragma warning(push)
#pragma warning(disable : 4244)
#endif

for (; n > it.size_; n -= it.size_, it.generate_next_primes())
primes.insert(primes.end(), it.primes_, it.primes_ + it.size_);
for (; n > 0; n--, it.i_++)
primes.push_back((V) it.primes_[it.i_]);

#if defined(_MSC_VER)
#pragma warning(pop)
#endif

if (~prime == 0)
if (~it.primes_[it.i_ - 1] == 0)
throw primesieve_error("cannot generate primes > 2^64");
}

Expand Down
32 changes: 32 additions & 0 deletions include/primesieve/malloc_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,21 @@ class malloc_vector
return array_;
}

const T* data() const noexcept
{
return array_;
}

T* end() noexcept
{
return end_;
}

const T* end() const noexcept
{
return end_;
}

std::size_t size() const noexcept
{
ASSERT(end_ >= array_);
Expand All @@ -69,6 +84,23 @@ class malloc_vector
*end_++ = value;
}

template <class InputIt>
void insert(T* const pos, InputIt first, InputIt last)
{
// We only support appending to the vector
ASSERT(pos == end_);
(void) pos;

if (first < last)
{
std::size_t old_size = size();
std::size_t new_size = old_size + (std::size_t) (last - first);
reserve(new_size);
end_ = array_ + new_size;
std::copy(first, last, &array_[old_size]);
}
}

void reserve(std::size_t n)
{
if (n > capacity())
Expand Down
17 changes: 17 additions & 0 deletions include/primesieve/pod_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,23 @@ class pod_vector
*end_++ = T(std::forward<Args>(args)...);
}

template <class InputIt>
void insert(T* const pos, InputIt first, InputIt last)
{
// We only support appending to the vector
ASSERT(pos == end_);
(void) pos;

if (first < last)
{
std::size_t old_size = size();
std::size_t new_size = old_size + (std::size_t) (last - first);
reserve(new_size);
end_ = array_ + new_size;
std::copy(first, last, &array_[old_size]);
}
}

void reserve(std::size_t n)
{
if (n > capacity())
Expand Down

0 comments on commit f78ddd5

Please sign in to comment.