use rayon::prelude::*;
use crate::common::{PRIME_ROOTS, align_to_cycle};
pub mod primality;
#[derive(Debug, PartialEq)]
pub enum PrimalityTest {
MillerRabinDeterministic,
MillerRabinProbabilistic,
}
pub struct PrimeFormula {
k: u32, mode: PrimalityTest, }
impl PrimeFormula {
pub fn new(mode: PrimalityTest, k: u32) -> Self {
PrimeFormula { k, mode }
}
pub fn get_unsorted_primes(&self, start: u128, end: u128) -> Vec<u128> {
let (b_start, b_end) = align_to_cycle(start, end);
let primes: Vec<u128> = PRIME_ROOTS
.into_par_iter()
.flat_map(|root| {
(b_start..b_end)
.map(|i| root as u128 + i * 210)
.filter(|p| *p >= start && *p <= end) .filter(|p| {
primality::is_prime(
p,
self.k,
self.mode == PrimalityTest::MillerRabinDeterministic,
)
})
.collect::<Vec<u128>>() })
.collect();
primes
}
pub fn get_primes(&self, start: u128, end: u128) -> Vec<u128> {
let mut primes = self.get_unsorted_primes(start, end);
primes.par_sort_unstable();
primes
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deterministic_primes() {
let primes;
let inst = PrimeFormula::new(PrimalityTest::MillerRabinDeterministic, 2);
primes = inst.get_primes(11, 1_000_000);
assert_eq!(primes.len(), 78498 - 4); assert_eq!(primes[0], 11); assert_eq!(primes[78498 - 4 - 1], 999_983); }
#[test]
fn test_probabilistic_primes() {
let primes;
let inst = PrimeFormula::new(PrimalityTest::MillerRabinProbabilistic, 4);
primes = inst.get_primes(11, 1_000);
assert_eq!(primes.len(), 168 - 4); assert_eq!(primes[0], 11); assert_eq!(primes[168 - 4 - 1], 997); }
}