use ruvector_collections::primality::{is_prime_u64, PRIMES_ABOVE_2K, PRIMES_BELOW_2K};
fn sweep_odds_strictly_between<F: FnMut(u64)>(lo: u64, hi: u64, mut f: F) {
let mut n = match lo.checked_add(1) {
Some(n) => n,
None => return,
};
if n & 1 == 0 {
n = match n.checked_add(1) {
Some(n) => n,
None => return,
};
}
while n < hi {
f(n);
n = match n.checked_add(2) {
Some(n) => n,
None => return,
};
}
}
#[test]
fn primality_below_table_cross_check() {
for k in 8u32..=64 {
let p = PRIMES_BELOW_2K[(k - 8) as usize];
assert!(
is_prime_u64(p),
"PRIMES_BELOW_2K[k={k}] = {p} not prime per Miller-Rabin"
);
let hi = if k == 64 {
sweep_odds_strictly_between(p, u64::MAX, |m| {
assert!(
!is_prime_u64(m),
"found prime {m} > PRIMES_BELOW_2K[64] = {p} (within u64)"
);
});
assert!(!is_prime_u64(u64::MAX), "u64::MAX is composite");
continue;
} else {
1u64 << k
};
sweep_odds_strictly_between(p, hi, |m| {
assert!(
!is_prime_u64(m),
"found prime {m} in (PRIMES_BELOW_2K[k={k}] = {p}, 2^{k} = {hi})"
);
});
}
}
#[test]
fn primality_above_table_cross_check() {
for k in 8u32..=63 {
let p = PRIMES_ABOVE_2K[(k - 8) as usize];
assert!(
is_prime_u64(p),
"PRIMES_ABOVE_2K[k={k}] = {p} not prime per Miller-Rabin"
);
let lo = 1u64 << k;
sweep_odds_strictly_between(lo, p, |m| {
assert!(
!is_prime_u64(m),
"found prime {m} in (2^{k} = {lo}, PRIMES_ABOVE_2K[k={k}] = {p})"
);
});
}
assert_eq!(
PRIMES_ABOVE_2K[(64 - 8) as usize],
0,
"PRIMES_ABOVE_2K[64] must be the sentinel 0 — there is no u64 prime > 2^64"
);
}