From 6bef6306c06c867f702cd8904cfae99cfc860e73 Mon Sep 17 00:00:00 2001 From: nicoo Date: Sat, 18 Jul 2020 10:42:30 +0200 Subject: [PATCH] factor::numeric::gcd: Avoid redundant u64::trailing_zeros and shifts 7 to 10% faster, according to criterion. --- src/uu/factor/src/numeric.rs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/uu/factor/src/numeric.rs b/src/uu/factor/src/numeric.rs index aaceb6428..814d72612 100644 --- a/src/uu/factor/src/numeric.rs +++ b/src/uu/factor/src/numeric.rs @@ -11,6 +11,7 @@ use num_traits::{ int::PrimInt, ops::wrapping::{WrappingMul, WrappingNeg, WrappingSub}, }; +use std::cmp::min; use std::fmt::{Debug, Display}; use std::mem::swap; @@ -26,20 +27,20 @@ pub fn gcd(mut n: u64, mut m: u64) -> u64 { return n; } - // First, let's extract common factor-2: gcd(2ⁱ n, 2ⁱ m) = 2ⁱ gcd(n, m) - let k = (n | m).trailing_zeros(); - n >>= k; - m >>= k; - - // Second, ensure n is odd; gcd(n, m) = gcd(n/2, m) when n or m is odd - n >>= n.trailing_zeros(); + // Extract common factor-2: gcd(2ⁱ n, 2ⁱ m) = 2ⁱ gcd(n, m) + // and reducing until odd gcd(2ⁱ n, m) = gcd(n, m) if m is odd + let k = { + let k_n = n.trailing_zeros(); + let k_m = m.trailing_zeros(); + n >>= k_n; + m >>= k_m; + min(k_n, k_m) + }; loop { // Invariant: n odd debug_assert!(n % 2 == 1, "n = {} is even", n); - m >>= m.trailing_zeros(); - if n > m { swap(&mut n, &mut m); } @@ -48,6 +49,8 @@ pub fn gcd(mut n: u64, mut m: u64) -> u64 { if m == 0 { return n << k; } + + m >>= m.trailing_zeros(); } }