crypto_bigint/modular/const_monty_form/
lincomb.rs1use core::marker::PhantomData;
4
5use super::{ConstMontyForm, ConstMontyParams};
6use crate::modular::lincomb::lincomb_const_monty_form;
7
8impl<MOD: ConstMontyParams<LIMBS>, const LIMBS: usize> ConstMontyForm<MOD, LIMBS> {
9 pub const fn lincomb_vartime(products: &[(Self, Self)]) -> Self {
14 Self {
15 montgomery_form: lincomb_const_monty_form(products, &MOD::MODULUS, MOD::MOD_NEG_INV),
16 phantom: PhantomData,
17 }
18 }
19}
20
21#[cfg(test)]
22mod tests {
23
24 #[cfg(feature = "rand")]
25 #[test]
26 fn lincomb_expected() {
27 use super::{ConstMontyForm, ConstMontyParams};
28 use crate::{impl_modulus, RandomMod, U256};
29 use rand_core::SeedableRng;
30 impl_modulus!(
31 P,
32 U256,
33 "7fffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"
34 );
35 let modulus = P::MODULUS.as_nz_ref();
36
37 let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(1);
38 for n in 0..1000 {
39 let a = U256::random_mod(&mut rng, modulus);
40 let b = U256::random_mod(&mut rng, modulus);
41 let c = U256::random_mod(&mut rng, modulus);
42 let d = U256::random_mod(&mut rng, modulus);
43 let e = U256::random_mod(&mut rng, modulus);
44 let f = U256::random_mod(&mut rng, modulus);
45
46 assert_eq!(
47 a.mul_mod(&b, modulus)
48 .add_mod(&c.mul_mod(&d, modulus), modulus)
49 .add_mod(&e.mul_mod(&f, modulus), modulus),
50 ConstMontyForm::<P, { P::LIMBS }>::lincomb_vartime(&[
51 (ConstMontyForm::new(&a), ConstMontyForm::new(&b)),
52 (ConstMontyForm::new(&c), ConstMontyForm::new(&d)),
53 (ConstMontyForm::new(&e), ConstMontyForm::new(&f)),
54 ])
55 .retrieve(),
56 "n={n}"
57 )
58 }
59 }
60}