math: add egcd function implementing the extended Euclidean algorithm (#11203)
parent
90b052b1db
commit
d235de63e2
|
@ -89,6 +89,21 @@ pub fn gcd(a_ i64, b_ i64) i64 {
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// egcd returns (gcd(a, b), x, y) such that |a*x + b*y| = gcd(a, b)
|
||||||
|
pub fn egcd(a i64, b i64) (i64, i64, i64) {
|
||||||
|
mut old_r, mut r := a, b
|
||||||
|
mut old_s, mut s := i64(1), i64(0)
|
||||||
|
mut old_t, mut t := i64(0), i64(1)
|
||||||
|
|
||||||
|
for r != 0 {
|
||||||
|
quot := old_r / r
|
||||||
|
old_r, r = r, old_r % r
|
||||||
|
old_s, s = s, old_s - quot * s
|
||||||
|
old_t, t = t, old_t - quot * t
|
||||||
|
}
|
||||||
|
return if old_r < 0 { -old_r } else { old_r }, old_s, old_t
|
||||||
|
}
|
||||||
|
|
||||||
// lcm calculates least common (non-negative) multiple.
|
// lcm calculates least common (non-negative) multiple.
|
||||||
pub fn lcm(a i64, b i64) i64 {
|
pub fn lcm(a i64, b i64) i64 {
|
||||||
if a == 0 {
|
if a == 0 {
|
||||||
|
|
|
@ -764,3 +764,16 @@ fn test_large_tan() {
|
||||||
assert soclose(f1, f2, 4e-9)
|
assert soclose(f1, f2, 4e-9)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_egcd() {
|
||||||
|
helper := fn (a i64, b i64, expected_g i64) {
|
||||||
|
g, x, y := egcd(a, b)
|
||||||
|
assert g == expected_g
|
||||||
|
assert abs(a * x + b * y) == g
|
||||||
|
}
|
||||||
|
|
||||||
|
helper(6, 9, 3)
|
||||||
|
helper(6, -9, 3)
|
||||||
|
helper(-6, -9, 3)
|
||||||
|
helper(0, 0, 0)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue