crypto_bigint/uint/boxed/
neg_mod.rs1use crate::{BoxedUint, Limb, NegMod};
4use subtle::ConditionallySelectable;
5
6impl BoxedUint {
7 pub fn neg_mod(&self, p: &Self) -> Self {
10 debug_assert_eq!(self.bits_precision(), p.bits_precision());
11 let is_zero = self.is_zero();
12 let mut ret = p.sbb(self, Limb::ZERO).0;
13
14 for i in 0..self.nlimbs() {
15 ret.limbs[i].conditional_assign(&Limb::ZERO, is_zero);
18 }
19
20 ret
21 }
22
23 pub fn neg_mod_special(&self, c: Limb) -> Self {
26 Self::zero_with_precision(self.bits_precision()).sub_mod_special(self, c)
27 }
28}
29
30impl NegMod for BoxedUint {
31 type Output = Self;
32
33 fn neg_mod(&self, p: &Self) -> Self {
34 debug_assert!(self < p);
35 self.neg_mod(p)
36 }
37}
38
39#[cfg(test)]
40mod tests {
41 use crate::BoxedUint;
42 use hex_literal::hex;
43
44 #[test]
45 fn neg_mod_random() {
46 let x = BoxedUint::from_be_slice(
47 &hex!("8d16e171674b4e6d8529edba4593802bf30b8cb161dd30aa8e550d41380007c2"),
48 256,
49 )
50 .unwrap();
51 let p = BoxedUint::from_be_slice(
52 &hex!("928334a4e4be0843ec225a4c9c61df34bdc7a81513e4b6f76f2bfa3148e2e1b5"),
53 256,
54 )
55 .unwrap();
56
57 let actual = x.neg_mod(&p);
58 let expected = BoxedUint::from_be_slice(
59 &hex!("056c53337d72b9d666f86c9256ce5f08cabc1b63b207864ce0d6ecf010e2d9f3"),
60 256,
61 )
62 .unwrap();
63
64 assert_eq!(expected, actual);
65 }
66
67 #[test]
68 fn neg_mod_zero() {
69 let x = BoxedUint::from_be_slice(
70 &hex!("0000000000000000000000000000000000000000000000000000000000000000"),
71 256,
72 )
73 .unwrap();
74 let p = BoxedUint::from_be_slice(
75 &hex!("928334a4e4be0843ec225a4c9c61df34bdc7a81513e4b6f76f2bfa3148e2e1b5"),
76 256,
77 )
78 .unwrap();
79
80 let actual = x.neg_mod(&p);
81 let expected = BoxedUint::from_be_slice(
82 &hex!("0000000000000000000000000000000000000000000000000000000000000000"),
83 256,
84 )
85 .unwrap();
86
87 assert_eq!(expected, actual);
88 }
89}