mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
factor::miller_rabin: Avoid unecessary exponentiation
Instead of computing a^r and a^(n-1) = a^(r 2ⁱ) separately, compute the latter by repeatedly squaring the former. 33.6% performance improvement
This commit is contained in:
parent
543c7b941a
commit
36a2948959
1 changed files with 19 additions and 6 deletions
|
@ -20,6 +20,7 @@ impl Result {
|
|||
|
||||
// Deterministic Miller-Rabin primality-checking algorithm, adapted to extract
|
||||
// (some) dividers; it will fail to factor strong pseudoprimes.
|
||||
#[allow(clippy::many_single_char_names)]
|
||||
pub(crate) fn test<A: Arithmetic>(n: u64) -> Result {
|
||||
use self::Result::*;
|
||||
|
||||
|
@ -30,18 +31,30 @@ pub(crate) fn test<A: Arithmetic>(n: u64) -> Result {
|
|||
return if n == 2 { Prime } else { Composite(2) };
|
||||
}
|
||||
|
||||
let r = (n - 1) >> (n - 1).trailing_zeros();
|
||||
// n-1 = r 2ⁱ
|
||||
let i = (n - 1).trailing_zeros();
|
||||
let r = (n - 1) >> i;
|
||||
|
||||
for a in BASIS.iter() {
|
||||
let mut x = a % n;
|
||||
if x == 0 {
|
||||
let a = a % n;
|
||||
if a == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
if A::pow(x, n - 1, n) != 1 {
|
||||
return Pseudoprime;
|
||||
// x = a^r mod n
|
||||
let mut x = A::pow(a, r, n);
|
||||
|
||||
{
|
||||
// y = ((x²)²...)² i times = x ^ (2ⁱ) = a ^ (r 2ⁱ) = x ^ (n - 1)
|
||||
let mut y = x;
|
||||
for _ in 0..i {
|
||||
y = A::mul(y, y, n)
|
||||
}
|
||||
if y != 1 {
|
||||
return Pseudoprime;
|
||||
};
|
||||
}
|
||||
x = A::pow(x, r, n);
|
||||
|
||||
if x == 1 || x == n - 1 {
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue