Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 21 additions & 10 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,21 +197,18 @@ pub trait FixedInteger: Bounded + ConditionallySelectable + Constants + Copy + I
const LIMBS: usize;
}

/// Obtain a precomputed inverter for efficiently computing modular inversions for a given modulus.
pub trait PrecomputeInverter {
/// Inverter type for integers of this size.
type Inverter: Inverter<Output = Self::Output> + Sized;

/// Output produced by the inverter.
/// Compute greatest common divisor of two integers.
pub trait Gcd<Rhs = Self>: Sized {
/// Output type.
type Output;

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

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

/// Obtain a precomputed inverter for efficiently computing modular inversions for a given modulus.
pub trait PrecomputeInverter {
/// Inverter type for integers of this size.
type Inverter: Inverter<Output = Self::Output> + Sized;

/// Output produced by the inverter.
type Output;

/// Obtain a precomputed inverter for `&self` as the modulus, using `Self::one()` as an adjusting parameter.
///
/// Returns `None` if `self` is even.
fn precompute_inverter(&self) -> Self::Inverter;
}

/// Zero values.
pub trait Zero: ConstantTimeEq + Sized {
/// The value `0`.
Expand Down
21 changes: 16 additions & 5 deletions src/uint/boxed/gcd.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
//! Support for computing greatest common divisor of two `BoxedUint`s.

use super::BoxedUint;
use crate::{modular::bernstein_yang, Odd};
use crate::{modular::bernstein_yang, Gcd, Integer, Odd};
use subtle::CtOption;

impl Odd<BoxedUint> {
/// Compute the greatest common divisor (GCD) of this number and another.
pub fn gcd(&self, rhs: &BoxedUint) -> BoxedUint {
impl Gcd for BoxedUint {
type Output = CtOption<Self>;

fn gcd(&self, rhs: &Self) -> CtOption<Self> {
let ret = bernstein_yang::boxed::gcd(self, rhs);
CtOption::new(ret, self.is_odd())
}
}

impl Gcd<BoxedUint> for Odd<BoxedUint> {
type Output = BoxedUint;

fn gcd(&self, rhs: &BoxedUint) -> BoxedUint {
bernstein_yang::boxed::gcd(self, rhs)
}
}

#[cfg(test)]
mod tests {
use crate::BoxedUint;
use crate::{BoxedUint, Gcd};

#[test]
fn gcd_relatively_prime() {
Expand Down
26 changes: 24 additions & 2 deletions src/uint/gcd.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Support for computing greatest common divisor of two `Uint`s.

use super::Uint;
use crate::{modular::BernsteinYangInverter, ConstCtOption, PrecomputeInverter};
use crate::{modular::BernsteinYangInverter, ConstCtOption, Gcd, Odd, PrecomputeInverter, Uint};
use subtle::CtOption;

impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Uint<SAT_LIMBS>
where
Expand All @@ -16,6 +16,28 @@ where
}
}

impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Gcd for Uint<SAT_LIMBS>
where
Self: PrecomputeInverter<Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>>,
{
type Output = CtOption<Uint<SAT_LIMBS>>;

fn gcd(&self, rhs: &Self) -> CtOption<Self> {
self.gcd(rhs).into()
}
}

impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Gcd<Uint<SAT_LIMBS>> for Odd<Uint<SAT_LIMBS>>
where
Self: PrecomputeInverter<Inverter = BernsteinYangInverter<SAT_LIMBS, UNSAT_LIMBS>>,
{
type Output = Uint<SAT_LIMBS>;

fn gcd(&self, rhs: &Uint<SAT_LIMBS>) -> Uint<SAT_LIMBS> {
<Self as PrecomputeInverter>::Inverter::gcd(self, rhs)
}
}

#[cfg(test)]
mod tests {
use crate::U256;
Expand Down
2 changes: 1 addition & 1 deletion tests/boxed_uint_proptests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#![cfg(feature = "alloc")]

use core::cmp::Ordering;
use crypto_bigint::{BoxedUint, CheckedAdd, Integer, Limb, NonZero};
use crypto_bigint::{BoxedUint, CheckedAdd, Gcd, Integer, Limb, NonZero};
use num_bigint::{BigUint, ModInverse};
use num_integer::Integer as _;
use num_traits::identities::One;
Expand Down