crypto_bigint/uint/
neg.rs1use crate::{Choice, Limb, Uint, WideWord, Word, WrappingNeg, word};
2
3impl<const LIMBS: usize> Uint<LIMBS> {
4 #[must_use]
6 pub const fn wrapping_neg(&self) -> Self {
7 self.carrying_neg().0
8 }
9
10 #[must_use]
15 #[allow(clippy::cast_possible_truncation)]
16 pub const fn carrying_neg(&self) -> (Self, Choice) {
17 let mut ret = [Limb::ZERO; LIMBS];
18 let mut carry = 1;
19 let mut i = 0;
20 while i < LIMBS {
21 let r = (!self.limbs[i].0 as WideWord) + carry;
22 ret[i] = Limb(r as Word);
23 carry = r >> Limb::BITS;
24 i += 1;
25 }
26 (Uint::new(ret), word::choice_from_lsb(carry as Word))
27 }
28
29 #[must_use]
31 pub const fn wrapping_neg_if(&self, negate: Choice) -> Self {
32 Uint::select(self, &self.wrapping_neg(), negate)
33 }
34}
35
36impl<const LIMBS: usize> WrappingNeg for Uint<LIMBS> {
37 #[inline]
38 fn wrapping_neg(&self) -> Self {
39 self.wrapping_neg()
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use crate::{Choice, U256};
46
47 #[test]
48 fn wrapping_neg() {
49 assert_eq!(U256::ZERO.wrapping_neg(), U256::ZERO);
50 assert_eq!(U256::MAX.wrapping_neg(), U256::ONE);
51 assert_eq!(
52 U256::from_u64(13).wrapping_neg(),
53 U256::from_u64(13).not().saturating_add(&U256::ONE)
54 );
55 assert_eq!(
56 U256::from_u64(42).wrapping_neg(),
57 U256::from_u64(42).saturating_sub(&U256::ONE).not()
58 );
59 }
60
61 #[test]
62 fn carrying_neg() {
63 let (ret, carry) = U256::ZERO.carrying_neg();
64 assert_eq!(ret, U256::ZERO);
65 assert!(carry.to_bool());
66
67 let (ret, carry) = U256::ONE.carrying_neg();
68 assert_eq!(ret, U256::MAX);
69 assert!(!carry.to_bool());
70
71 let (ret, carry) = U256::MAX.carrying_neg();
72 assert_eq!(ret, U256::ONE);
73 assert!(!carry.to_bool());
74 }
75
76 #[test]
77 fn wrapping_neg_if() {
78 let negate = Choice::TRUE;
79 assert_eq!(U256::ZERO.wrapping_neg_if(negate), U256::ZERO);
80 assert_eq!(U256::ONE.wrapping_neg_if(negate), U256::MAX);
81 assert_eq!(U256::MAX.wrapping_neg_if(negate), U256::ONE);
82
83 let do_not_negate = Choice::FALSE;
84 assert_eq!(U256::ZERO.wrapping_neg_if(do_not_negate), U256::ZERO);
85 assert_eq!(U256::ONE.wrapping_neg_if(do_not_negate), U256::ONE);
86 assert_eq!(U256::MAX.wrapping_neg_if(do_not_negate), U256::MAX);
87 }
88}