mod reduction;
pub mod constant_mod;
pub mod runtime_mod;
mod add;
mod div_by_2;
mod inv;
mod mul;
mod pow;
mod sub;
pub use reduction::montgomery_reduction;
pub trait Retrieve {
type Output;
fn retrieve(&self) -> Self::Output;
}
#[cfg(test)]
mod tests {
use crate::{
const_residue, impl_modulus,
modular::{
constant_mod::Residue, constant_mod::ResidueParams, reduction::montgomery_reduction,
},
NonZero, Uint, U256, U64,
};
impl_modulus!(
Modulus1,
U256,
"73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"
);
#[test]
fn test_montgomery_params() {
assert_eq!(
Modulus1::R,
U256::from_be_hex("1824b159acc5056f998c4fefecbc4ff55884b7fa0003480200000001fffffffe")
);
assert_eq!(
Modulus1::R2,
U256::from_be_hex("0748d9d99f59ff1105d314967254398f2b6cedcb87925c23c999e990f3f29c6d")
);
assert_eq!(
Modulus1::MOD_NEG_INV,
U64::from_be_hex("fffffffeffffffff").limbs[0]
);
}
impl_modulus!(
Modulus2,
U256,
"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"
);
#[test]
fn test_reducing_r() {
assert_eq!(
montgomery_reduction::<{ Modulus2::LIMBS }>(
&(Modulus2::R, Uint::ZERO),
&Modulus2::MODULUS,
Modulus2::MOD_NEG_INV
),
Uint::ONE
);
}
#[test]
fn test_reducing_r2() {
assert_eq!(
montgomery_reduction::<{ Modulus2::LIMBS }>(
&(Modulus2::R2, Uint::ZERO),
&Modulus2::MODULUS,
Modulus2::MOD_NEG_INV
),
Modulus2::R
);
}
#[test]
fn test_reducing_r2_wide() {
let (hi, lo) = Modulus2::R.square().split();
assert_eq!(
montgomery_reduction::<{ Modulus2::LIMBS }>(
&(lo, hi),
&Modulus2::MODULUS,
Modulus2::MOD_NEG_INV
),
Modulus2::R
);
}
#[test]
fn test_reducing_xr_wide() {
let x =
U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56");
let product = x.mul_wide(&Modulus2::R);
assert_eq!(
montgomery_reduction::<{ Modulus2::LIMBS }>(
&product,
&Modulus2::MODULUS,
Modulus2::MOD_NEG_INV
),
x
);
}
#[test]
fn test_reducing_xr2_wide() {
let x =
U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56");
let product = x.mul_wide(&Modulus2::R2);
let (lo, hi) = x.mul_wide(&Modulus2::R);
let c = hi.concat(&lo);
let red = c.rem(&NonZero::new(U256::ZERO.concat(&Modulus2::MODULUS)).unwrap());
let (hi, lo) = red.split();
assert_eq!(hi, Uint::ZERO);
assert_eq!(
montgomery_reduction::<{ Modulus2::LIMBS }>(
&product,
&Modulus2::MODULUS,
Modulus2::MOD_NEG_INV
),
lo
);
}
#[test]
fn test_new_retrieve() {
let x =
U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56");
let x_mod = Residue::<Modulus2, { Modulus2::LIMBS }>::new(&x);
assert_eq!(x, x_mod.retrieve());
}
#[test]
fn test_residue_macro() {
let x =
U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56");
assert_eq!(
Residue::<Modulus2, { Modulus2::LIMBS }>::new(&x),
const_residue!(x, Modulus2)
);
}
}