mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-31 13:07:46 +00:00
factor::numeric::gcd: Avoid redundant u64::trailing_zeros and shifts
7 to 10% faster, according to criterion.
This commit is contained in:
parent
29d45e472d
commit
6bef6306c0
1 changed files with 12 additions and 9 deletions
|
@ -11,6 +11,7 @@ use num_traits::{
|
||||||
int::PrimInt,
|
int::PrimInt,
|
||||||
ops::wrapping::{WrappingMul, WrappingNeg, WrappingSub},
|
ops::wrapping::{WrappingMul, WrappingNeg, WrappingSub},
|
||||||
};
|
};
|
||||||
|
use std::cmp::min;
|
||||||
use std::fmt::{Debug, Display};
|
use std::fmt::{Debug, Display};
|
||||||
use std::mem::swap;
|
use std::mem::swap;
|
||||||
|
|
||||||
|
@ -26,20 +27,20 @@ pub fn gcd(mut n: u64, mut m: u64) -> u64 {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, let's extract common factor-2: gcd(2ⁱ n, 2ⁱ m) = 2ⁱ gcd(n, m)
|
// Extract common factor-2: gcd(2ⁱ n, 2ⁱ m) = 2ⁱ gcd(n, m)
|
||||||
let k = (n | m).trailing_zeros();
|
// and reducing until odd gcd(2ⁱ n, m) = gcd(n, m) if m is odd
|
||||||
n >>= k;
|
let k = {
|
||||||
m >>= k;
|
let k_n = n.trailing_zeros();
|
||||||
|
let k_m = m.trailing_zeros();
|
||||||
// Second, ensure n is odd; gcd(n, m) = gcd(n/2, m) when n or m is odd
|
n >>= k_n;
|
||||||
n >>= n.trailing_zeros();
|
m >>= k_m;
|
||||||
|
min(k_n, k_m)
|
||||||
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// Invariant: n odd
|
// Invariant: n odd
|
||||||
debug_assert!(n % 2 == 1, "n = {} is even", n);
|
debug_assert!(n % 2 == 1, "n = {} is even", n);
|
||||||
|
|
||||||
m >>= m.trailing_zeros();
|
|
||||||
|
|
||||||
if n > m {
|
if n > m {
|
||||||
swap(&mut n, &mut m);
|
swap(&mut n, &mut m);
|
||||||
}
|
}
|
||||||
|
@ -48,6 +49,8 @@ pub fn gcd(mut n: u64, mut m: u64) -> u64 {
|
||||||
if m == 0 {
|
if m == 0 {
|
||||||
return n << k;
|
return n << k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m >>= m.trailing_zeros();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue