Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flatten uint::modular #300

Merged
merged 1 commit into from
Nov 23, 2023
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
2 changes: 1 addition & 1 deletion benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use criterion::{
criterion_group, criterion_main, measurement::Measurement, BatchSize, BenchmarkGroup, Criterion,
};
use crypto_bigint::{
modular::runtime_mod::{DynResidue, DynResidueParams},
modular::{DynResidue, DynResidueParams},
Limb, MultiExponentiate, NonZero, Random, Reciprocal, U128, U2048, U256,
};
use rand_core::OsRng;
Expand Down
1 change: 0 additions & 1 deletion src/uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ mod sqrt;
mod sub;
mod sub_mod;

/// Implements modular arithmetic for constant moduli.
pub mod modular;

#[cfg(feature = "generic-array")]
Expand Down
29 changes: 25 additions & 4 deletions src/uint/modular.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
pub mod constant_mod;
pub mod runtime_mod;

//! Modular arithmetic support.
//!
//! This module provides support for various modular arithmetic operations, implemented in terms of
//! Montgomery form.
//!
//! # Constant moduli
//!
//! The [`Residue`] and [`ResidueParams`] types implement support for modular arithmetic where the
//! modulus is fixed at compile-time.
//!
//! The [`impl_modulus!`][`crate::impl_modulus`] macro can be used to define a compile-time modulus,
//! whereas the [`const_residue!`][`crate::const_residue`] macro can define a [`Residue`] constant.
//!
//! # Dynamic moduli chosen at runtime
//!
//! The [`DynResidue`] and [`DynResidueParams`] types implement support for modular arithmetic where
//! the modulus can vary at runtime.

mod constant_mod;
mod reduction;
mod runtime_mod;

mod add;
mod div_by_2;
Expand All @@ -10,7 +27,11 @@ mod mul;
mod pow;
mod sub;

pub use reduction::montgomery_reduction;
pub use self::{
constant_mod::{Residue, ResidueParams},
reduction::montgomery_reduction,
runtime_mod::{DynResidue, DynResidueParams},
};

/// A generalization for numbers kept in optimized representations (e.g. Montgomery)
/// that can be converted back to the original form.
Expand Down
24 changes: 15 additions & 9 deletions src/uint/modular/constant_mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ use {
#[macro_use]
mod macros;

pub use macros::*;

/// The parameters to efficiently go to and from the Montgomery form for a given odd modulus. An easy way to generate these parameters is using the `impl_modulus!` macro. These parameters are constant, so they cannot be set at runtime.
/// The parameters to efficiently go to and from the Montgomery form for a given odd modulus. An
/// easy way to generate these parameters is using the [`impl_modulus!`][`crate::impl_modulus`]
/// macro. These parameters are constant, so they cannot be set at runtime.
///
/// Unfortunately, `LIMBS` must be generic for now until const generics are stabilized.
pub trait ResidueParams<const LIMBS: usize>:
Expand All @@ -51,7 +51,9 @@ pub trait ResidueParams<const LIMBS: usize>:
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// A residue mod `MOD`, represented using `LIMBS` limbs. The modulus of this residue is constant, so it cannot be set at runtime.
/// A residue mod `MOD`, represented using `LIMBS` limbs. The modulus of this residue is constant,
/// so it cannot be set at runtime.
///
/// Internally, the value is stored in Montgomery form (multiplied by MOD::R) until it is retrieved.
pub struct Residue<MOD, const LIMBS: usize>
where
Expand Down Expand Up @@ -80,7 +82,7 @@ impl<MOD: ResidueParams<LIMBS>, const LIMBS: usize> Residue<MOD, LIMBS> {
phantom: PhantomData,
};

// Internal helper function to generate a residue; this lets us wrap the constructors more cleanly
/// Internal helper function to generate a residue; this lets us cleanly wrap the constructors.
const fn generate_residue(integer: &Uint<LIMBS>) -> Self {
let product = integer.mul_wide(&MOD::R2);
let montgomery_form =
Expand All @@ -92,8 +94,10 @@ impl<MOD: ResidueParams<LIMBS>, const LIMBS: usize> Residue<MOD, LIMBS> {
}
}

/// Instantiates a new `Residue` that represents this `integer` mod `MOD`.
/// If the modulus represented by `MOD` is not odd, this function will panic; use [`new_checked`][`Residue::new_checked`] if you want to be able to detect an invalid modulus.
/// Instantiates a new [`Residue`] that represents this `integer` mod `MOD`.
///
/// If the modulus represented by `MOD` is not odd, this function will panic; use
/// [`new_checked`][`Residue::new_checked`] if you want to be able to detect an invalid modulus.
pub const fn new(integer: &Uint<LIMBS>) -> Self {
// A valid modulus must be odd
if MOD::MODULUS.ct_is_odd().to_u8() == 0 {
Expand All @@ -104,7 +108,9 @@ impl<MOD: ResidueParams<LIMBS>, const LIMBS: usize> Residue<MOD, LIMBS> {
}

/// Instantiates a new `Residue` that represents this `integer` mod `MOD` if the modulus is odd.
/// Returns a `CtOption` that is `None` if the provided modulus is not odd; this is a safer version of [`new`][`Residue::new`], which can panic.
///
/// Returns a [`CtOption`] that is `None` if the provided modulus is not odd; this is a safer
/// version of [`new`][`Residue::new`], which can panic.
// TODO: remove this method when we can use `generic_const_exprs.` to ensure the modulus is
// always valid.
pub fn new_checked(integer: &Uint<LIMBS>) -> CtOption<Self> {
Expand All @@ -115,7 +121,7 @@ impl<MOD: ResidueParams<LIMBS>, const LIMBS: usize> Residue<MOD, LIMBS> {
)
}

/// Retrieves the integer currently encoded in this `Residue`, guaranteed to be reduced.
/// Retrieves the integer currently encoded in this [`Residue`], guaranteed to be reduced.
pub const fn retrieve(&self) -> Uint<LIMBS> {
montgomery_reduction::<LIMBS>(
&(self.montgomery_form, Uint::ZERO),
Expand Down
28 changes: 19 additions & 9 deletions src/uint/modular/constant_mod/macros.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
// TODO: Use `adt_const_params` once stabilized to make a `Residue` generic around a modulus rather than having to implement a ZST + trait
#[macro_export]
/// Implements a modulus with the given name, type, and value, in that specific order. Please `use crypto_bigint::traits::Encoding` to make this work.
/// For example, `impl_modulus!(MyModulus, U256, "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001");` implements a 256-bit modulus named `MyModulus`.
//! Macro support.

/// Implements a modulus with the given name, type, and value, in that specific order. Please
/// `use crypto_bigint::traits::Encoding` to make this work.
///
/// For example,
/// `impl_modulus!(MyModulus, U256, "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001");`
/// implements a 256-bit modulus named `MyModulus`.
///
/// The modulus _must_ be odd, or this will panic.
// TODO: Use `adt_const_params` once stabilized to make a `Residue` generic around a modulus rather
// than having to implement a ZST + trait
#[macro_export]
macro_rules! impl_modulus {
($name:ident, $uint_type:ty, $value:expr) => {
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct $name {}
impl<const DLIMBS: usize>
$crate::modular::constant_mod::ResidueParams<{ <$uint_type>::LIMBS }> for $name
impl<const DLIMBS: usize> $crate::modular::ResidueParams<{ <$uint_type>::LIMBS }> for $name
where
$uint_type: $crate::ConcatMixed<MixedOutput = $crate::Uint<DLIMBS>>,
{
Expand Down Expand Up @@ -46,12 +53,15 @@ macro_rules! impl_modulus {
};
}

#[macro_export]
/// Creates a `Residue` with the given value for a specific modulus.
/// For example, `residue!(U256::from(105u64), MyModulus);` creates a `Residue` for 105 mod `MyModulus`.
///
/// For example, `residue!(U256::from(105u64), MyModulus);` creates a `Residue` for 105 mod
/// `MyModulus`.
///
/// The modulus _must_ be odd, or this will panic.
#[macro_export]
macro_rules! const_residue {
($variable:ident, $modulus:ident) => {
$crate::modular::constant_mod::Residue::<$modulus, { $modulus::LIMBS }>::new(&$variable)
$crate::modular::Residue::<$modulus, { $modulus::LIMBS }>::new(&$variable)
};
}
2 changes: 1 addition & 1 deletion tests/const_residue.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Test to ensure that `const_residue!` works from outside this crate.

use crypto_bigint::{const_residue, impl_modulus, modular::constant_mod::ResidueParams, U64};
use crypto_bigint::{const_residue, impl_modulus, modular::ResidueParams, U64};

impl_modulus!(TestMod, U64, "30e4b8f030ab42f3");

Expand Down
2 changes: 1 addition & 1 deletion tests/proptests.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Equivalence tests between `num-bigint` and `crypto-bigint`

use crypto_bigint::{
modular::runtime_mod::{DynResidue, DynResidueParams},
modular::{DynResidue, DynResidueParams},
CtChoice, Encoding, Limb, NonZero, Word, U256,
};
use num_bigint::BigUint;
Expand Down