use std::collections::BTreeMap;
use crate::prim::{typ::*, mpz::*};
pub struct EraPrimeTableUI {
pub maxera: mp_size_t,
pub era: mpz_s,
pub tbl: BTreeMap<mp_size_t, mpz_s>
}
impl EraPrimeTableUI {
pub fn new(maxera: mp_size_t) -> Self {
let mut era = mpz_s::from(0); let even64 = maxera + 63 - (maxera - 1) % 64; era.setbit(even64 as ui_t); (0..=1).for_each(|i| { era.setbit(i); });
(2..=(maxera as f64).sqrt() as ui_t).for_each(|i| { if era.tstbit(i) { return; } (2..=maxera as ui_t / i).for_each(|j| {
if !era.tstbit(i * j) { era.setbit(i * j); }
});
});
let mut tbl = BTreeMap::<mp_size_t, mpz_s>::new();
let _t = (2..maxera as ui_t).fold((&mut tbl, 0), |(tbl, cnt), i| {
if era.tstbit(i) { (tbl, cnt) }
else { tbl.insert(cnt, mpz_s::from(i)); (tbl, cnt + 1) }
});
EraPrimeTableUI{maxera, era, tbl}
}
#[inline]
pub fn get_maxera(&self) -> mp_size_t {
self.maxera
}
#[inline]
pub fn is_prime(&self, n: mp_size_t) -> Option<bool> {
if n >= self.maxera { None } else { Some(!self.era.tstbit(n as ui_t)) }
}
#[inline]
pub fn nprimes(&self) -> mp_size_t {
self.tbl.len()
}
pub fn nth_prime(&mut self, n: mp_size_t, gen: int_t) -> mpz_r {
let mut m = self.tbl.len() - 1;
if n <= m { self.tbl.get(&n).expect("prime in the table") }
else {
match gen {
0 => panic!("tbl does not have nth prime"),
_ => {
while m < n {
let p = self.tbl.get(&m).expect("generate next of last prime");
let q = p.nextprime();
if q.probab_prime_p(3) >= gen {
m += 1;
self.tbl.insert(m, q);
}
}
self.tbl.get(&m).expect("nth prime")
}
}
}
}
}