crypto_bigint/uint/boxed/
neg.rs1use crate::{BoxedUint, Choice, CtAssign, Limb, WideWord, Word, WrappingNeg};
4
5impl BoxedUint {
6 #[must_use]
8 #[allow(clippy::cast_possible_truncation)]
9 pub fn wrapping_neg(&self) -> Self {
10 let mut ret = vec![Limb::ZERO; self.nlimbs()];
11 let mut carry = 1;
12
13 for i in 0..self.nlimbs() {
14 let r = WideWord::from(!self.limbs[i].0) + carry;
15 ret[i] = Limb(r as Word);
16 carry = r >> Limb::BITS;
17 }
18
19 ret.into()
20 }
21
22 #[allow(clippy::cast_possible_truncation)]
25 pub(crate) fn conditional_wrapping_neg_assign(&mut self, choice: Choice) {
26 let mut carry = 1;
27
28 for i in 0..self.nlimbs() {
29 let r = WideWord::from(!self.limbs[i].0) + carry;
30 self.limbs[i].ct_assign(&Limb(r as Word), choice);
31 carry = r >> Limb::BITS;
32 }
33 }
34}
35
36impl WrappingNeg for BoxedUint {
37 fn wrapping_neg(&self) -> Self {
38 self.wrapping_neg()
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use crate::{BoxedUint, Choice, CtNeg};
45
46 #[test]
47 fn ct_neg() {
48 let a = BoxedUint::from(123u64);
49 assert_eq!(a.ct_neg(Choice::FALSE), a);
50 assert_eq!(a.ct_neg(Choice::TRUE), a.wrapping_neg());
51 }
52
53 #[test]
54 fn ct_neg_assign() {
55 let mut a = BoxedUint::from(123u64);
56 let control = a.clone();
57
58 a.ct_neg_assign(Choice::FALSE);
59 assert_eq!(a, control);
60
61 a.ct_neg_assign(Choice::TRUE);
62 assert_ne!(a, control);
63 assert_eq!(a, control.wrapping_neg());
64 }
65
66 #[cfg(feature = "subtle")]
67 #[test]
68 fn subtle_conditional_negate() {
69 use subtle::ConditionallyNegatable;
70 let mut a = BoxedUint::from(123u64);
71 let control = a.clone();
72
73 a.conditional_negate(Choice::FALSE.into());
74 assert_eq!(a, control);
75
76 a.conditional_negate(Choice::TRUE.into());
77 assert_ne!(a, control);
78 assert_eq!(a, control.wrapping_neg());
79 }
80
81 #[test]
82 fn wrapping_neg() {
83 assert_eq!(BoxedUint::zero().wrapping_neg(), BoxedUint::zero());
84 assert_eq!(BoxedUint::max(64).wrapping_neg(), BoxedUint::one());
85 }
94}