Skip to main content

crypto_bigint/modular/const_monty_form/
lincomb.rs

1//! Linear combinations of integers n Montgomery form with a constant modulus.
2
3use 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    /// Calculate the sum of products of pairs `(a, b)` in `products`.
10    #[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}