use crate::integer_square_root_with_binary_search_u64::isqrt;
pub fn prime_pi_fast_half(n: u64) -> u64 {
if n < 2 {
return 0;
}
if n == 2 {
return 1;
}
let sqrt = isqrt(n) as usize;
let n = n as usize;
let size = (sqrt + 1) >> 1;
let half = |j: usize| (j - 1) >> 1;
let mut small = (0..size).collect::<Vec<_>>();
let mut large =
(0..size).map(|i| half(n / (i << 1 | 1))).collect::<Vec<_>>();
for i in (3..=sqrt).step_by(2) {
let i_half = half(i);
if small[i_half] == small[i_half - 1] {
continue;
}
let pi = small[half(i - 1)];
let mut border = sqrt / i;
if border & 1 == 0 {
border -= 1;
}
let n_i = n / i;
for k in (1..=border).step_by(2) {
large[half(k)] -= large[half(k * i + 1)].saturating_sub(pi);
}
for k in (border + 2..=sqrt.min(n_i / i)).step_by(2) {
large[half(k)] -= small[half(n_i / k)] - pi;
}
for k in (i..=border).rev().step_by(2) {
let sub = small[half(k)] - pi;
small[half(k * i)..]
.iter_mut()
.take(half(i) + 1)
.for_each(|j| *j -= sub);
}
}
large[0] as u64 + 1
}
#[cfg(test)]
mod tests {
#[test]
fn test() {
use super::*;
}
}