pub(super) struct Sieve {
composite: Vec<u64>,
limit: u64,
}
const PERIOD: usize = 3 * 5 * 7;
const PATTERN: [u64; PERIOD] = {
let mut t = [0u64; PERIOD];
let mut j = 0;
while j < 64 * PERIOD {
let n = 2 * j + 1;
if n % 3 == 0 || n % 5 == 0 || n % 7 == 0 {
t[j / 64] |= 1 << (j % 64);
}
j += 1;
}
t
};
impl Sieve {
pub(super) fn new(limit: u64) -> Sieve {
let bits = usize::try_from(limit / 2 + 1).expect("capacity overflow");
let words = bits.div_ceil(64);
let mut composite = Vec::with_capacity(words);
for w in 0..words {
composite.push(PATTERN[w % PERIOD]);
}
composite[0] = (composite[0] | 1) & !0b1110;
let mut p = 11u64;
while p.saturating_mul(p) <= limit {
let i = (p / 2) as usize;
if composite[i / 64] >> (i % 64) & 1 == 0 {
let step = p as usize;
let mut j = (p * p / 2) as usize;
if step < 64 {
while j < bits {
let w = j / 64;
let end = (64 * w + 64).min(bits);
let mut m = 0u64;
while j < end {
m |= 1 << (j % 64);
j += step;
}
composite[w] |= m;
}
} else {
while j < bits {
composite[j / 64] |= 1 << (j % 64);
j += step;
}
}
}
p += 2;
}
Sieve { composite, limit }
}
#[inline(always)]
pub(super) fn each(&self, lo: u64, hi: u64, mut f: impl FnMut(u64)) {
debug_assert!(hi <= self.limit);
if lo > hi {
return;
}
let (first, last) = ((lo / 2) as usize, (hi.max(1) - 1) as usize / 2);
if first > last {
return;
}
let (w0, w1) = (first / 64, last / 64);
for w in w0..=w1 {
let mut bits = !self.composite[w];
if w == w0 {
bits &= u64::MAX << (first % 64);
}
if w == w1 {
bits &= u64::MAX >> (63 - last % 64);
}
while bits != 0 {
let i = 64 * w + bits.trailing_zeros() as usize;
f(2 * i as u64 + 1);
bits &= bits - 1;
}
}
}
}
pub(super) struct Remainders {
x: u64,
q: u64,
last: u64,
}
impl Remainders {
pub(super) fn of(x: u64) -> Remainders {
Remainders { x, q: 0, last: 0 }
}
#[inline(always)]
pub(super) fn of_divisor(&mut self, d: u64) -> u64 {
if d > self.last {
self.q = self.x / d;
self.last = self.x.checked_div(self.q).unwrap_or(u64::MAX);
}
self.x - self.q * d
}
}