From d576f6fc0e66d7535036f969c8e46f94b9da84b9 Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Tue, 21 Jan 2025 09:30:04 +0100 Subject: [PATCH 1/3] `impl Gcd for Int` --- src/int.rs | 1 + src/int/gcd.rs | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 src/int/gcd.rs 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..f422587a9 --- /dev/null +++ b/src/int/gcd.rs @@ -0,0 +1,63 @@ +//! Support for computing the greatest common divisor of `Int`s. + +use crate::{Gcd, Int, Odd, PrecomputeInverter, Uint}; +use crate::modular::SafeGcdInverter; + +/// 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)); + } +} \ No newline at end of file From 3ce24580721d6faf13d2223a3d5425e9af22d8f8 Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Tue, 21 Jan 2025 09:30:18 +0100 Subject: [PATCH 2/3] `impl Gcd for Uint` --- src/uint/gcd.rs | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/uint/gcd.rs b/src/uint/gcd.rs index 6a6e5f812..290c27ee6 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, Odd, PrecomputeInverter, Uint, Int}; 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())); + } } From 7e0cb164422ae39ecd992b9292cfa2bda1f582a8 Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Tue, 21 Jan 2025 09:32:57 +0100 Subject: [PATCH 3/3] Fix fmt and clippy --- src/int/gcd.rs | 10 +++++----- src/uint/gcd.rs | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/int/gcd.rs b/src/int/gcd.rs index f422587a9..0df124573 100644 --- a/src/int/gcd.rs +++ b/src/int/gcd.rs @@ -1,12 +1,12 @@ //! Support for computing the greatest common divisor of `Int`s. -use crate::{Gcd, Int, Odd, PrecomputeInverter, Uint}; use crate::modular::SafeGcdInverter; +use crate::{Gcd, Int, Odd, PrecomputeInverter, Uint}; /// Gcd of two [Int]s impl Gcd for Int where - Odd>: PrecomputeInverter>, + Odd>: PrecomputeInverter>, { type Output = Uint; @@ -22,12 +22,12 @@ where /// Gcd of an [Int] and a [Uint]. impl Gcd> for Int where - Odd>: PrecomputeInverter>, + Odd>: PrecomputeInverter>, { type Output = Uint; fn gcd(&self, rhs: &Uint) -> Self::Output { - self.abs().gcd(&rhs) + self.abs().gcd(rhs) } fn gcd_vartime(&self, rhs: &Uint) -> Self::Output { @@ -60,4 +60,4 @@ mod tests { assert_eq!(U256::from(61u32), f.gcd(&g)); assert_eq!(U256::from(61u32), f.wrapping_neg().gcd(&g)); } -} \ No newline at end of file +} diff --git a/src/uint/gcd.rs b/src/uint/gcd.rs index 290c27ee6..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, Int}; +use crate::{modular::SafeGcdInverter, ConstChoice, Gcd, Int, Odd, PrecomputeInverter, Uint}; impl Uint where @@ -78,7 +78,7 @@ where /// Gcd of a [Uint] and an [Int]. impl Gcd> for Uint where - Odd>: PrecomputeInverter>, + Odd>: PrecomputeInverter>, { type Output = Uint;