/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 | | } |