crypto_bigint/modular/const_monty_form/
add.rs

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