1use crate::modular::SafeGcdInverter;
4use crate::{Gcd, Int, Odd, PrecomputeInverter, Uint};
5
6impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Gcd for Int<SAT_LIMBS>
8where
9 Odd<Uint<SAT_LIMBS>>: PrecomputeInverter<Inverter = SafeGcdInverter<SAT_LIMBS, UNSAT_LIMBS>>,
10{
11 type Output = Uint<SAT_LIMBS>;
12
13 fn gcd(&self, rhs: &Self) -> Self::Output {
14 self.abs().gcd(&rhs.abs())
15 }
16
17 fn gcd_vartime(&self, rhs: &Self) -> Self::Output {
18 self.abs().gcd_vartime(&rhs.abs())
19 }
20}
21
22impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Gcd<Uint<SAT_LIMBS>> for Int<SAT_LIMBS>
24where
25 Odd<Uint<SAT_LIMBS>>: PrecomputeInverter<Inverter = SafeGcdInverter<SAT_LIMBS, UNSAT_LIMBS>>,
26{
27 type Output = Uint<SAT_LIMBS>;
28
29 fn gcd(&self, rhs: &Uint<SAT_LIMBS>) -> Self::Output {
30 self.abs().gcd(rhs)
31 }
32
33 fn gcd_vartime(&self, rhs: &Uint<SAT_LIMBS>) -> Self::Output {
34 self.abs().gcd_vartime(rhs)
35 }
36}
37
38#[cfg(test)]
39mod tests {
40 use crate::{Gcd, I256, U256};
41
42 #[test]
43 fn gcd_always_positive() {
44 let f = I256::from(59i32 * 61);
46 let g = I256::from(61i32 * 71);
47
48 assert_eq!(U256::from(61u32), f.gcd(&g));
49 assert_eq!(U256::from(61u32), f.wrapping_neg().gcd(&g));
50 assert_eq!(U256::from(61u32), f.gcd(&g.wrapping_neg()));
51 assert_eq!(U256::from(61u32), f.wrapping_neg().gcd(&g.wrapping_neg()));
52 }
53
54 #[test]
55 fn gcd_int_uint() {
56 let f = I256::from(59i32 * 61);
58 let g = U256::from(61u32 * 71);
59
60 assert_eq!(U256::from(61u32), f.gcd(&g));
61 assert_eq!(U256::from(61u32), f.wrapping_neg().gcd(&g));
62 }
63}