Skip to content

Commit 687b990

Browse files
authored
Add Gcd trait (#499)
Adds a trait for computing the greatest common divisor of two numbers. Uses a fallible impl for the `*Uint` types, and an infallible one for `Odd<*Uint>`.
1 parent 3ca5068 commit 687b990

File tree

4 files changed

+62
-18
lines changed

4 files changed

+62
-18
lines changed

src/traits.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -197,21 +197,18 @@ pub trait FixedInteger: Bounded + ConditionallySelectable + Constants + Copy + I
197197
const LIMBS: usize;
198198
}
199199

200-
/// Obtain a precomputed inverter for efficiently computing modular inversions for a given modulus.
201-
pub trait PrecomputeInverter {
202-
/// Inverter type for integers of this size.
203-
type Inverter: Inverter<Output = Self::Output> + Sized;
204-
205-
/// Output produced by the inverter.
200+
/// Compute greatest common divisor of two integers.
201+
pub trait Gcd<Rhs = Self>: Sized {
202+
/// Output type.
206203
type Output;
207204

208-
/// Obtain a precomputed inverter for `&self` as the modulus, using `Self::one()` as an adjusting parameter.
205+
/// Compute greatest common divisor of `self` and `rhs`.
209206
///
210-
/// Returns `None` if `self` is even.
211-
fn precompute_inverter(&self) -> Self::Inverter;
207+
/// Returns none unless `self` is odd (`rhs` may be even or odd)`.
208+
fn gcd(&self, rhs: &Rhs) -> Self::Output;
212209
}
213210

214-
/// Trait impl'd by precomputed modular inverters.
211+
/// Trait impl'd by precomputed modular inverters obtained via the [`PrecomputeInverter`] trait.
215212
pub trait Inverter {
216213
/// Output of an inversion.
217214
type Output;
@@ -221,6 +218,20 @@ pub trait Inverter {
221218
fn invert(&self, value: &Self::Output) -> CtOption<Self::Output>;
222219
}
223220

221+
/// Obtain a precomputed inverter for efficiently computing modular inversions for a given modulus.
222+
pub trait PrecomputeInverter {
223+
/// Inverter type for integers of this size.
224+
type Inverter: Inverter<Output = Self::Output> + Sized;
225+
226+
/// Output produced by the inverter.
227+
type Output;
228+
229+
/// Obtain a precomputed inverter for `&self` as the modulus, using `Self::one()` as an adjusting parameter.
230+
///
231+
/// Returns `None` if `self` is even.
232+
fn precompute_inverter(&self) -> Self::Inverter;
233+
}
234+
224235
/// Zero values.
225236
pub trait Zero: ConstantTimeEq + Sized {
226237
/// The value `0`.

src/uint/boxed/gcd.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,29 @@
11
//! Support for computing greatest common divisor of two `BoxedUint`s.
22
33
use super::BoxedUint;
4-
use crate::{modular::bernstein_yang, Odd};
4+
use crate::{modular::bernstein_yang, Gcd, Integer, Odd};
5+
use subtle::CtOption;
56

6-
impl Odd<BoxedUint> {
7-
/// Compute the greatest common divisor (GCD) of this number and another.
8-
pub fn gcd(&self, rhs: &BoxedUint) -> BoxedUint {
7+
impl Gcd for BoxedUint {
8+
type Output = CtOption<Self>;
9+
10+
fn gcd(&self, rhs: &Self) -> CtOption<Self> {
11+
let ret = bernstein_yang::boxed::gcd(self, rhs);
12+
CtOption::new(ret, self.is_odd())
13+
}
14+
}
15+
16+
impl Gcd<BoxedUint> for Odd<BoxedUint> {
17+
type Output = BoxedUint;
18+
19+
fn gcd(&self, rhs: &BoxedUint) -> BoxedUint {
920
bernstein_yang::boxed::gcd(self, rhs)
1021
}
1122
}
1223

1324
#[cfg(test)]
1425
mod tests {
15-
use crate::BoxedUint;
26+
use crate::{BoxedUint, Gcd};
1627

1728
#[test]
1829
fn gcd_relatively_prime() {

src/uint/gcd.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Support for computing greatest common divisor of two `Uint`s.
22
3-
use super::Uint;
4-
use crate::{modular::BernsteinYangInverter, ConstCtOption, PrecomputeInverter};
3+
use crate::{modular::BernsteinYangInverter, ConstCtOption, Gcd, Odd, PrecomputeInverter, Uint};
4+
use subtle::CtOption;
55

66
impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Uint<SAT_LIMBS>
77
where
@@ -16,6 +16,28 @@ where
1616
}
1717
}
1818

19+
impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Gcd for Uint<SAT_LIMBS>
20+
where
21+
Self: PrecomputeInverter<Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>>,
22+
{
23+
type Output = CtOption<Uint<SAT_LIMBS>>;
24+
25+
fn gcd(&self, rhs: &Self) -> CtOption<Self> {
26+
self.gcd(rhs).into()
27+
}
28+
}
29+
30+
impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Gcd<Uint<SAT_LIMBS>> for Odd<Uint<SAT_LIMBS>>
31+
where
32+
Self: PrecomputeInverter<Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>>,
33+
{
34+
type Output = Uint<SAT_LIMBS>;
35+
36+
fn gcd(&self, rhs: &Uint<SAT_LIMBS>) -> Uint<SAT_LIMBS> {
37+
<Self as PrecomputeInverter>::Inverter::gcd(self, rhs)
38+
}
39+
}
40+
1941
#[cfg(test)]
2042
mod tests {
2143
use crate::U256;

tests/boxed_uint_proptests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#![cfg(feature = "alloc")]
44

55
use core::cmp::Ordering;
6-
use crypto_bigint::{BoxedUint, CheckedAdd, Integer, Limb, NonZero};
6+
use crypto_bigint::{BoxedUint, CheckedAdd, Gcd, Integer, Limb, NonZero};
77
use num_bigint::{BigUint, ModInverse};
88
use num_integer::Integer as _;
99
use num_traits::identities::One;

0 commit comments

Comments
 (0)