Skip to main content

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