diff --git a/src/int.rs b/src/int.rs index ee9fe1c60..3b3d60ee3 100644 --- a/src/int.rs +++ b/src/int.rs @@ -21,6 +21,7 @@ mod div; mod div_uint; mod encoding; mod from; +mod gcd; mod inv_mod; mod mul; mod mul_uint; diff --git a/src/int/gcd.rs b/src/int/gcd.rs new file mode 100644 index 000000000..0df124573 --- /dev/null +++ b/src/int/gcd.rs @@ -0,0 +1,63 @@ +//! Support for computing the greatest common divisor of `Int`s. + +use crate::modular::SafeGcdInverter; +use crate::{Gcd, Int, Odd, PrecomputeInverter, Uint}; + +/// Gcd of two [Int]s +impl Gcd for Int +where + Odd>: PrecomputeInverter>, +{ + type Output = Uint; + + fn gcd(&self, rhs: &Self) -> Self::Output { + self.abs().gcd(&rhs.abs()) + } + + fn gcd_vartime(&self, rhs: &Self) -> Self::Output { + self.abs().gcd_vartime(&rhs.abs()) + } +} + +/// Gcd of an [Int] and a [Uint]. +impl Gcd> for Int +where + Odd>: PrecomputeInverter>, +{ + type Output = Uint; + + fn gcd(&self, rhs: &Uint) -> Self::Output { + self.abs().gcd(rhs) + } + + fn gcd_vartime(&self, rhs: &Uint) -> Self::Output { + self.abs().gcd_vartime(rhs) + } +} + +#[cfg(test)] +mod tests { + use crate::{Gcd, I256, U256}; + + #[test] + fn gcd_always_positive() { + // Two numbers with a shared factor of 61 + let f = I256::from(59i32 * 61); + let g = I256::from(61i32 * 71); + + assert_eq!(U256::from(61u32), f.gcd(&g)); + assert_eq!(U256::from(61u32), f.wrapping_neg().gcd(&g)); + assert_eq!(U256::from(61u32), f.gcd(&g.wrapping_neg())); + assert_eq!(U256::from(61u32), f.wrapping_neg().gcd(&g.wrapping_neg())); + } + + #[test] + fn gcd_int_uint() { + // Two numbers with a shared factor of 61 + let f = I256::from(59i32 * 61); + let g = U256::from(61u32 * 71); + + assert_eq!(U256::from(61u32), f.gcd(&g)); + assert_eq!(U256::from(61u32), f.wrapping_neg().gcd(&g)); + } +} diff --git a/src/uint/gcd.rs b/src/uint/gcd.rs index 6a6e5f812..e293cb222 100644 --- a/src/uint/gcd.rs +++ b/src/uint/gcd.rs @@ -1,6 +1,6 @@ //! Support for computing the greatest common divisor of two `Uint`s. -use crate::{modular::SafeGcdInverter, ConstChoice, Gcd, Odd, PrecomputeInverter, Uint}; +use crate::{modular::SafeGcdInverter, ConstChoice, Gcd, Int, Odd, PrecomputeInverter, Uint}; impl Uint where @@ -75,9 +75,25 @@ where } } +/// Gcd of a [Uint] and an [Int]. +impl Gcd> for Uint +where + Odd>: PrecomputeInverter>, +{ + type Output = Uint; + + fn gcd(&self, rhs: &Int) -> Self::Output { + self.gcd(&rhs.abs()) + } + + fn gcd_vartime(&self, rhs: &Int) -> Self::Output { + self.gcd_vartime(&rhs.abs()) + } +} + #[cfg(test)] mod tests { - use crate::U256; + use crate::{Gcd, I256, U256}; #[test] fn gcd_relatively_prime() { @@ -119,4 +135,15 @@ mod tests { assert_eq!(f, f.gcd(&g)); assert_eq!(f, g.gcd(&f)); } + + #[test] + fn gcd_uint_int() { + // Two numbers with a shared factor of 61 + let f = U256::from(61u32 * 71); + let g = I256::from(59i32 * 61); + + let sixty_one = U256::from(61u32); + assert_eq!(sixty_one, >::gcd(&f, &g)); + assert_eq!(sixty_one, >::gcd(&f, &g.wrapping_neg())); + } }