use hakmem::prelude::*;
use hakmem::rank9::Rank9;
fn sieve(limit: usize) -> Vec<u64> {
let mut words = vec![u64::MAX; limit.div_ceil(64)];
words.clear_bit(0);
words.clear_bit(1);
for n in 2..=limit.isqrt() {
if words.bit(n) {
for m in (n * n..limit).step_by(n) {
words.clear_bit(m);
}
}
}
if !limit.is_multiple_of(64) {
*words.last_mut().unwrap() &= u64::MAX >> (64 - limit % 64);
}
words
}
fn main() {
let limit = 10_000_000;
let bits = sieve(limit);
let mut counts = vec![0; Rank9::counts_len(bits.len())];
let mut select = vec![0; Rank9::select_len(bits.len())];
let primes = Rank9::build(&bits, &mut counts, &mut select);
assert_eq!(primes.count_ones(), 664_579);
assert_eq!(primes.select(664_579), None);
assert_eq!(primes.rank(1_000_000), 78_498);
assert_eq!(primes.select(78_497), Some(999_983));
assert_eq!(bits.rank(1_000_000), 78_498);
assert_eq!(bits.select(78_497), Some(999_983));
let twins = bits
.positions()
.filter(|&p| bits.next_set_from(p + 1) == Some(p + 2))
.count();
println!(
"{} primes below {limit}, {twins} twin pairs; the directory costs {} words next to {}",
primes.count_ones(),
counts.len() + select.len(),
bits.len()
);
}