pub fn prime_sieve(limit: u64) -> Vec<u64> {
if limit < 2 {
return vec![];
}
let odd_count = limit.div_ceil(2) as usize; let word_count = odd_count.div_ceil(64);
let mut sieve = vec![0u64; word_count];
sieve[0] |= 1;
let mut p = 3u64;
while p.saturating_mul(p) <= limit {
let pi = ((p - 1) / 2) as usize; if sieve[pi / 64] & (1 << (pi % 64)) == 0 {
let mut multiple = p * p;
while multiple <= limit {
let mi = ((multiple - 1) / 2) as usize;
sieve[mi / 64] |= 1 << (mi % 64);
multiple = match multiple.checked_add(2 * p) {
Some(v) => v,
None => break,
};
}
}
p += 2;
}
let mut primes = vec![2u64];
for i in 1..odd_count {
if sieve[i / 64] & (1 << (i % 64)) == 0 {
primes.push(2 * i as u64 + 1);
}
}
primes
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sieve_empty_for_small_limits() {
assert!(prime_sieve(0).is_empty());
assert!(prime_sieve(1).is_empty());
}
#[test]
fn sieve_two_is_first_prime() {
assert_eq!(prime_sieve(2), vec![2]);
}
#[test]
fn sieve_up_to_10() {
assert_eq!(prime_sieve(10), vec![2, 3, 5, 7]);
}
#[test]
fn sieve_up_to_100() {
let expected = vec![
2u64, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79,
83, 89, 97,
];
assert_eq!(prime_sieve(100), expected);
}
#[test]
fn sieve_count_1000() {
assert_eq!(prime_sieve(1000).len(), 168);
}
#[test]
fn sieve_count_10000() {
assert_eq!(prime_sieve(10_000).len(), 1229);
}
}