-
-
Notifications
You must be signed in to change notification settings - Fork 123
libprimesieve 8.0 ABI changes
There have been a few changes in the ABI (Application binary interface) of libprimesieve-8.0 compared to libprimesieve-7.x. This ABI break was necessary to fix undefined behavior present in libprimesieve-7.x (in primesieve::iterator
). The API remains backwards compatible. If your program uses libprimesieve, simply recompiling your program against the latest libprimesieve-8.0 should be enough. If on the other hand you have written libprimesieve bindings for another programming language you need to migrate your code to the new ABI.
Below are the ABI changes of the primesieve_iterator
struct (header: primesieve/include/iterator.h
) compared to libprimesieve-7.x. Pay attention to the primesieve_prev_prime()
function, its decrementing has subtly changed in a non backwards compatible way.
--- a/include/primesieve/iterator.h
+++ b/include/primesieve/iterator.h
@@ -39,12 +39,9 @@ typedef struct
size_t i;
- size_t last_idx;
+ size_t size;
uint64_t start;
- uint64_t stop;
uint64_t stop_hint;
- uint64_t dist;
uint64_t* primes;
- void* vector;
- void* primeGenerator;
+ void* memory;
int is_error;
} primesieve_iterator;
static inline uint64_t primesieve_next_prime(primesieve_iterator* it)
{
- if (it->i++ == it->last_idx)
+ it->i += 1;
+ if (it->i >= it->size)
primesieve_generate_next_primes(it);
return it->primes[it->i];
}
static inline uint64_t primesieve_prev_prime(primesieve_iterator* it)
{
- if (it->i-- == 0)
+ if (it->i == 0)
primesieve_generate_prev_primes(it);
+ it->i -= 1;
return it->primes[it->i];
}
If you want your code to support both libprimesieve-7.x and libprimesieve-8.x you can use something like this:
#include <primesieve.h>
#if PRIMESIEVE_VERSION_MAJOR >= 8
typedef struct
{
size_t i;
size_t size;
uint64_t start;
uint64_t stop_hint;
uint64_t* primes;
void* memory;
int is_error;
} primesieve_iterator;
static inline uint64_t primesieve_prev_prime(primesieve_iterator* it)
{
if (it->i == 0)
primesieve_generate_prev_primes(it);
it->i -= 1;
return it->primes[it->i];
}
#else
typedef struct
{
size_t i;
size_t last_idx;
uint64_t start;
uint64_t stop;
uint64_t stop_hint;
uint64_t dist;
uint64_t* primes;
void* vector;
void* primeGenerator;
int is_error;
} primesieve_iterator;
static inline uint64_t primesieve_prev_prime(primesieve_iterator* it)
{
if (it->i-- == 0)
primesieve_generate_prev_primes(it);
return it->primes[it->i];
}
#endif
Below are the ABI changes of the primesieve::iterator
struct (header: primesieve/include/iterator.hpp
) compared to libprimesieve-7.x. Pay attention to the prev_prime()
method, its decrementing has subtly changed in a non backwards compatible way.
--- a/include/primesieve/iterator.hpp
+++ b/include/primesieve/iterator.hpp
@@ -14,32 +14,41 @@
-class PrimeGenerator;
-uint64_t get_max_stop();
-class iterator
+struct iterator
{
-public:
- iterator(uint64_t start = 0, uint64_t stop_hint = get_max_stop());
- void skipto(uint64_t start, uint64_t stop_hint = get_max_stop());
+ iterator() noexcept;
+ iterator(uint64_t start, uint64_t stop_hint = std::numeric_limits<uint64_t>::max()) noexcept;
+ void skipto(uint64_t start, uint64_t stop_hint = std::numeric_limits<uint64_t>::max()) noexcept;
+ void clear() noexcept;
uint64_t next_prime()
{
- if (i_++ == last_idx_)
+ i_ += 1;
+ if (i_ >= size_)
generate_next_primes();
return primes_[i_];
}
uint64_t prev_prime()
{
- if (i_-- == 0)
+ if (i_ == 0)
generate_prev_primes();
+ i_ -= 1;
return primes_[i_];
}
@@ -83,17 +94,12 @@ public:
-private:
std::size_t i_;
- std::size_t last_idx_;
+ std::size_t size_;
- std::vector<uint64_t> primes_;
uint64_t start_;
- uint64_t stop_;
uint64_t stop_hint_;
- uint64_t dist_;
- std::unique_ptr<PrimeGenerator> primeGenerator_;
- void generate_next_primes();
- void generate_prev_primes();
+ uint64_t* primes_;
+ void* memory_;
};
The signatures of the primesieve::generate_primes()
functions from the primesieve.hpp
header have also
been modified to allow vector types other than std::vector
. The API of the primesieve::generate_primes()
functions (and of primesieve.hpp
) is still backwards compatible to libprimesieve-7.x.
--- a/include/primesieve.hpp
+++ b/include/primesieve.hpp
@@ -13,50 +13,63 @@
/// Store the primes <= stop in the primes vector.
-template <typename T>
-inline void generate_primes(uint64_t stop, std::vector<T>* primes)
+template <typename vect>
+inline void generate_primes(uint64_t stop, vect* primes)
{
if (primes)
store_primes(0, stop, *primes);
}
/// Store the primes within the interval [start, stop] in the primes vector.
-template <typename T>
-inline void generate_primes(uint64_t start, uint64_t stop, std::vector<T>* primes)
+template <typename vect>
+inline void generate_primes(uint64_t start, uint64_t stop, vect* primes)
{
if (primes)
store_primes(start, stop, *primes);
}
/// Store the first n primes in the primes vector.
-template <typename T>
-inline void generate_n_primes(uint64_t n, std::vector<T>* primes)
+template <typename vect>
+inline void generate_n_primes(uint64_t n, vect* primes)
{
if (primes)
store_n_primes(n, 0, *primes);
}
/// Store the first n primes >= start in the primes vector.
-template <typename T>
-inline void generate_n_primes(uint64_t n, uint64_t start, std::vector<T>* primes)
+template <typename vect>
+inline void generate_n_primes(uint64_t n, uint64_t start, vect* primes)
{
if (primes)
store_n_primes(n, start, *primes);
}