in crypto/src/prime.rs [213:263]
fn miller_rabin(num: &BigUint, limit: usize) -> bool {
// Iterations recommended for which p < (1/2)^{80}
// 500 bits => 6 iterations
// 1000 bits => 3 iterations
// 2000 bits => 2 iterations
/// Factorize a number n = 2^r * d
/// (i.e., 2^r is the largest power of 2 that divides the candidate).
#[inline]
fn factorize_pow_two(n: &BigUint) -> (u64, BigUint) {
let d = n.clone();
// FIXME: assumption - the power of two is not a BigUint
let num_two_power = d.trailing_zeros().unwrap_or(0);
(num_two_power, d >> num_two_power)
}
assert!(num > &(3.to_biguint().unwrap()));
assert!(num.is_odd());
let one = BigUint::one();
let two = &one + &one;
let (r, d) = factorize_pow_two(&(num - &one));
assert_eq!((BigUint::one() << r) * (&d), num - &one);
let mut rng = rand::thread_rng();
for _ in 0..limit {
// Random sample from [2, n-1) or [2, n-2]
let a = rng.gen_biguint_range(&two, &(num - &one));
let mut x = a.modpow(&d, num).to_bigint().unwrap();
if x.is_one() || x == (num - &one).to_bigint().unwrap() {
continue;
} else {
let mut counter = one.clone();
// Repeat r - 1 times
while counter < r.to_biguint().unwrap() {
x = x.modpow(&(two.to_bigint().unwrap()), &(num.to_bigint().unwrap()));
if x == (num - &one).to_bigint().unwrap() {
break;
}
counter += &one;
}
if counter == r.to_biguint().unwrap() {
return false;
}
}
}
true
}