use crate::gaussian_integer::GaussianInteger;
use crate::test_util::gaussian_integer::factorization::remove_one_plus_i::*;
use malachite_base::num::arithmetic::traits::{AbsSquared, CanonicalizeUnit};
pub fn gaussian_integer_gcd_euclidean(x: &GaussianInteger, y: &GaussianInteger) -> GaussianInteger {
let mut x = x.clone();
let mut y = y.clone();
while y != 0u32 {
let r = &x % &y;
x = y;
y = r;
}
x.canonicalize_unit()
}
pub fn gaussian_integer_gcd_binary(x: &GaussianInteger, y: &GaussianInteger) -> GaussianInteger {
if *x == 0u32 {
return y.clone().canonicalize_unit();
} else if *y == 0u32 {
return x.clone().canonicalize_unit();
}
let (mut x, hx) = x.remove_one_plus_i();
let (mut y, hy) = y.remove_one_plus_i();
if (&x).abs_squared() < (&y).abs_squared() {
core::mem::swap(&mut x, &mut y);
}
while y != 0u32 {
let iy = GaussianInteger {
real: -&y.imaginary,
imaginary: y.real.clone(),
};
let candidates = [&x + &y, &x - &y, &x + &iy, &x - &iy];
let z = candidates
.into_iter()
.min_by_key(|z| z.abs_squared())
.unwrap();
x = z.remove_one_plus_i().0;
if (&x).abs_squared() < (&y).abs_squared() {
core::mem::swap(&mut x, &mut y);
}
}
(x * gaussian_integer_one_plus_i_pow(hx.min(hy))).canonicalize_unit()
}