/rust/registry/src/index.crates.io-1949cf8c6b5b557f/crypto-bigint-0.7.10/src/uint/neg.rs
Line | Count | Source |
1 | | use crate::{Choice, Limb, Uint, WideWord, Word, WrappingNeg, word}; |
2 | | |
3 | | impl<const LIMBS: usize> Uint<LIMBS> { |
4 | | /// Perform wrapping negation. |
5 | | #[must_use] |
6 | 639k | pub const fn wrapping_neg(&self) -> Self { |
7 | 639k | self.carrying_neg().0 |
8 | 639k | } |
9 | | |
10 | | /// Perform negation: map `self` to `(self ^ 1111...1111) + 0000...0001`. |
11 | | /// Additionally return whether the carry flag is set on the addition. |
12 | | /// |
13 | | /// Note: the carry is set if and only if `self == Self::ZERO`. |
14 | | #[must_use] |
15 | | #[allow(clippy::cast_possible_truncation)] |
16 | 1.43M | pub const fn carrying_neg(&self) -> (Self, Choice) { |
17 | 1.43M | let mut ret = [Limb::ZERO; LIMBS]; |
18 | 1.43M | let mut carry = 1; |
19 | 1.43M | let mut i = 0; |
20 | 5.27M | while i < LIMBS { |
21 | 3.83M | let r = (!self.limbs[i].0 as WideWord) + carry; |
22 | 3.83M | ret[i] = Limb(r as Word); |
23 | 3.83M | carry = r >> Limb::BITS; |
24 | 3.83M | i += 1; |
25 | 3.83M | } |
26 | 1.43M | (Uint::new(ret), word::choice_from_lsb(carry as Word)) |
27 | 1.43M | } <crypto_bigint::uint::Uint<4>>::carrying_neg Line | Count | Source | 16 | 799k | pub const fn carrying_neg(&self) -> (Self, Choice) { | 17 | 799k | let mut ret = [Limb::ZERO; LIMBS]; | 18 | 799k | let mut carry = 1; | 19 | 799k | let mut i = 0; | 20 | 3.99M | while i < LIMBS { | 21 | 3.19M | let r = (!self.limbs[i].0 as WideWord) + carry; | 22 | 3.19M | ret[i] = Limb(r as Word); | 23 | 3.19M | carry = r >> Limb::BITS; | 24 | 3.19M | i += 1; | 25 | 3.19M | } | 26 | 799k | (Uint::new(ret), word::choice_from_lsb(carry as Word)) | 27 | 799k | } |
<crypto_bigint::uint::Uint<1>>::carrying_neg Line | Count | Source | 16 | 639k | pub const fn carrying_neg(&self) -> (Self, Choice) { | 17 | 639k | let mut ret = [Limb::ZERO; LIMBS]; | 18 | 639k | let mut carry = 1; | 19 | 639k | let mut i = 0; | 20 | 1.27M | while i < LIMBS { | 21 | 639k | let r = (!self.limbs[i].0 as WideWord) + carry; | 22 | 639k | ret[i] = Limb(r as Word); | 23 | 639k | carry = r >> Limb::BITS; | 24 | 639k | i += 1; | 25 | 639k | } | 26 | 639k | (Uint::new(ret), word::choice_from_lsb(carry as Word)) | 27 | 639k | } |
|
28 | | |
29 | | /// Perform wrapping negation, if `negate` is truthy. Otherwise, return `self`. |
30 | | #[must_use] |
31 | 639k | pub const fn wrapping_neg_if(&self, negate: Choice) -> Self { |
32 | 639k | Uint::select(self, &self.wrapping_neg(), negate) |
33 | 639k | } |
34 | | } |
35 | | |
36 | | impl<const LIMBS: usize> WrappingNeg for Uint<LIMBS> { |
37 | | #[inline] |
38 | 0 | fn wrapping_neg(&self) -> Self { |
39 | 0 | self.wrapping_neg() |
40 | 0 | } |
41 | | } |
42 | | |
43 | | #[cfg(test)] |
44 | | mod 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 | | } |