use num_bigint::BigUint;
use crate::common::PRIME_ROOTS;
pub mod big_primality;
pub struct BigPrimeFormula {
k: u32, }
impl BigPrimeFormula {
pub fn new(k: u32) -> Self {
BigPrimeFormula { k }
}
pub fn get_next_prime(&self, start: BigUint) -> BigUint {
let mut i = &start / 210u8;
loop {
for root in PRIME_ROOTS.iter().copied() {
let candidate = &i * 210u8 + BigUint::from(root);
if candidate > start && big_primality::is_likely_big_prime(&candidate, self.k) {
return candidate;
}
}
i += 1u8; }
}
pub fn get_prev_prime(&self, start: BigUint) -> BigUint {
let mut i = (&start + 209u8) / 210u8 + 1u8; loop {
for root in PRIME_ROOTS.iter().rev().copied() {
let candidate = &i * 210u8 + BigUint::from(root);
if candidate < start && big_primality::is_likely_big_prime(&candidate, self.k) {
return candidate;
}
}
i -= 1u8; }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_large_prime() {
let mut next_prime;
let inst = BigPrimeFormula::new(2);
next_prime = inst.get_next_prime(BigUint::from(0x8000_8080_8888_8008_u128));
assert_eq!(next_prime, 0x8000808088888027u128.into());
next_prime = inst.get_next_prime(BigUint::from(0x8000_0000_0000_0000_u128 - 1));
assert_eq!(next_prime, 0x800000000000001Du128.into());
next_prime = inst.get_prev_prime(BigUint::from(u128::MAX));
assert_eq!(
next_prime,
340282366920938463463374607431768211297u128.into()
);
next_prime = inst.get_next_prime(340282366920938463463374607431768211297u128.into());
assert_eq!(next_prime.clone(), BigUint::from(u128::MAX) + 52u8);
next_prime =
inst.get_prev_prime(BigUint::from(340282366920938463463374607431768211297u128));
assert_eq!(
next_prime,
340282366920938463463374607431768211283u128.into()
);
}
#[test]
fn test_huge_prime() {
let next_prime;
let inst = BigPrimeFormula::new(4);
next_prime = inst.get_next_prime(BigUint::from(2u8).pow(300));
let huge_prime_str = "2037035976334486086268445688409378161051468393665936250636140449354381299763336706183397533";
assert_eq!(format!("{next_prime}"), huge_prime_str);
}
#[test]
fn test_rsa_prime() {
let next_prime;
let inst = BigPrimeFormula::new(1000);
let rsa_init = BigUint::from(1u8) << 1023u32
| BigUint::from(1u8) << 250u32
| BigUint::from(1u8) << 64u32;
next_prime = inst.get_next_prime(rsa_init);
let huge_prime_str = "89884656743115795386465259539451236680898848947115328636715040578866337902750481566354238661203768010560056939935696678829394884407208311246423715319737062188883946712432742638151109800623047059726541476042502884419075341171231440738765806664746684135168551983053897680180966479640491965552649659009464271097";
assert_eq!(format!("{next_prime}"), huge_prime_str);
}
}