Skip to main content

crypto_bigint/modular/boxed_monty_form/
add.rs

1//! Additions between boxed Montgoemery form integers.
2
3use super::BoxedMontyForm;
4use core::ops::{Add, AddAssign};
5
6impl BoxedMontyForm {
7    /// Adds `rhs`.
8    #[must_use]
9    pub fn add(&self, rhs: &Self) -> Self {
10        debug_assert_eq!(self.params, rhs.params);
11
12        Self {
13            montgomery_form: self
14                .montgomery_form
15                .add_mod(&rhs.montgomery_form, self.params.modulus().as_nz_ref()),
16            params: self.params.clone(),
17        }
18    }
19
20    /// Double `self`.
21    #[must_use]
22    pub fn double(&self) -> Self {
23        Self {
24            montgomery_form: self
25                .montgomery_form
26                .double_mod(self.params.modulus().as_nz_ref()),
27            params: self.params.clone(),
28        }
29    }
30}
31
32impl Add<&BoxedMontyForm> for &BoxedMontyForm {
33    type Output = BoxedMontyForm;
34    fn add(self, rhs: &BoxedMontyForm) -> BoxedMontyForm {
35        self.add(rhs)
36    }
37}
38
39impl Add<BoxedMontyForm> for &BoxedMontyForm {
40    type Output = BoxedMontyForm;
41    #[allow(clippy::op_ref)]
42    fn add(self, rhs: BoxedMontyForm) -> BoxedMontyForm {
43        self + &rhs
44    }
45}
46
47impl Add<&BoxedMontyForm> for BoxedMontyForm {
48    type Output = BoxedMontyForm;
49    #[allow(clippy::op_ref)]
50    fn add(self, rhs: &BoxedMontyForm) -> BoxedMontyForm {
51        &self + rhs
52    }
53}
54
55impl Add<BoxedMontyForm> for BoxedMontyForm {
56    type Output = BoxedMontyForm;
57    fn add(self, rhs: BoxedMontyForm) -> BoxedMontyForm {
58        &self + &rhs
59    }
60}
61
62impl AddAssign<&BoxedMontyForm> for BoxedMontyForm {
63    fn add_assign(&mut self, rhs: &BoxedMontyForm) {
64        debug_assert_eq!(self.params, rhs.params);
65        self.montgomery_form
66            .add_mod_assign(&rhs.montgomery_form, self.params.modulus().as_nz_ref());
67    }
68}
69
70impl AddAssign<BoxedMontyForm> for BoxedMontyForm {
71    fn add_assign(&mut self, rhs: BoxedMontyForm) {
72        *self += &rhs;
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use crate::{
79        BoxedUint,
80        modular::{BoxedMontyForm, BoxedMontyParams},
81    };
82    use hex_literal::hex;
83
84    #[test]
85    fn add_overflow() {
86        let modulus = BoxedUint::from_be_slice(
87            &hex!("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"),
88            256,
89        )
90        .unwrap();
91        let params = BoxedMontyParams::new(modulus.to_odd().unwrap());
92
93        let x = BoxedUint::from_be_slice(
94            &hex!("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56"),
95            256,
96        )
97        .unwrap();
98        let mut x_mod = BoxedMontyForm::new(x, &params);
99
100        let y = BoxedUint::from_be_slice(
101            &hex!("d5777c45019673125ad240f83094d4252d829516fac8601ed01979ec1ec1a251"),
102            256,
103        )
104        .unwrap();
105        let y_mod = BoxedMontyForm::new(y, &params);
106
107        x_mod += &y_mod;
108
109        let expected = BoxedUint::from_be_slice(
110            &hex!("1a2472fde50286541d97ca6a3592dd75beb9c9646e40c511b82496cfc3926956"),
111            256,
112        )
113        .unwrap();
114
115        assert_eq!(expected, x_mod.retrieve());
116    }
117}