1use core::ops::{Add, AddAssign};
4
5use num_traits::WrappingAdd;
6use subtle::CtOption;
7
8use crate::{Checked, CheckedAdd, ConstChoice, ConstCtOption, Int, Wrapping};
9
10impl<const LIMBS: usize> Int<LIMBS> {
11 pub const fn checked_add(&self, rhs: &Self) -> ConstCtOption<Self> {
13 let (value, overflow) = self.overflowing_add(rhs);
14 ConstCtOption::new(value, overflow.not())
15 }
16
17 pub const fn overflowing_add(&self, rhs: &Self) -> (Self, ConstChoice) {
19 let res = Self(self.0.wrapping_add(&rhs.0));
21
22 let self_msb = self.is_negative();
29 let overflow = self_msb
30 .eq(rhs.is_negative())
31 .and(self_msb.ne(res.is_negative()));
32
33 (res, overflow)
35 }
36
37 pub const fn wrapping_add(&self, rhs: &Self) -> Self {
39 Self(self.0.wrapping_add(&rhs.0))
40 }
41}
42
43impl<const LIMBS: usize> Add for Int<LIMBS> {
44 type Output = Self;
45
46 fn add(self, rhs: Self) -> Self {
47 self.add(&rhs)
48 }
49}
50
51impl<const LIMBS: usize> Add<&Int<LIMBS>> for Int<LIMBS> {
52 type Output = Self;
53
54 fn add(self, rhs: &Self) -> Self {
55 CtOption::from(self.checked_add(rhs)).expect("attempted to add with overflow")
56 }
57}
58
59impl<const LIMBS: usize> AddAssign for Int<LIMBS> {
60 fn add_assign(&mut self, other: Self) {
61 *self += &other;
62 }
63}
64
65impl<const LIMBS: usize> AddAssign<&Int<LIMBS>> for Int<LIMBS> {
66 fn add_assign(&mut self, other: &Self) {
67 *self = *self + other;
68 }
69}
70
71impl<const LIMBS: usize> AddAssign for Wrapping<Int<LIMBS>> {
72 fn add_assign(&mut self, other: Self) {
73 *self = *self + other;
74 }
75}
76
77impl<const LIMBS: usize> AddAssign<&Wrapping<Int<LIMBS>>> for Wrapping<Int<LIMBS>> {
78 fn add_assign(&mut self, other: &Self) {
79 *self = *self + other;
80 }
81}
82
83impl<const LIMBS: usize> AddAssign for Checked<Int<LIMBS>> {
84 fn add_assign(&mut self, other: Self) {
85 *self = *self + other;
86 }
87}
88
89impl<const LIMBS: usize> AddAssign<&Checked<Int<LIMBS>>> for Checked<Int<LIMBS>> {
90 fn add_assign(&mut self, other: &Self) {
91 *self = *self + other;
92 }
93}
94
95impl<const LIMBS: usize> CheckedAdd for Int<LIMBS> {
96 fn checked_add(&self, rhs: &Self) -> CtOption<Self> {
97 self.checked_add(rhs).into()
98 }
99}
100
101impl<const LIMBS: usize> WrappingAdd for Int<LIMBS> {
102 fn wrapping_add(&self, v: &Self) -> Self {
103 self.wrapping_add(v)
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use crate::{ConstChoice, I128, U128};
110
111 #[test]
112 fn checked_add() {
113 let min_plus_one = I128 {
114 0: I128::MIN.0.wrapping_add(&I128::ONE.0),
115 };
116 let max_minus_one = I128 {
117 0: I128::MAX.0.wrapping_sub(&I128::ONE.0),
118 };
119 let two = I128 {
120 0: U128::from(2u32),
121 };
122
123 let result = I128::MIN.checked_add(&I128::MIN);
126 assert!(bool::from(result.is_none()));
127
128 let result = I128::MIN.checked_add(&I128::MINUS_ONE);
129 assert!(bool::from(result.is_none()));
130
131 let result = I128::MIN.checked_add(&I128::ZERO);
132 assert_eq!(result.unwrap(), I128::MIN);
133
134 let result = I128::MIN.checked_add(&I128::ONE);
135 assert_eq!(result.unwrap(), min_plus_one);
136
137 let result = I128::MIN.checked_add(&I128::MAX);
138 assert_eq!(result.unwrap(), I128::MINUS_ONE);
139
140 let result = I128::MINUS_ONE.checked_add(&I128::MIN);
143 assert!(bool::from(result.is_none()));
144
145 let result = I128::MINUS_ONE.checked_add(&I128::MINUS_ONE);
146 assert_eq!(result.unwrap(), two.checked_neg().unwrap());
147
148 let result = I128::MINUS_ONE.checked_add(&I128::ZERO);
149 assert_eq!(result.unwrap(), I128::MINUS_ONE);
150
151 let result = I128::MINUS_ONE.checked_add(&I128::ONE);
152 assert_eq!(result.unwrap(), I128::ZERO);
153
154 let result = I128::MINUS_ONE.checked_add(&I128::MAX);
155 assert_eq!(result.unwrap(), max_minus_one);
156
157 let result = I128::ZERO.checked_add(&I128::MIN);
160 assert_eq!(result.unwrap(), I128::MIN);
161
162 let result = I128::ZERO.checked_add(&I128::MINUS_ONE);
163 assert_eq!(result.unwrap(), I128::MINUS_ONE);
164
165 let result = I128::ZERO.checked_add(&I128::ZERO);
166 assert_eq!(result.unwrap(), I128::ZERO);
167
168 let result = I128::ZERO.checked_add(&I128::ONE);
169 assert_eq!(result.unwrap(), I128::ONE);
170
171 let result = I128::ZERO.checked_add(&I128::MAX);
172 assert_eq!(result.unwrap(), I128::MAX);
173
174 let result = I128::ONE.checked_add(&I128::MIN);
177 assert_eq!(result.unwrap(), min_plus_one);
178
179 let result = I128::ONE.checked_add(&I128::MINUS_ONE);
180 assert_eq!(result.unwrap(), I128::ZERO);
181
182 let result = I128::ONE.checked_add(&I128::ZERO);
183 assert_eq!(result.unwrap(), I128::ONE);
184
185 let result = I128::ONE.checked_add(&I128::ONE);
186 assert_eq!(result.unwrap(), two);
187
188 let result = I128::ONE.checked_add(&I128::MAX);
189 assert!(bool::from(result.is_none()));
190
191 let result = I128::MAX.checked_add(&I128::MIN);
194 assert_eq!(result.unwrap(), I128::MINUS_ONE);
195
196 let result = I128::MAX.checked_add(&I128::MINUS_ONE);
197 assert_eq!(result.unwrap(), max_minus_one);
198
199 let result = I128::MAX.checked_add(&I128::ZERO);
200 assert_eq!(result.unwrap(), I128::MAX);
201
202 let result = I128::MAX.checked_add(&I128::ONE);
203 assert!(bool::from(result.is_none()));
204
205 let result = I128::MAX.checked_add(&I128::MAX);
206 assert!(bool::from(result.is_none()));
207 }
208
209 #[test]
210 fn overflowing_add() {
211 let min_plus_one = I128 {
212 0: I128::MIN.0.wrapping_add(&I128::ONE.0),
213 };
214 let max_minus_one = I128 {
215 0: I128::MAX.0.wrapping_sub(&I128::ONE.0),
216 };
217 let two = I128 {
218 0: U128::from(2u32),
219 };
220
221 let (_val, overflow) = I128::MIN.overflowing_add(&I128::MIN);
224 assert_eq!(overflow, ConstChoice::TRUE);
225
226 let (_val, overflow) = I128::MIN.overflowing_add(&I128::MINUS_ONE);
227 assert_eq!(overflow, ConstChoice::TRUE);
228
229 let (val, overflow) = I128::MIN.overflowing_add(&I128::ZERO);
230 assert_eq!(overflow, ConstChoice::FALSE);
231 assert_eq!(val, I128::MIN);
232
233 let (val, overflow) = I128::MIN.overflowing_add(&I128::ONE);
234 assert_eq!(overflow, ConstChoice::FALSE);
235 assert_eq!(val, min_plus_one);
236
237 let (val, overflow) = I128::MIN.overflowing_add(&I128::MAX);
238 assert_eq!(overflow, ConstChoice::FALSE);
239 assert_eq!(val, I128::MINUS_ONE);
240
241 let (_val, overflow) = I128::MINUS_ONE.overflowing_add(&I128::MIN);
244 assert_eq!(overflow, ConstChoice::TRUE);
245
246 let (val, overflow) = I128::MINUS_ONE.overflowing_add(&I128::MINUS_ONE);
247 assert_eq!(overflow, ConstChoice::FALSE);
248 assert_eq!(val, two.wrapping_neg());
249
250 let (val, overflow) = I128::MINUS_ONE.overflowing_add(&I128::ZERO);
251 assert_eq!(overflow, ConstChoice::FALSE);
252 assert_eq!(val, I128::MINUS_ONE);
253
254 let (val, overflow) = I128::MINUS_ONE.overflowing_add(&I128::ONE);
255 assert_eq!(overflow, ConstChoice::FALSE);
256 assert_eq!(val, I128::ZERO);
257
258 let (val, overflow) = I128::MINUS_ONE.overflowing_add(&I128::MAX);
259 assert_eq!(overflow, ConstChoice::FALSE);
260 assert_eq!(val, max_minus_one);
261
262 let (val, overflow) = I128::ZERO.overflowing_add(&I128::MIN);
265 assert_eq!(overflow, ConstChoice::FALSE);
266 assert_eq!(val, I128::MIN);
267
268 let (val, overflow) = I128::ZERO.overflowing_add(&I128::MINUS_ONE);
269 assert_eq!(overflow, ConstChoice::FALSE);
270 assert_eq!(val, I128::MINUS_ONE);
271
272 let (val, overflow) = I128::ZERO.overflowing_add(&I128::ZERO);
273 assert_eq!(overflow, ConstChoice::FALSE);
274 assert_eq!(val, I128::ZERO);
275
276 let (val, overflow) = I128::ZERO.overflowing_add(&I128::ONE);
277 assert_eq!(overflow, ConstChoice::FALSE);
278 assert_eq!(val, I128::ONE);
279
280 let (val, overflow) = I128::ZERO.overflowing_add(&I128::MAX);
281 assert_eq!(overflow, ConstChoice::FALSE);
282 assert_eq!(val, I128::MAX);
283
284 let (val, overflow) = I128::ONE.overflowing_add(&I128::MIN);
287 assert_eq!(overflow, ConstChoice::FALSE);
288 assert_eq!(val, min_plus_one);
289
290 let (val, overflow) = I128::ONE.overflowing_add(&I128::MINUS_ONE);
291 assert_eq!(overflow, ConstChoice::FALSE);
292 assert_eq!(val, I128::ZERO);
293
294 let (val, overflow) = I128::ONE.overflowing_add(&I128::ZERO);
295 assert_eq!(overflow, ConstChoice::FALSE);
296 assert_eq!(val, I128::ONE);
297
298 let (val, overflow) = I128::ONE.overflowing_add(&I128::ONE);
299 assert_eq!(overflow, ConstChoice::FALSE);
300 assert_eq!(val, two);
301
302 let (_val, overflow) = I128::ONE.overflowing_add(&I128::MAX);
303 assert_eq!(overflow, ConstChoice::TRUE);
304
305 let (val, overflow) = I128::MAX.overflowing_add(&I128::MIN);
308 assert_eq!(overflow, ConstChoice::FALSE);
309 assert_eq!(val, I128::MINUS_ONE);
310
311 let (val, overflow) = I128::MAX.overflowing_add(&I128::MINUS_ONE);
312 assert_eq!(overflow, ConstChoice::FALSE);
313 assert_eq!(val, max_minus_one);
314
315 let (val, overflow) = I128::MAX.overflowing_add(&I128::ZERO);
316 assert_eq!(overflow, ConstChoice::FALSE);
317 assert_eq!(val, I128::MAX);
318
319 let (_val, overflow) = I128::MAX.overflowing_add(&I128::ONE);
320 assert_eq!(overflow, ConstChoice::TRUE);
321
322 let (_val, overflow) = I128::MAX.overflowing_add(&I128::MAX);
323 assert_eq!(overflow, ConstChoice::TRUE);
324 }
325}