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 #[must_use]
11 pub const fn lincomb(products: &[(Self, Self)]) -> Self {
12 Self {
13 montgomery_form: lincomb_const_monty_form(
14 products,
15 &MOD::PARAMS.modulus,
16 MOD::PARAMS.mod_neg_inv(),
17 ),
18 phantom: PhantomData,
19 }
20 }
21}
22
23#[cfg(test)]
24mod tests {
25
26 #[cfg(feature = "rand_core")]
27 #[test]
28 fn lincomb_expected() {
29 use super::{ConstMontyForm, ConstMontyParams};
30 use crate::{RandomMod, U256, const_monty_params};
31 use rand_core::SeedableRng;
32 const_monty_params!(
33 P,
34 U256,
35 "7fffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"
36 );
37 let modulus = P::PARAMS.modulus.as_nz_ref();
38
39 let mut rng = chacha20::ChaCha8Rng::seed_from_u64(1);
40 for n in 0..1000 {
41 let a = U256::random_mod_vartime(&mut rng, modulus);
42 let b = U256::random_mod_vartime(&mut rng, modulus);
43 let c = U256::random_mod_vartime(&mut rng, modulus);
44 let d = U256::random_mod_vartime(&mut rng, modulus);
45 let e = U256::random_mod_vartime(&mut rng, modulus);
46 let f = U256::random_mod_vartime(&mut rng, modulus);
47
48 assert_eq!(
49 a.mul_mod(&b, modulus)
50 .add_mod(&c.mul_mod(&d, modulus), modulus)
51 .add_mod(&e.mul_mod(&f, modulus), modulus),
52 ConstMontyForm::<P, { P::LIMBS }>::lincomb(&[
53 (ConstMontyForm::new(&a), ConstMontyForm::new(&b)),
54 (ConstMontyForm::new(&c), ConstMontyForm::new(&d)),
55 (ConstMontyForm::new(&e), ConstMontyForm::new(&f)),
56 ])
57 .retrieve(),
58 "n={n}"
59 );
60 }
61 }
62}