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