crypto_bigint_syncless/modular/boxed_monty_form/
sub.rs

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