Skip to main content

crypto_bigint/modular/fixed_monty_form/
sub.rs

1//! Subtractions between integers in Montgomery form with a modulus set at runtime.
2
3use super::FixedMontyForm;
4use crate::modular::sub::sub_montgomery_form;
5use core::ops::{Sub, SubAssign};
6
7impl<const LIMBS: usize> FixedMontyForm<LIMBS> {
8    /// Subtracts `rhs`.
9    #[must_use]
10    pub const fn sub(&self, rhs: &Self) -> Self {
11        Self {
12            montgomery_form: sub_montgomery_form(
13                &self.montgomery_form,
14                &rhs.montgomery_form,
15                &self.params.modulus,
16            ),
17            params: self.params,
18        }
19    }
20}
21
22impl<const LIMBS: usize> Sub<&FixedMontyForm<LIMBS>> for &FixedMontyForm<LIMBS> {
23    type Output = FixedMontyForm<LIMBS>;
24    fn sub(self, rhs: &FixedMontyForm<LIMBS>) -> FixedMontyForm<LIMBS> {
25        debug_assert_eq!(self.params, rhs.params);
26        self.sub(rhs)
27    }
28}
29
30impl<const LIMBS: usize> Sub<FixedMontyForm<LIMBS>> for &FixedMontyForm<LIMBS> {
31    type Output = FixedMontyForm<LIMBS>;
32    #[allow(clippy::op_ref)]
33    fn sub(self, rhs: FixedMontyForm<LIMBS>) -> FixedMontyForm<LIMBS> {
34        self - &rhs
35    }
36}
37
38impl<const LIMBS: usize> Sub<&FixedMontyForm<LIMBS>> for FixedMontyForm<LIMBS> {
39    type Output = FixedMontyForm<LIMBS>;
40    #[allow(clippy::op_ref)]
41    fn sub(self, rhs: &FixedMontyForm<LIMBS>) -> FixedMontyForm<LIMBS> {
42        &self - rhs
43    }
44}
45
46impl<const LIMBS: usize> Sub<FixedMontyForm<LIMBS>> for FixedMontyForm<LIMBS> {
47    type Output = FixedMontyForm<LIMBS>;
48    fn sub(self, rhs: FixedMontyForm<LIMBS>) -> FixedMontyForm<LIMBS> {
49        &self - &rhs
50    }
51}
52
53impl<const LIMBS: usize> SubAssign<&FixedMontyForm<LIMBS>> for FixedMontyForm<LIMBS> {
54    fn sub_assign(&mut self, rhs: &FixedMontyForm<LIMBS>) {
55        *self = *self - rhs;
56    }
57}
58
59impl<const LIMBS: usize> SubAssign<FixedMontyForm<LIMBS>> for FixedMontyForm<LIMBS> {
60    fn sub_assign(&mut self, rhs: FixedMontyForm<LIMBS>) {
61        *self -= &rhs;
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use crate::{
68        Odd, U256,
69        modular::{FixedMontyForm, FixedMontyParams},
70    };
71
72    #[test]
73    fn sub_overflow() {
74        let params = FixedMontyParams::new_vartime(Odd::<U256>::from_be_hex(
75            "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
76        ));
77
78        let x =
79            U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56");
80        let mut x_mod = FixedMontyForm::new(&x, &params);
81
82        let y =
83            U256::from_be_hex("d5777c45019673125ad240f83094d4252d829516fac8601ed01979ec1ec1a251");
84        let y_mod = FixedMontyForm::new(&y, &params);
85
86        x_mod -= &y_mod;
87
88        let expected =
89            U256::from_be_hex("6f357a71e1d5a03167f34879d469352add829491c6df41ddff65387d7ed56f56");
90
91        assert_eq!(expected, x_mod.retrieve());
92    }
93}