Coverage Report

Created: 2026-11-12 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}