Coverage Report

Created: 2026-01-13 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/crypto-bigint-0.5.5/src/uint/add.rs
Line
Count
Source
1
//! [`Uint`] addition operations.
2
3
use crate::{Checked, CheckedAdd, CtChoice, Limb, Uint, Wrapping, Zero};
4
use core::ops::{Add, AddAssign};
5
use subtle::CtOption;
6
7
impl<const LIMBS: usize> Uint<LIMBS> {
8
    /// Computes `a + b + carry`, returning the result along with the new carry.
9
    #[inline(always)]
10
6.35k
    pub const fn adc(&self, rhs: &Self, mut carry: Limb) -> (Self, Limb) {
11
6.35k
        let mut limbs = [Limb::ZERO; LIMBS];
12
6.35k
        let mut i = 0;
13
14
31.7k
        while i < LIMBS {
15
25.4k
            let (w, c) = self.limbs[i].adc(rhs.limbs[i], carry);
16
25.4k
            limbs[i] = w;
17
25.4k
            carry = c;
18
25.4k
            i += 1;
19
25.4k
        }
20
21
6.35k
        (Self { limbs }, carry)
22
6.35k
    }
<crypto_bigint::uint::Uint<4>>::adc
Line
Count
Source
10
6.35k
    pub const fn adc(&self, rhs: &Self, mut carry: Limb) -> (Self, Limb) {
11
6.35k
        let mut limbs = [Limb::ZERO; LIMBS];
12
6.35k
        let mut i = 0;
13
14
31.7k
        while i < LIMBS {
15
25.4k
            let (w, c) = self.limbs[i].adc(rhs.limbs[i], carry);
16
25.4k
            limbs[i] = w;
17
25.4k
            carry = c;
18
25.4k
            i += 1;
19
25.4k
        }
20
21
6.35k
        (Self { limbs }, carry)
22
6.35k
    }
Unexecuted instantiation: <crypto_bigint::uint::Uint<_>>::adc
23
24
    /// Perform saturating addition, returning `MAX` on overflow.
25
0
    pub const fn saturating_add(&self, rhs: &Self) -> Self {
26
0
        let (res, overflow) = self.adc(rhs, Limb::ZERO);
27
0
        Self::ct_select(&res, &Self::MAX, CtChoice::from_lsb(overflow.0))
28
0
    }
29
30
    /// Perform wrapping addition, discarding overflow.
31
3.17k
    pub const fn wrapping_add(&self, rhs: &Self) -> Self {
32
3.17k
        self.adc(rhs, Limb::ZERO).0
33
3.17k
    }
<crypto_bigint::uint::Uint<4>>::wrapping_add
Line
Count
Source
31
3.17k
    pub const fn wrapping_add(&self, rhs: &Self) -> Self {
32
3.17k
        self.adc(rhs, Limb::ZERO).0
33
3.17k
    }
Unexecuted instantiation: <crypto_bigint::uint::Uint<_>>::wrapping_add
34
35
    /// Perform wrapping addition, returning the truthy value as the second element of the tuple
36
    /// if an overflow has occurred.
37
0
    pub(crate) const fn conditional_wrapping_add(
38
0
        &self,
39
0
        rhs: &Self,
40
0
        choice: CtChoice,
41
0
    ) -> (Self, CtChoice) {
42
0
        let actual_rhs = Uint::ct_select(&Uint::ZERO, rhs, choice);
43
0
        let (sum, carry) = self.adc(&actual_rhs, Limb::ZERO);
44
0
        (sum, CtChoice::from_lsb(carry.0))
45
0
    }
46
}
47
48
impl<const LIMBS: usize> CheckedAdd<&Uint<LIMBS>> for Uint<LIMBS> {
49
    type Output = Self;
50
51
0
    fn checked_add(&self, rhs: &Self) -> CtOption<Self> {
52
0
        let (result, carry) = self.adc(rhs, Limb::ZERO);
53
0
        CtOption::new(result, carry.is_zero())
54
0
    }
55
}
56
57
impl<const LIMBS: usize> Add for Wrapping<Uint<LIMBS>> {
58
    type Output = Self;
59
60
0
    fn add(self, rhs: Self) -> Wrapping<Uint<LIMBS>> {
61
0
        Wrapping(self.0.wrapping_add(&rhs.0))
62
0
    }
63
}
64
65
impl<const LIMBS: usize> Add<&Wrapping<Uint<LIMBS>>> for Wrapping<Uint<LIMBS>> {
66
    type Output = Wrapping<Uint<LIMBS>>;
67
68
0
    fn add(self, rhs: &Wrapping<Uint<LIMBS>>) -> Wrapping<Uint<LIMBS>> {
69
0
        Wrapping(self.0.wrapping_add(&rhs.0))
70
0
    }
71
}
72
73
impl<const LIMBS: usize> Add<Wrapping<Uint<LIMBS>>> for &Wrapping<Uint<LIMBS>> {
74
    type Output = Wrapping<Uint<LIMBS>>;
75
76
0
    fn add(self, rhs: Wrapping<Uint<LIMBS>>) -> Wrapping<Uint<LIMBS>> {
77
0
        Wrapping(self.0.wrapping_add(&rhs.0))
78
0
    }
79
}
80
81
impl<const LIMBS: usize> Add<&Wrapping<Uint<LIMBS>>> for &Wrapping<Uint<LIMBS>> {
82
    type Output = Wrapping<Uint<LIMBS>>;
83
84
0
    fn add(self, rhs: &Wrapping<Uint<LIMBS>>) -> Wrapping<Uint<LIMBS>> {
85
0
        Wrapping(self.0.wrapping_add(&rhs.0))
86
0
    }
87
}
88
89
impl<const LIMBS: usize> AddAssign for Wrapping<Uint<LIMBS>> {
90
0
    fn add_assign(&mut self, other: Self) {
91
0
        *self = *self + other;
92
0
    }
93
}
94
95
impl<const LIMBS: usize> AddAssign<&Wrapping<Uint<LIMBS>>> for Wrapping<Uint<LIMBS>> {
96
0
    fn add_assign(&mut self, other: &Self) {
97
0
        *self = *self + other;
98
0
    }
99
}
100
101
impl<const LIMBS: usize> Add for Checked<Uint<LIMBS>> {
102
    type Output = Self;
103
104
0
    fn add(self, rhs: Self) -> Checked<Uint<LIMBS>> {
105
        Checked(
106
0
            self.0
107
0
                .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(&rhs))),
108
        )
109
0
    }
110
}
111
112
impl<const LIMBS: usize> Add<&Checked<Uint<LIMBS>>> for Checked<Uint<LIMBS>> {
113
    type Output = Checked<Uint<LIMBS>>;
114
115
0
    fn add(self, rhs: &Checked<Uint<LIMBS>>) -> Checked<Uint<LIMBS>> {
116
        Checked(
117
0
            self.0
118
0
                .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(&rhs))),
119
        )
120
0
    }
121
}
122
123
impl<const LIMBS: usize> Add<Checked<Uint<LIMBS>>> for &Checked<Uint<LIMBS>> {
124
    type Output = Checked<Uint<LIMBS>>;
125
126
0
    fn add(self, rhs: Checked<Uint<LIMBS>>) -> Checked<Uint<LIMBS>> {
127
        Checked(
128
0
            self.0
129
0
                .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(&rhs))),
130
        )
131
0
    }
132
}
133
134
impl<const LIMBS: usize> Add<&Checked<Uint<LIMBS>>> for &Checked<Uint<LIMBS>> {
135
    type Output = Checked<Uint<LIMBS>>;
136
137
0
    fn add(self, rhs: &Checked<Uint<LIMBS>>) -> Checked<Uint<LIMBS>> {
138
        Checked(
139
0
            self.0
140
0
                .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(&rhs))),
141
        )
142
0
    }
143
}
144
145
impl<const LIMBS: usize> AddAssign for Checked<Uint<LIMBS>> {
146
0
    fn add_assign(&mut self, other: Self) {
147
0
        *self = *self + other;
148
0
    }
149
}
150
151
impl<const LIMBS: usize> AddAssign<&Checked<Uint<LIMBS>>> for Checked<Uint<LIMBS>> {
152
0
    fn add_assign(&mut self, other: &Self) {
153
0
        *self = *self + other;
154
0
    }
155
}
156
157
#[cfg(test)]
158
mod tests {
159
    use crate::{CheckedAdd, Limb, U128};
160
161
    #[test]
162
    fn adc_no_carry() {
163
        let (res, carry) = U128::ZERO.adc(&U128::ONE, Limb::ZERO);
164
        assert_eq!(res, U128::ONE);
165
        assert_eq!(carry, Limb::ZERO);
166
    }
167
168
    #[test]
169
    fn adc_with_carry() {
170
        let (res, carry) = U128::MAX.adc(&U128::ONE, Limb::ZERO);
171
        assert_eq!(res, U128::ZERO);
172
        assert_eq!(carry, Limb::ONE);
173
    }
174
175
    #[test]
176
    fn saturating_add_no_carry() {
177
        assert_eq!(U128::ZERO.saturating_add(&U128::ONE), U128::ONE);
178
    }
179
180
    #[test]
181
    fn saturating_add_with_carry() {
182
        assert_eq!(U128::MAX.saturating_add(&U128::ONE), U128::MAX);
183
    }
184
185
    #[test]
186
    fn wrapping_add_no_carry() {
187
        assert_eq!(U128::ZERO.wrapping_add(&U128::ONE), U128::ONE);
188
    }
189
190
    #[test]
191
    fn wrapping_add_with_carry() {
192
        assert_eq!(U128::MAX.wrapping_add(&U128::ONE), U128::ZERO);
193
    }
194
195
    #[test]
196
    fn checked_add_ok() {
197
        let result = U128::ZERO.checked_add(&U128::ONE);
198
        assert_eq!(result.unwrap(), U128::ONE);
199
    }
200
201
    #[test]
202
    fn checked_add_overflow() {
203
        let result = U128::MAX.checked_add(&U128::ONE);
204
        assert!(!bool::from(result.is_some()));
205
    }
206
}