Skip to content

Commit

Permalink
Simplify the Miller-Rabin witness
Browse files Browse the repository at this point in the history
We can just let it do the full `modpow` in REDC.
  • Loading branch information
cuviper committed Mar 3, 2018
1 parent 7b4e975 commit 63889a3
Showing 1 changed file with 10 additions and 39 deletions.
49 changes: 10 additions & 39 deletions examples/primes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,17 @@ fn is_prime(n: &BigUint) -> bool {
}
}

// Test a possible Miller-Rabin witness to the compositeness of n.
//
// Computes a**(n-1) (mod n), and checks if the result gives evidence that
// n is composite. Returning false means that n is likely prime, but not
// necessarily.
let n_m1 = n - 1u32;
let witness = move |a: &BigUint| !a.modpow(&n_m1, n).is_one();

// try series of primes as witnesses
for &(p, u) in &A014233 {
if witness(&BigUint::from(p), n) {
if witness(&BigUint::from(p)) {
return false;
}
if let Some(n) = n64 {
Expand All @@ -104,46 +112,9 @@ fn is_prime(n: &BigUint) -> bool {
let max = n - 3u32;
for _ in 0..10 {
let w = rng.gen_biguint_below(&max) + 2u32;
if witness(&w, n) {
return false;
}
}
true
}

/// Test a possible witness to the compositeness of n.
///
/// Computes a**(n-1) (mod n), and checks if the result gives evidence that
/// n is composite. Returning false means that n is likely prime, but not
/// necessarily.
#[cfg(feature = "rand")]
fn witness(a: &BigUint, n: &BigUint) -> bool {
// let n-1 = (2**t)*u, where t ≥ 1 and u is odd
// TODO `trailing_zeros` would make this trivial
let n_m1 = n - 1u32;
let (t, u) = if n_m1.is_even() {
let mut t = 1usize;
let mut u = n_m1.clone() >> 1;
while u.is_even() {
t += 1;
u >>= 1;
}
(t, u)
} else {
(0, n_m1.clone())
};

let mut x = a.modpow(&u, n);
if x.is_one() || x == n_m1 {
return false;
}

for _ in 1..t {
x = &x * &x % n;
if x == n_m1 {
if witness(&w) {
return false;
}
}

true
}

0 comments on commit 63889a3

Please sign in to comment.