1 use super::CheckedUnsignedAbs::{Negative, Positive};
2 use super::Sign::{Minus, NoSign, Plus};
3 use super::{BigInt, UnsignedAbs};
4 
5 use crate::{IsizePromotion, UsizePromotion};
6 
7 use core::cmp::Ordering::{Equal, Greater, Less};
8 use core::iter::Sum;
9 use core::mem;
10 use core::ops::{Add, AddAssign};
11 use num_traits::{CheckedAdd, Zero};
12 
13 // We want to forward to BigUint::add, but it's not clear how that will go until
14 // we compare both sign and magnitude.  So we duplicate this body for every
15 // val/ref combination, deferring that decision to BigUint's own forwarding.
16 macro_rules! bigint_add {
17     ($a:expr, $a_owned:expr, $a_data:expr, $b:expr, $b_owned:expr, $b_data:expr) => {
18         match ($a.sign, $b.sign) {
19             (_, NoSign) => $a_owned,
20             (NoSign, _) => $b_owned,
21             // same sign => keep the sign with the sum of magnitudes
22             (Plus, Plus) | (Minus, Minus) => BigInt::from_biguint($a.sign, $a_data + $b_data),
23             // opposite signs => keep the sign of the larger with the difference of magnitudes
24             (Plus, Minus) | (Minus, Plus) => match $a.data.cmp(&$b.data) {
25                 Less => BigInt::from_biguint($b.sign, $b_data - $a_data),
26                 Greater => BigInt::from_biguint($a.sign, $a_data - $b_data),
27                 Equal => Zero::zero(),
28             },
29         }
30     };
31 }
32 
33 impl Add<&BigInt> for &BigInt {
34     type Output = BigInt;
35 
36     #[inline]
add(self, other: &BigInt) -> BigInt37     fn add(self, other: &BigInt) -> BigInt {
38         bigint_add!(
39             self,
40             self.clone(),
41             &self.data,
42             other,
43             other.clone(),
44             &other.data
45         )
46     }
47 }
48 
49 impl Add<BigInt> for &BigInt {
50     type Output = BigInt;
51 
52     #[inline]
add(self, other: BigInt) -> BigInt53     fn add(self, other: BigInt) -> BigInt {
54         bigint_add!(self, self.clone(), &self.data, other, other, other.data)
55     }
56 }
57 
58 impl Add<&BigInt> for BigInt {
59     type Output = BigInt;
60 
61     #[inline]
add(self, other: &BigInt) -> BigInt62     fn add(self, other: &BigInt) -> BigInt {
63         bigint_add!(self, self, self.data, other, other.clone(), &other.data)
64     }
65 }
66 
67 impl Add<BigInt> for BigInt {
68     type Output = BigInt;
69 
70     #[inline]
add(self, other: BigInt) -> BigInt71     fn add(self, other: BigInt) -> BigInt {
72         bigint_add!(self, self, self.data, other, other, other.data)
73     }
74 }
75 
76 impl AddAssign<&BigInt> for BigInt {
77     #[inline]
add_assign(&mut self, other: &BigInt)78     fn add_assign(&mut self, other: &BigInt) {
79         let n = mem::replace(self, BigInt::zero());
80         *self = n + other;
81     }
82 }
83 forward_val_assign!(impl AddAssign for BigInt, add_assign);
84 
85 promote_all_scalars!(impl Add for BigInt, add);
86 promote_all_scalars_assign!(impl AddAssign for BigInt, add_assign);
87 forward_all_scalar_binop_to_val_val_commutative!(impl Add<u32> for BigInt, add);
88 forward_all_scalar_binop_to_val_val_commutative!(impl Add<u64> for BigInt, add);
89 forward_all_scalar_binop_to_val_val_commutative!(impl Add<u128> for BigInt, add);
90 
91 impl Add<u32> for BigInt {
92     type Output = BigInt;
93 
94     #[inline]
add(self, other: u32) -> BigInt95     fn add(self, other: u32) -> BigInt {
96         match self.sign {
97             NoSign => From::from(other),
98             Plus => BigInt::from(self.data + other),
99             Minus => match self.data.cmp(&From::from(other)) {
100                 Equal => Zero::zero(),
101                 Less => BigInt::from(other - self.data),
102                 Greater => -BigInt::from(self.data - other),
103             },
104         }
105     }
106 }
107 
108 impl AddAssign<u32> for BigInt {
109     #[inline]
add_assign(&mut self, other: u32)110     fn add_assign(&mut self, other: u32) {
111         let n = mem::replace(self, BigInt::zero());
112         *self = n + other;
113     }
114 }
115 
116 impl Add<u64> for BigInt {
117     type Output = BigInt;
118 
119     #[inline]
add(self, other: u64) -> BigInt120     fn add(self, other: u64) -> BigInt {
121         match self.sign {
122             NoSign => From::from(other),
123             Plus => BigInt::from(self.data + other),
124             Minus => match self.data.cmp(&From::from(other)) {
125                 Equal => Zero::zero(),
126                 Less => BigInt::from(other - self.data),
127                 Greater => -BigInt::from(self.data - other),
128             },
129         }
130     }
131 }
132 
133 impl AddAssign<u64> for BigInt {
134     #[inline]
add_assign(&mut self, other: u64)135     fn add_assign(&mut self, other: u64) {
136         let n = mem::replace(self, BigInt::zero());
137         *self = n + other;
138     }
139 }
140 
141 impl Add<u128> for BigInt {
142     type Output = BigInt;
143 
144     #[inline]
add(self, other: u128) -> BigInt145     fn add(self, other: u128) -> BigInt {
146         match self.sign {
147             NoSign => BigInt::from(other),
148             Plus => BigInt::from(self.data + other),
149             Minus => match self.data.cmp(&From::from(other)) {
150                 Equal => BigInt::zero(),
151                 Less => BigInt::from(other - self.data),
152                 Greater => -BigInt::from(self.data - other),
153             },
154         }
155     }
156 }
157 impl AddAssign<u128> for BigInt {
158     #[inline]
add_assign(&mut self, other: u128)159     fn add_assign(&mut self, other: u128) {
160         let n = mem::replace(self, BigInt::zero());
161         *self = n + other;
162     }
163 }
164 
165 forward_all_scalar_binop_to_val_val_commutative!(impl Add<i32> for BigInt, add);
166 forward_all_scalar_binop_to_val_val_commutative!(impl Add<i64> for BigInt, add);
167 forward_all_scalar_binop_to_val_val_commutative!(impl Add<i128> for BigInt, add);
168 
169 impl Add<i32> for BigInt {
170     type Output = BigInt;
171 
172     #[inline]
add(self, other: i32) -> BigInt173     fn add(self, other: i32) -> BigInt {
174         match other.checked_uabs() {
175             Positive(u) => self + u,
176             Negative(u) => self - u,
177         }
178     }
179 }
180 impl AddAssign<i32> for BigInt {
181     #[inline]
add_assign(&mut self, other: i32)182     fn add_assign(&mut self, other: i32) {
183         match other.checked_uabs() {
184             Positive(u) => *self += u,
185             Negative(u) => *self -= u,
186         }
187     }
188 }
189 
190 impl Add<i64> for BigInt {
191     type Output = BigInt;
192 
193     #[inline]
add(self, other: i64) -> BigInt194     fn add(self, other: i64) -> BigInt {
195         match other.checked_uabs() {
196             Positive(u) => self + u,
197             Negative(u) => self - u,
198         }
199     }
200 }
201 impl AddAssign<i64> for BigInt {
202     #[inline]
add_assign(&mut self, other: i64)203     fn add_assign(&mut self, other: i64) {
204         match other.checked_uabs() {
205             Positive(u) => *self += u,
206             Negative(u) => *self -= u,
207         }
208     }
209 }
210 
211 impl Add<i128> for BigInt {
212     type Output = BigInt;
213 
214     #[inline]
add(self, other: i128) -> BigInt215     fn add(self, other: i128) -> BigInt {
216         match other.checked_uabs() {
217             Positive(u) => self + u,
218             Negative(u) => self - u,
219         }
220     }
221 }
222 impl AddAssign<i128> for BigInt {
223     #[inline]
add_assign(&mut self, other: i128)224     fn add_assign(&mut self, other: i128) {
225         match other.checked_uabs() {
226             Positive(u) => *self += u,
227             Negative(u) => *self -= u,
228         }
229     }
230 }
231 
232 impl CheckedAdd for BigInt {
233     #[inline]
checked_add(&self, v: &BigInt) -> Option<BigInt>234     fn checked_add(&self, v: &BigInt) -> Option<BigInt> {
235         Some(self.add(v))
236     }
237 }
238 
239 impl_sum_iter_type!(BigInt);
240