#ifndef SIEVE_HPP
#define SIEVE_HPP
#include <pod_vector.hpp>
#include <stdint.h>
#include <cassert>
#include <vector>
namespace primecount {
class Sieve
{
public:
Sieve(uint64_t low, uint64_t segment_size, uint64_t wheel_size);
void cross_off(uint64_t prime, uint64_t i);
void cross_off_count(uint64_t prime, uint64_t i);
static uint64_t get_segment_size(uint64_t size);
uint64_t count(uint64_t start, uint64_t stop) const;
uint64_t count(uint64_t stop);
uint64_t get_total_count() const
{
return total_count_;
}
template <typename T>
void pre_sieve(const std::vector<T>& primes, uint64_t c, uint64_t low, uint64_t high)
{
assert(c < primes.size());
reset_sieve(low, high);
for (uint64_t i = 4; i <= c; i++)
cross_off(primes[i], i);
init_counter(low, high);
}
private:
void add(uint64_t prime);
void allocate_counter(uint64_t low);
void init_counter(uint64_t low, uint64_t high);
void reset_counter();
void reset_sieve(uint64_t low, uint64_t high);
uint64_t segment_size() const;
struct Wheel
{
uint32_t multiple;
uint32_t index;
Wheel()
: multiple(0),
index(0)
{ }
Wheel(uint32_t m, uint32_t i)
: multiple(m),
index(i)
{ }
};
struct Counter
{
uint64_t stop = 0;
uint64_t dist = 0;
uint64_t log2_dist = 0;
uint64_t sum = 0;
uint64_t i = 0;
pod_vector<uint32_t> counter;
uint32_t& operator[](std::size_t pos)
{
return counter[pos];
}
uint32_t operator[](std::size_t pos) const
{
return counter[pos];
}
};
uint64_t start_ = 0;
uint64_t prev_stop_ = 0;
uint64_t count_ = 0;
uint64_t total_count_ = 0;
pod_vector<uint8_t> sieve_;
std::vector<Wheel> wheel_;
Counter counter_;
};
}
#endif