Skip to main content

crypto_bigint/uint/
neg_mod.rs

1//! [`Uint`] modular negation operations.
2
3use crate::{Limb, NegMod, NonZero, Uint};
4
5impl<const LIMBS: usize> Uint<LIMBS> {
6    /// Computes `-a mod p`.
7    /// Assumes `self` is in `[0, p)`.
8    #[must_use]
9    pub const fn neg_mod(&self, p: &NonZero<Self>) -> Self {
10        let z = self.is_zero();
11        let mut ret = p.as_ref().borrowing_sub(self, Limb::ZERO).0;
12        ret.as_mut_uint_ref().conditional_set_zero(z);
13        ret
14    }
15
16    /// Computes `-a mod p` for the special modulus
17    /// `p = MAX+1-c` where `c` is small enough to fit in a single [`Limb`].
18    #[must_use]
19    pub const fn neg_mod_special(&self, c: Limb) -> Self {
20        Self::ZERO.sub_mod_special(self, c)
21    }
22}
23
24impl<const LIMBS: usize> NegMod for Uint<LIMBS> {
25    type Output = Self;
26
27    fn neg_mod(&self, p: &NonZero<Self>) -> Self {
28        debug_assert!(self < p.as_ref());
29        self.neg_mod(p)
30    }
31}
32
33#[cfg(test)]
34mod tests {
35    use crate::U256;
36
37    #[test]
38    fn neg_mod_random() {
39        let x =
40            U256::from_be_hex("8d16e171674b4e6d8529edba4593802bf30b8cb161dd30aa8e550d41380007c2");
41        let p =
42            U256::from_be_hex("928334a4e4be0843ec225a4c9c61df34bdc7a81513e4b6f76f2bfa3148e2e1b5")
43                .to_nz()
44                .unwrap();
45
46        let actual = x.neg_mod(&p);
47        let expected =
48            U256::from_be_hex("056c53337d72b9d666f86c9256ce5f08cabc1b63b207864ce0d6ecf010e2d9f3");
49
50        assert_eq!(expected, actual);
51    }
52
53    #[test]
54    fn neg_mod_zero() {
55        let x =
56            U256::from_be_hex("0000000000000000000000000000000000000000000000000000000000000000");
57        let p =
58            U256::from_be_hex("928334a4e4be0843ec225a4c9c61df34bdc7a81513e4b6f76f2bfa3148e2e1b5")
59                .to_nz()
60                .unwrap();
61
62        let actual = x.neg_mod(&p);
63        let expected =
64            U256::from_be_hex("0000000000000000000000000000000000000000000000000000000000000000");
65
66        assert_eq!(expected, actual);
67    }
68}