crypto_bigint/modular/monty_form/
add.rs

1//! Additions between integers in Montgomery form with a modulus set at runtime.
2
3use super::MontyForm;
4use crate::modular::add::{add_montgomery_form, double_montgomery_form};
5use core::ops::{Add, AddAssign};
6
7impl<const LIMBS: usize> MontyForm<LIMBS> {
8    /// Adds `rhs`.
9    pub const fn add(&self, rhs: &Self) -> Self {
10        Self {
11            montgomery_form: add_montgomery_form(
12                &self.montgomery_form,
13                &rhs.montgomery_form,
14                &self.params.modulus,
15            ),
16            params: self.params,
17        }
18    }
19
20    /// Double `self`.
21    pub const fn double(&self) -> Self {
22        Self {
23            montgomery_form: double_montgomery_form(&self.montgomery_form, &self.params.modulus),
24            params: self.params,
25        }
26    }
27}
28
29impl<const LIMBS: usize> Add<&MontyForm<LIMBS>> for &MontyForm<LIMBS> {
30    type Output = MontyForm<LIMBS>;
31    fn add(self, rhs: &MontyForm<LIMBS>) -> MontyForm<LIMBS> {
32        debug_assert_eq!(self.params, rhs.params);
33        self.add(rhs)
34    }
35}
36
37impl<const LIMBS: usize> Add<MontyForm<LIMBS>> for &MontyForm<LIMBS> {
38    type Output = MontyForm<LIMBS>;
39    #[allow(clippy::op_ref)]
40    fn add(self, rhs: MontyForm<LIMBS>) -> MontyForm<LIMBS> {
41        self + &rhs
42    }
43}
44
45impl<const LIMBS: usize> Add<&MontyForm<LIMBS>> for MontyForm<LIMBS> {
46    type Output = MontyForm<LIMBS>;
47    #[allow(clippy::op_ref)]
48    fn add(self, rhs: &MontyForm<LIMBS>) -> MontyForm<LIMBS> {
49        &self + rhs
50    }
51}
52
53impl<const LIMBS: usize> Add<MontyForm<LIMBS>> for MontyForm<LIMBS> {
54    type Output = MontyForm<LIMBS>;
55    fn add(self, rhs: MontyForm<LIMBS>) -> MontyForm<LIMBS> {
56        &self + &rhs
57    }
58}
59
60impl<const LIMBS: usize> AddAssign<&MontyForm<LIMBS>> for MontyForm<LIMBS> {
61    fn add_assign(&mut self, rhs: &MontyForm<LIMBS>) {
62        *self = *self + rhs;
63    }
64}
65
66impl<const LIMBS: usize> AddAssign<MontyForm<LIMBS>> for MontyForm<LIMBS> {
67    fn add_assign(&mut self, rhs: MontyForm<LIMBS>) {
68        *self += &rhs;
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use crate::{
75        modular::{MontyForm, MontyParams},
76        Odd, U256,
77    };
78
79    #[test]
80    fn add_overflow() {
81        let params = MontyParams::new_vartime(Odd::<U256>::from_be_hex(
82            "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
83        ));
84
85        let x =
86            U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56");
87        let mut x_mod = MontyForm::new(&x, params);
88
89        let y =
90            U256::from_be_hex("d5777c45019673125ad240f83094d4252d829516fac8601ed01979ec1ec1a251");
91        let y_mod = MontyForm::new(&y, params);
92
93        x_mod += &y_mod;
94
95        let expected =
96            U256::from_be_hex("1a2472fde50286541d97ca6a3592dd75beb9c9646e40c511b82496cfc3926956");
97
98        assert_eq!(expected, x_mod.retrieve());
99    }
100}