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