1use super::CheckedUnsignedAbs::{Negative, Positive};
2use super::Sign::{Minus, NoSign, Plus};
3use super::{BigInt, UnsignedAbs};
4
5use crate::{IsizePromotion, UsizePromotion};
6
7use core::cmp::Ordering::{Equal, Greater, Less};
8use core::iter::Sum;
9use core::mem;
10use core::ops::{Add, AddAssign};
11use num_traits::CheckedAdd;
12
13macro_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 (Plus, Plus) | (Minus, Minus) => BigInt::from_biguint($a.sign, $a_data + $b_data),
23 (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 => BigInt::ZERO,
28 },
29 }
30 };
31}
32
33impl Add<&BigInt> for &BigInt {
34 type Output = BigInt;
35
36 #[inline]
37 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
49impl Add<BigInt> for &BigInt {
50 type Output = BigInt;
51
52 #[inline]
53 fn add(self, other: BigInt) -> BigInt {
54 bigint_add!(self, self.clone(), &self.data, other, other, other.data)
55 }
56}
57
58impl Add<&BigInt> for BigInt {
59 type Output = BigInt;
60
61 #[inline]
62 fn add(self, other: &BigInt) -> BigInt {
63 bigint_add!(self, self, self.data, other, other.clone(), &other.data)
64 }
65}
66
67impl Add<BigInt> for BigInt {
68 type Output = BigInt;
69
70 #[inline]
71 fn add(self, other: BigInt) -> BigInt {
72 bigint_add!(self, self, self.data, other, other, other.data)
73 }
74}
75
76impl AddAssign<&BigInt> for BigInt {
77 #[inline]
78 fn add_assign(&mut self, other: &BigInt) {
79 let n = mem::replace(self, Self::ZERO);
80 *self = n + other;
81 }
82}
83forward_val_assign!(impl AddAssign for BigInt, add_assign);
84
85promote_all_scalars!(impl Add for BigInt, add);
86promote_all_scalars_assign!(impl AddAssign for BigInt, add_assign);
87forward_all_scalar_binop_to_val_val_commutative!(impl Add<u32> for BigInt, add);
88forward_all_scalar_binop_to_val_val_commutative!(impl Add<u64> for BigInt, add);
89forward_all_scalar_binop_to_val_val_commutative!(impl Add<u128> for BigInt, add);
90
91impl Add<u32> for BigInt {
92 type Output = BigInt;
93
94 #[inline]
95 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 => Self::ZERO,
101 Less => BigInt::from(other - self.data),
102 Greater => -BigInt::from(self.data - other),
103 },
104 }
105 }
106}
107
108impl AddAssign<u32> for BigInt {
109 #[inline]
110 fn add_assign(&mut self, other: u32) {
111 let n = mem::replace(self, Self::ZERO);
112 *self = n + other;
113 }
114}
115
116impl Add<u64> for BigInt {
117 type Output = BigInt;
118
119 #[inline]
120 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 => Self::ZERO,
126 Less => BigInt::from(other - self.data),
127 Greater => -BigInt::from(self.data - other),
128 },
129 }
130 }
131}
132
133impl AddAssign<u64> for BigInt {
134 #[inline]
135 fn add_assign(&mut self, other: u64) {
136 let n = mem::replace(self, Self::ZERO);
137 *self = n + other;
138 }
139}
140
141impl Add<u128> for BigInt {
142 type Output = BigInt;
143
144 #[inline]
145 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 => Self::ZERO,
151 Less => BigInt::from(other - self.data),
152 Greater => -BigInt::from(self.data - other),
153 },
154 }
155 }
156}
157impl AddAssign<u128> for BigInt {
158 #[inline]
159 fn add_assign(&mut self, other: u128) {
160 let n = mem::replace(self, Self::ZERO);
161 *self = n + other;
162 }
163}
164
165forward_all_scalar_binop_to_val_val_commutative!(impl Add<i32> for BigInt, add);
166forward_all_scalar_binop_to_val_val_commutative!(impl Add<i64> for BigInt, add);
167forward_all_scalar_binop_to_val_val_commutative!(impl Add<i128> for BigInt, add);
168
169impl Add<i32> for BigInt {
170 type Output = BigInt;
171
172 #[inline]
173 fn add(self, other: i32) -> BigInt {
174 match other.checked_uabs() {
175 Positive(u) => self + u,
176 Negative(u) => self - u,
177 }
178 }
179}
180impl AddAssign<i32> for BigInt {
181 #[inline]
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
190impl Add<i64> for BigInt {
191 type Output = BigInt;
192
193 #[inline]
194 fn add(self, other: i64) -> BigInt {
195 match other.checked_uabs() {
196 Positive(u) => self + u,
197 Negative(u) => self - u,
198 }
199 }
200}
201impl AddAssign<i64> for BigInt {
202 #[inline]
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
211impl Add<i128> for BigInt {
212 type Output = BigInt;
213
214 #[inline]
215 fn add(self, other: i128) -> BigInt {
216 match other.checked_uabs() {
217 Positive(u) => self + u,
218 Negative(u) => self - u,
219 }
220 }
221}
222impl AddAssign<i128> for BigInt {
223 #[inline]
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
232impl CheckedAdd for BigInt {
233 #[inline]
234 fn checked_add(&self, v: &BigInt) -> Option<BigInt> {
235 Some(self.add(v))
236 }
237}
238
239impl_sum_iter_type!(BigInt);