#include <SegmentedPiTable.hpp>
#include <primecount-internal.hpp>
#include <primesieve.hpp>
#include <imath.hpp>
#include <min.hpp>
#include <stdint.h>
#include <cassert>
namespace primecount {
void SegmentedPiTable::init(uint64_t low, uint64_t high)
{
assert(low < high);
assert(low % 240 == 0);
int threads = 1;
uint64_t pi_low;
if (low <= 5)
pi_low = pi_tiny_[5];
else if (low == high_)
pi_low = operator[](low - 1);
else
pi_low = pi_noprint(low - 1, threads);
low_ = low;
high_ = high;
uint64_t segment_size = high - low;
uint64_t size = ceil_div(segment_size, 240);
pi_.clear();
pi_.resize(size);
init_bits();
init_count(pi_low);
}
void SegmentedPiTable::init_bits()
{
uint64_t low = max(low_, 5);
uint64_t prime = 0;
primesieve::iterator it(low, high_);
while ((prime = it.next_prime()) < high_)
{
uint64_t p = prime - low_;
pi_[p / 240].bits |= set_bit_[p % 240];
}
}
void SegmentedPiTable::init_count(uint64_t pi_low)
{
uint64_t j = ceil_div((high_ - low_), 240);
for (uint64_t i = 0; i < j; i++)
{
pi_[i].count = pi_low;
pi_low += popcnt64(pi_[i].bits);
}
}
}