#ifndef SEGMENTEDPITABLE_HPP
#define SEGMENTEDPITABLE_HPP
#include <BitSieve240.hpp>
#include <popcnt.hpp>
#include <macros.hpp>
#include <stdint.h>
#include <algorithm>
#include <cassert>
#include <vector>
namespace primecount {
class SegmentedPiTable : public BitSieve240
{
public:
void init(uint64_t low, uint64_t high);
int64_t low() const
{
return low_;
}
int64_t high() const
{
return high_;
}
static constexpr int64_t numbers_per_byte()
{
return 240 / sizeof(pi_t);
}
static int64_t get_segment_size(uint64_t size)
{
size = std::max<uint64_t>(240, size);
if (size % 240)
size += 240 - size % 240;
return size;
}
ALWAYS_INLINE int64_t operator[](uint64_t x) const
{
assert(x >= low_);
assert(x < high_);
if_unlikely(x < pi_tiny_.size())
return pi_tiny_[x];
x -= low_;
uint64_t count = pi_[x / 240].count;
uint64_t bits = pi_[x / 240].bits;
uint64_t bitmask = unset_larger_[x % 240];
return count + popcnt64(bits & bitmask);
}
private:
void init_bits();
void init_count(uint64_t pi_low);
struct pi_t
{
uint64_t count = 0;
uint64_t bits = 0;
};
std::vector<pi_t> pi_;
uint64_t low_ = 0;
uint64_t high_ = 0;
};
}
#endif