#[inline]
#[allow(dead_code)]
fn mr_mulmod_u64(a: u64, b: u64, m: u64) -> u64 {
((a as u128).wrapping_mul(b as u128) % (m as u128)) as u64
}
#[inline]
#[allow(dead_code)]
fn mr_powmod_u64(mut base: u64, mut exp: u64, m: u64) -> u64 {
if m == 1 {
return 0;
}
let mut acc: u64 = 1;
base %= m;
while exp > 0 {
if exp & 1 == 1 {
acc = mr_mulmod_u64(acc, base, m);
}
exp >>= 1;
if exp > 0 {
base = mr_mulmod_u64(base, base, m);
}
}
acc
}
#[inline]
#[allow(dead_code)]
fn mr_is_composite_witness(n: u64, d: u64, s: u32, a: u64) -> bool {
let mut x = mr_powmod_u64(a, d, n);
if x == 1 || x == n - 1 {
return false;
}
for _ in 0..s.saturating_sub(1) {
x = mr_mulmod_u64(x, x, n);
if x == n - 1 {
return false;
}
}
true
}
#[inline]
#[allow(dead_code)]
fn mr_is_prime_u64(n: u64) -> bool {
if n < 2 {
return false;
}
const SMALL_PRIMES: [u64; 12] = [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 mut d = n - 1;
let mut s: u32 = 0;
while d & 1 == 0 {
d >>= 1;
s += 1;
}
for &a in &SMALL_PRIMES {
if mr_is_composite_witness(n, d, s, a) {
return false;
}
}
true
}
#[inline]
#[allow(dead_code)]
fn mr_is_prime_u32(n: u32) -> bool {
mr_is_prime_u64(n as u64)
}
#[inline]
#[allow(dead_code)]
fn mr_prev_prime_u64(upper: u64) -> u64 {
if upper <= 2 {
return 0;
}
if upper == 3 {
return 2;
}
let mut n = upper - 1;
if n & 1 == 0 {
n -= 1;
}
loop {
if mr_is_prime_u64(n) {
return n;
}
if n <= 3 {
return 2;
}
n -= 2;
}
}
#[inline]
#[allow(dead_code)]
fn mr_next_prime_u64(lower: u64) -> u64 {
if lower < 2 {
return 2;
}
if lower < 3 {
return 3;
}
let largest_u64_prime: u64 = u64::MAX - 58;
if lower >= largest_u64_prime {
return 0;
}
let mut n = lower + 1;
if n & 1 == 0 {
n += 1;
}
loop {
if mr_is_prime_u64(n) {
return n;
}
n += 2;
}
}