crypto_bigint/modular/boxed_monty_form/
sub.rs

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