Skip to content

Commit 7fbf363

Browse files
authored
Int - Gcd (#748)
* `impl Gcd for Int` * `impl Gcd<Int> for Uint`
1 parent 91f184f commit 7fbf363

File tree

3 files changed

+93
-2
lines changed

3 files changed

+93
-2
lines changed

src/int.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ mod div;
2121
mod div_uint;
2222
mod encoding;
2323
mod from;
24+
mod gcd;
2425
mod inv_mod;
2526
mod mul;
2627
mod mul_uint;

src/int/gcd.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//! Support for computing the greatest common divisor of `Int`s.
2+
3+
use crate::modular::SafeGcdInverter;
4+
use crate::{Gcd, Int, Odd, PrecomputeInverter, Uint};
5+
6+
/// Gcd of two [Int]s
7+
impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Gcd for Int<SAT_LIMBS>
8+
where
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+
22+
/// Gcd of an [Int] and a [Uint].
23+
impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Gcd<Uint<SAT_LIMBS>> for Int<SAT_LIMBS>
24+
where
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)]
39+
mod tests {
40+
use crate::{Gcd, I256, U256};
41+
42+
#[test]
43+
fn gcd_always_positive() {
44+
// Two numbers with a shared factor of 61
45+
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+
// Two numbers with a shared factor of 61
57+
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+
}

src/uint/gcd.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Support for computing the greatest common divisor of two `Uint`s.
22
3-
use crate::{modular::SafeGcdInverter, ConstChoice, Gcd, Odd, PrecomputeInverter, Uint};
3+
use crate::{modular::SafeGcdInverter, ConstChoice, Gcd, Int, Odd, PrecomputeInverter, Uint};
44

55
impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Uint<SAT_LIMBS>
66
where
@@ -75,9 +75,25 @@ where
7575
}
7676
}
7777

78+
/// Gcd of a [Uint] and an [Int].
79+
impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Gcd<Int<SAT_LIMBS>> for Uint<SAT_LIMBS>
80+
where
81+
Odd<Uint<SAT_LIMBS>>: PrecomputeInverter<Inverter = SafeGcdInverter<SAT_LIMBS, UNSAT_LIMBS>>,
82+
{
83+
type Output = Uint<SAT_LIMBS>;
84+
85+
fn gcd(&self, rhs: &Int<SAT_LIMBS>) -> Self::Output {
86+
self.gcd(&rhs.abs())
87+
}
88+
89+
fn gcd_vartime(&self, rhs: &Int<SAT_LIMBS>) -> Self::Output {
90+
self.gcd_vartime(&rhs.abs())
91+
}
92+
}
93+
7894
#[cfg(test)]
7995
mod tests {
80-
use crate::U256;
96+
use crate::{Gcd, I256, U256};
8197

8298
#[test]
8399
fn gcd_relatively_prime() {
@@ -119,4 +135,15 @@ mod tests {
119135
assert_eq!(f, f.gcd(&g));
120136
assert_eq!(f, g.gcd(&f));
121137
}
138+
139+
#[test]
140+
fn gcd_uint_int() {
141+
// Two numbers with a shared factor of 61
142+
let f = U256::from(61u32 * 71);
143+
let g = I256::from(59i32 * 61);
144+
145+
let sixty_one = U256::from(61u32);
146+
assert_eq!(sixty_one, <U256 as Gcd<I256>>::gcd(&f, &g));
147+
assert_eq!(sixty_one, <U256 as Gcd<I256>>::gcd(&f, &g.wrapping_neg()));
148+
}
122149
}

0 commit comments

Comments
 (0)