User:Inthar/Code: Difference between revisions
| Line 694: | Line 694: | ||
} | } | ||
fn gcd( | /// Gives the greatest common denominator of the two inputs, unless that's 2^63. | ||
/// 2^63 doesn't fit in an `i64`, so it returns -2^63, which does. | |||
pub fn gcd(u: i64, v: i64) -> i64 { | |||
// `wrapping_abs` gives a number's absolute value, unless that's 2^63. 2^63 | |||
// won't fit in `i64`, so it gives -2^63 instead. | |||
let mut v = v.wrapping_abs() as u64; | |||
if u == 0 { | |||
return v as i64; | |||
} | |||
let mut u = u.wrapping_abs() as u64; | |||
if v == 0 { | |||
return u as i64; | |||
} | |||
// `|` is bitwise OR. `trailing_zeros` quickly counts a binary number's | |||
// trailing zeros, giving its prime factorization's exponent on two. | |||
let gcd_exponent_on_two = (u | v).trailing_zeros(); | |||
// `>>=` divides the left by two to the power of the right, storing that in | |||
// the left variable. `u` divided by its prime factorization's power of two | |||
// turns it odd. | |||
u >>= u.trailing_zeros(); | |||
v >>= v.trailing_zeros(); | |||
while u != v { | |||
if u < v { | |||
// Swap the variables' values with each other. | |||
core::mem::swap(&mut u, &mut v); | |||
} | |||
u -= v; | |||
u >>= u.trailing_zeros(); | |||
} | |||
// `<<` multiplies the left by two to the power of the right. | |||
(u << gcd_exponent_on_two) as i64 | |||
} | } | ||
| Line 924: | Line 948: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== main.rs === | === main.rs === | ||
<syntaxhighlight lang="rust> | <syntaxhighlight lang="rust> | ||