num_bigint/bigint/
subtraction.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::mem;
9use core::ops::{Sub, SubAssign};
10use num_traits::{CheckedSub, Zero};
11
12// We want to forward to BigUint::sub, but it's not clear how that will go until
13// we compare both sign and magnitude.  So we duplicate this body for every
14// val/ref combination, deferring that decision to BigUint's own forwarding.
15macro_rules! bigint_sub {
16    ($a:expr, $a_owned:expr, $a_data:expr, $b:expr, $b_owned:expr, $b_data:expr) => {
17        match ($a.sign, $b.sign) {
18            (_, NoSign) => $a_owned,
19            (NoSign, _) => -$b_owned,
20            // opposite signs => keep the sign of the left with the sum of magnitudes
21            (Plus, Minus) | (Minus, Plus) => BigInt::from_biguint($a.sign, $a_data + $b_data),
22            // same sign => keep or toggle the sign of the left with the difference of magnitudes
23            (Plus, Plus) | (Minus, Minus) => match $a.data.cmp(&$b.data) {
24                Less => BigInt::from_biguint(-$a.sign, $b_data - $a_data),
25                Greater => BigInt::from_biguint($a.sign, $a_data - $b_data),
26                Equal => Zero::zero(),
27            },
28        }
29    };
30}
31
32impl<'a, 'b> Sub<&'b BigInt> for &'a BigInt {
33    type Output = BigInt;
34
35    #[inline]
36    fn sub(self, other: &BigInt) -> BigInt {
37        bigint_sub!(
38            self,
39            self.clone(),
40            &self.data,
41            other,
42            other.clone(),
43            &other.data
44        )
45    }
46}
47
48impl<'a> Sub<BigInt> for &'a BigInt {
49    type Output = BigInt;
50
51    #[inline]
52    fn sub(self, other: BigInt) -> BigInt {
53        bigint_sub!(self, self.clone(), &self.data, other, other, other.data)
54    }
55}
56
57impl<'a> Sub<&'a BigInt> for BigInt {
58    type Output = BigInt;
59
60    #[inline]
61    fn sub(self, other: &BigInt) -> BigInt {
62        bigint_sub!(self, self, self.data, other, other.clone(), &other.data)
63    }
64}
65
66impl Sub<BigInt> for BigInt {
67    type Output = BigInt;
68
69    #[inline]
70    fn sub(self, other: BigInt) -> BigInt {
71        bigint_sub!(self, self, self.data, other, other, other.data)
72    }
73}
74
75impl<'a> SubAssign<&'a BigInt> for BigInt {
76    #[inline]
77    fn sub_assign(&mut self, other: &BigInt) {
78        let n = mem::replace(self, BigInt::zero());
79        *self = n - other;
80    }
81}
82forward_val_assign!(impl SubAssign for BigInt, sub_assign);
83
84promote_all_scalars!(impl Sub for BigInt, sub);
85promote_all_scalars_assign!(impl SubAssign for BigInt, sub_assign);
86forward_all_scalar_binop_to_val_val!(impl Sub<u32> for BigInt, sub);
87forward_all_scalar_binop_to_val_val!(impl Sub<u64> for BigInt, sub);
88forward_all_scalar_binop_to_val_val!(impl Sub<u128> for BigInt, sub);
89
90impl Sub<u32> for BigInt {
91    type Output = BigInt;
92
93    #[inline]
94    fn sub(self, other: u32) -> BigInt {
95        match self.sign {
96            NoSign => -BigInt::from(other),
97            Minus => -BigInt::from(self.data + other),
98            Plus => match self.data.cmp(&From::from(other)) {
99                Equal => Zero::zero(),
100                Greater => BigInt::from(self.data - other),
101                Less => -BigInt::from(other - self.data),
102            },
103        }
104    }
105}
106impl SubAssign<u32> for BigInt {
107    #[inline]
108    fn sub_assign(&mut self, other: u32) {
109        let n = mem::replace(self, BigInt::zero());
110        *self = n - other;
111    }
112}
113
114impl Sub<BigInt> for u32 {
115    type Output = BigInt;
116
117    #[inline]
118    fn sub(self, other: BigInt) -> BigInt {
119        -(other - self)
120    }
121}
122
123impl Sub<BigInt> for u64 {
124    type Output = BigInt;
125
126    #[inline]
127    fn sub(self, other: BigInt) -> BigInt {
128        -(other - self)
129    }
130}
131
132impl Sub<BigInt> for u128 {
133    type Output = BigInt;
134
135    #[inline]
136    fn sub(self, other: BigInt) -> BigInt {
137        -(other - self)
138    }
139}
140
141impl Sub<u64> for BigInt {
142    type Output = BigInt;
143
144    #[inline]
145    fn sub(self, other: u64) -> BigInt {
146        match self.sign {
147            NoSign => -BigInt::from(other),
148            Minus => -BigInt::from(self.data + other),
149            Plus => match self.data.cmp(&From::from(other)) {
150                Equal => Zero::zero(),
151                Greater => BigInt::from(self.data - other),
152                Less => -BigInt::from(other - self.data),
153            },
154        }
155    }
156}
157
158impl SubAssign<u64> for BigInt {
159    #[inline]
160    fn sub_assign(&mut self, other: u64) {
161        let n = mem::replace(self, BigInt::zero());
162        *self = n - other;
163    }
164}
165
166impl Sub<u128> for BigInt {
167    type Output = BigInt;
168
169    #[inline]
170    fn sub(self, other: u128) -> BigInt {
171        match self.sign {
172            NoSign => -BigInt::from(other),
173            Minus => -BigInt::from(self.data + other),
174            Plus => match self.data.cmp(&From::from(other)) {
175                Equal => Zero::zero(),
176                Greater => BigInt::from(self.data - other),
177                Less => -BigInt::from(other - self.data),
178            },
179        }
180    }
181}
182
183impl SubAssign<u128> for BigInt {
184    #[inline]
185    fn sub_assign(&mut self, other: u128) {
186        let n = mem::replace(self, BigInt::zero());
187        *self = n - other;
188    }
189}
190
191forward_all_scalar_binop_to_val_val!(impl Sub<i32> for BigInt, sub);
192forward_all_scalar_binop_to_val_val!(impl Sub<i64> for BigInt, sub);
193forward_all_scalar_binop_to_val_val!(impl Sub<i128> for BigInt, sub);
194
195impl Sub<i32> for BigInt {
196    type Output = BigInt;
197
198    #[inline]
199    fn sub(self, other: i32) -> BigInt {
200        match other.checked_uabs() {
201            Positive(u) => self - u,
202            Negative(u) => self + u,
203        }
204    }
205}
206impl SubAssign<i32> for BigInt {
207    #[inline]
208    fn sub_assign(&mut self, other: i32) {
209        match other.checked_uabs() {
210            Positive(u) => *self -= u,
211            Negative(u) => *self += u,
212        }
213    }
214}
215
216impl Sub<BigInt> for i32 {
217    type Output = BigInt;
218
219    #[inline]
220    fn sub(self, other: BigInt) -> BigInt {
221        match self.checked_uabs() {
222            Positive(u) => u - other,
223            Negative(u) => -other - u,
224        }
225    }
226}
227
228impl Sub<i64> for BigInt {
229    type Output = BigInt;
230
231    #[inline]
232    fn sub(self, other: i64) -> BigInt {
233        match other.checked_uabs() {
234            Positive(u) => self - u,
235            Negative(u) => self + u,
236        }
237    }
238}
239impl SubAssign<i64> for BigInt {
240    #[inline]
241    fn sub_assign(&mut self, other: i64) {
242        match other.checked_uabs() {
243            Positive(u) => *self -= u,
244            Negative(u) => *self += u,
245        }
246    }
247}
248
249impl Sub<BigInt> for i64 {
250    type Output = BigInt;
251
252    #[inline]
253    fn sub(self, other: BigInt) -> BigInt {
254        match self.checked_uabs() {
255            Positive(u) => u - other,
256            Negative(u) => -other - u,
257        }
258    }
259}
260
261impl Sub<i128> for BigInt {
262    type Output = BigInt;
263
264    #[inline]
265    fn sub(self, other: i128) -> BigInt {
266        match other.checked_uabs() {
267            Positive(u) => self - u,
268            Negative(u) => self + u,
269        }
270    }
271}
272
273impl SubAssign<i128> for BigInt {
274    #[inline]
275    fn sub_assign(&mut self, other: i128) {
276        match other.checked_uabs() {
277            Positive(u) => *self -= u,
278            Negative(u) => *self += u,
279        }
280    }
281}
282
283impl Sub<BigInt> for i128 {
284    type Output = BigInt;
285
286    #[inline]
287    fn sub(self, other: BigInt) -> BigInt {
288        match self.checked_uabs() {
289            Positive(u) => u - other,
290            Negative(u) => -other - u,
291        }
292    }
293}
294
295impl CheckedSub for BigInt {
296    #[inline]
297    fn checked_sub(&self, v: &BigInt) -> Option<BigInt> {
298        Some(self.sub(v))
299    }
300}