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