num_bigint/bigint/
addition.rs

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
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.
16macro_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 => 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);