use rand::Rng;
pub fn is_prime(n: u64, iterations: usize) -> bool {
if n < 2 {
return false;
}
if n == 2 || n == 3 {
return true;
}
if n.is_multiple_of(2) {
return false;
}
let (r, d) = factor_power_of_two(n - 1);
let mut rng = rand::thread_rng();
'witness_loop: for _ in 0..iterations {
let a = rng.gen_range(2..n - 1);
let mut x = mod_pow(a, d, n);
if x == 1 || x == n - 1 {
continue 'witness_loop;
}
for _ in 0..r - 1 {
x = mod_mul(x, x, n);
if x == n - 1 {
continue 'witness_loop;
}
}
return false;
}
true
}
pub fn is_prime_deterministic(n: u64) -> bool {
if n < 2 {
return false;
}
if n == 2 || n == 3 {
return true;
}
if n.is_multiple_of(2) {
return false;
}
let small_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37];
for &p in &small_primes {
if n == p {
return true;
}
if n.is_multiple_of(p) {
return false;
}
}
let witnesses = if n < 2_047 {
vec![2]
} else if n < 1_373_653 {
vec![2, 3]
} else if n < 9_080_191 {
vec![31, 73]
} else if n < 25_326_001 {
vec![2, 3, 5]
} else if n < 3_215_031_751 {
vec![2, 3, 5, 7]
} else if n < 4_759_123_141 {
vec![2, 7, 61]
} else if n < 1_122_004_669_633 {
vec![2, 13, 23, 1662803]
} else if n < 2_152_302_898_747 {
vec![2, 3, 5, 7, 11]
} else if n < 3_474_749_660_383 {
vec![2, 3, 5, 7, 11, 13]
} else if n < 341_550_071_728_321 {
vec![2, 3, 5, 7, 11, 13, 17]
} else {
vec![2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]
};
let (r, d) = factor_power_of_two(n - 1);
'witness_loop: for a in witnesses {
if a >= n {
continue;
}
let mut x = mod_pow(a, d, n);
if x == 1 || x == n - 1 {
continue 'witness_loop;
}
for _ in 0..r - 1 {
x = mod_mul(x, x, n);
if x == n - 1 {
continue 'witness_loop;
}
}
return false;
}
true
}
pub fn generate_prime(bits: u32, iterations: usize) -> u64 {
assert!(bits > 2 && bits <= 63, "Bit length must be between 3 and 63");
let mut rng = rand::thread_rng();
loop {
let mut candidate = rng.gen_range(1u64 << (bits - 1)..(1u64 << bits));
candidate |= 1;
candidate |= 1u64 << (bits - 1);
if is_prime(candidate, iterations) {
return candidate;
}
}
}
fn factor_power_of_two(mut n: u64) -> (u64, u64) {
let mut r = 0;
while n.is_multiple_of(2) {
n /= 2;
r += 1;
}
(r, n)
}
fn mod_pow(mut base: u64, mut exp: u64, m: u64) -> u64 {
let mut result = 1u64;
base %= m;
while exp > 0 {
if exp % 2 == 1 {
result = mod_mul(result, base, m);
}
base = mod_mul(base, base, m);
exp /= 2;
}
result
}
fn mod_mul(a: u64, b: u64, m: u64) -> u64 {
((a as u128 * b as u128) % m as u128) as u64
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_small_primes() {
let primes = vec![2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31];
for p in primes {
assert!(is_prime(p, 10), "{} should be prime", p);
assert!(is_prime_deterministic(p), "{} should be prime (deterministic)", p);
}
}
#[test]
fn test_composites() {
let composites = vec![4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20];
for c in composites {
assert!(!is_prime(c, 10), "{} should be composite", c);
assert!(!is_prime_deterministic(c), "{} should be composite (deterministic)", c);
}
}
#[test]
fn test_large_prime() {
let large_prime = 1_000_000_007u64;
assert!(is_prime(large_prime, 20));
assert!(is_prime_deterministic(large_prime));
}
#[test]
fn test_carmichael_number() {
assert!(!is_prime(561, 20));
assert!(!is_prime_deterministic(561));
}
#[test]
fn test_generate_prime() {
let prime = generate_prime(16, 20);
assert!(is_prime_deterministic(prime));
assert!(prime >= 1 << 15 && prime < 1 << 16);
}
}