bigdecimal/
impl_ops_sub.rs
1use crate::*;
6
7
8impl Sub<BigDecimal> for BigDecimal {
9 type Output = BigDecimal;
10
11 #[inline]
12 fn sub(self, rhs: BigDecimal) -> BigDecimal {
13 if rhs.is_zero() {
14 return self;
15 }
16
17 if self.is_zero() {
18 return rhs.neg();
19 }
20
21 let mut lhs = self;
22 match lhs.scale.cmp(&rhs.scale) {
23 Ordering::Equal => {
24 lhs.int_val -= rhs.int_val;
25 lhs
26 }
27 Ordering::Less => {
28 lhs.take_and_scale(rhs.scale) - rhs
29 }
30 Ordering::Greater => {
31 let rhs = rhs.take_and_scale(lhs.scale);
32 lhs - rhs
33 },
34 }
35 }
36}
37
38impl Sub<BigDecimal> for &'_ BigDecimal {
39 type Output = BigDecimal;
40
41 #[inline]
42 fn sub(self, rhs: BigDecimal) -> BigDecimal {
43 self.to_ref() - rhs
44 }
45}
46
47impl Sub<BigDecimal> for BigDecimalRef<'_> {
48 type Output = BigDecimal;
49
50 #[inline]
51 fn sub(self, rhs: BigDecimal) -> BigDecimal {
52 (rhs - self).neg()
53 }
54}
55
56impl<'a, T: Into<BigDecimalRef<'a>>> Sub<T> for BigDecimal {
57 type Output = BigDecimal;
58
59 fn sub(mut self, rhs: T) -> BigDecimal {
60 self.sub_assign(rhs);
61 self
62 }
63}
64
65impl<'a, T: Into<BigDecimalRef<'a>>> Sub<T> for &'_ BigDecimal {
66 type Output = BigDecimal;
67
68 fn sub(self, rhs: T) -> BigDecimal {
69 let rhs = rhs.into();
70
71 match self.scale.cmp(&rhs.scale) {
72 Ordering::Equal => {
73 self.clone() - rhs
74 }
75 Ordering::Less => {
76 self.with_scale(rhs.scale) - rhs
77 }
78 Ordering::Greater => {
79 self - rhs.to_owned_with_scale(self.scale)
80 }
81 }
82 }
83}
84
85impl<'a, T: Into<BigDecimalRef<'a>>> Sub<T> for BigDecimalRef<'_> {
86 type Output = BigDecimal;
87
88 fn sub(self, rhs: T) -> BigDecimal {
89 let rhs = rhs.into();
90
91 match self.scale.cmp(&rhs.scale) {
92 Ordering::Equal => self.to_owned() - rhs,
93 Ordering::Less => self.to_owned_with_scale(rhs.scale) - rhs,
94 Ordering::Greater => self - rhs.to_owned_with_scale(self.scale),
95 }
96 }
97}
98
99impl Sub<BigInt> for BigDecimal {
100 type Output = BigDecimal;
101
102 fn sub(mut self, rhs: BigInt) -> BigDecimal {
103 self.sub_assign(rhs);
104 self
105 }
106}
107
108
109impl Sub<BigInt> for &'_ BigDecimal {
110 type Output = BigDecimal;
111
112 #[inline]
113 fn sub(self, rhs: BigInt) -> BigDecimal {
114 self.to_ref() - rhs
115 }
116}
117
118impl Sub<BigInt> for BigDecimalRef<'_> {
119 type Output = BigDecimal;
120
121 #[inline]
122 fn sub(self, rhs: BigInt) -> BigDecimal {
123 self - BigDecimal::from(rhs)
124 }
125}
126
127impl Sub<BigDecimal> for BigInt {
128 type Output = BigDecimal;
129
130 #[inline]
131 fn sub(self, rhs: BigDecimal) -> BigDecimal {
132 (rhs - self).neg()
133 }
134}
135
136impl Sub<BigDecimal> for &BigInt {
137 type Output = BigDecimal;
138
139 #[inline]
140 fn sub(self, rhs: BigDecimal) -> BigDecimal {
141 (rhs - self).neg()
142 }
143}
144
145impl<'a> Sub<BigDecimalRef<'a>> for BigInt {
146 type Output = BigDecimal;
147
148 #[inline]
149 fn sub(self, rhs: BigDecimalRef<'a>) -> BigDecimal {
150 (rhs - &self).neg()
151 }
152}
153
154
155impl<'a> Sub<BigDecimalRef<'a>> for &BigInt {
156 type Output = BigDecimal;
157
158 #[inline]
159 fn sub(self, rhs: BigDecimalRef<'a>) -> BigDecimal {
160 (rhs - self).neg()
161 }
162}
163
164
165impl SubAssign<BigDecimal> for BigDecimal {
166 #[inline]
167 fn sub_assign(&mut self, rhs: BigDecimal) {
168 if rhs.is_zero() {
169 return;
170 }
171 if self.is_zero() {
172 *self = rhs.neg();
173 return;
174 }
175 match self.scale.cmp(&rhs.scale) {
176 Ordering::Equal => {
177 self.int_val -= rhs.int_val;
178 }
179 Ordering::Less => {
180 self.int_val *= ten_to_the((rhs.scale - self.scale) as u64);
181 self.int_val -= rhs.int_val;
182 self.scale = rhs.scale;
183 }
184 Ordering::Greater => {
185 let mut rhs_int_val = rhs.int_val;
186 rhs_int_val *= ten_to_the((self.scale - rhs.scale) as u64);
187 self.int_val -= rhs_int_val;
188 }
189 }
190 }
191}
192
193impl<'rhs, T: Into<BigDecimalRef<'rhs>>> SubAssign<T> for BigDecimal {
194 #[inline]
195 fn sub_assign(&mut self, rhs: T) {
196 let rhs = rhs.into();
197 if rhs.is_zero() {
198 return;
199 }
200 if self.is_zero() {
201 *self = rhs.neg().to_owned();
202 return;
203 }
204
205 match self.scale.cmp(&rhs.scale) {
206 Ordering::Equal => {
207 self.int_val -= rhs.to_owned().int_val;
208 }
209 Ordering::Less => {
210 self.int_val *= ten_to_the((rhs.scale - self.scale) as u64);
211 self.int_val -= rhs.to_owned().int_val;
212 self.scale = rhs.scale;
213 }
214 Ordering::Greater => {
215 *self -= rhs.to_owned_with_scale(self.scale);
216 }
217 }
218 }
219}
220
221impl SubAssign<BigInt> for BigDecimal {
222 #[inline(always)]
223 fn sub_assign(&mut self, rhs: BigInt) {
224 *self -= BigDecimal::new(rhs, 0)
225 }
226}
227
228
229#[cfg(test)]
230mod test {
231 use super::*;
232 use paste::paste;
233
234 macro_rules! impl_case {
235 ($name:ident: $a:literal - $b:literal => $c:literal ) => {
236 #[test]
237 fn $name() {
238 let a: BigDecimal = $a.parse().unwrap();
239 let b: BigDecimal = $b.parse().unwrap();
240 let c: BigDecimal = $c.parse().unwrap();
241
242 assert_eq!(c, a.clone() - b.clone());
243
244 assert_eq!(c, a.clone() - &b);
245 assert_eq!(c, &a - b.clone());
246 assert_eq!(c, &a - &b);
247
248 assert_eq!(c, a.to_ref() - &b);
249 assert_eq!(c, &a - b.to_ref());
250 assert_eq!(c, a.to_ref() - b.to_ref());
251
252 let mut n = a.clone();
253 n -= b.to_ref();
254 assert_eq!(n, c);
255
256 let mut n = a.clone();
257 n -= &b;
258 assert_eq!(n, c);
259
260 let mut n = a.clone();
261 n -= b.clone();
262 assert_eq!(n, c);
263
264 let mut n = a.clone();
265 (&mut n).sub_assign(b.clone());
266 assert_eq!(n, c);
267 }
268 };
269 ($name:ident: $a:literal - (int) $b:literal => $c:literal ) => {
270 #[test]
271 fn $name() {
272 let a: BigDecimal = $a.parse().unwrap();
273 let b: BigInt = $b.parse().unwrap();
274 let expected: BigDecimal = $c.parse().unwrap();
275
276 assert_eq!(expected, a.clone() - b.clone());
277 assert_eq!(expected, a.clone() - &b);
278 assert_eq!(expected, &a - &b);
279 assert_eq!(expected, &a - b.clone());
280 assert_eq!(expected, a.to_ref() - &b);
281
282 let expected_neg = expected.clone().neg();
283 assert_eq!(expected_neg, b.clone() - a.clone());
284 assert_eq!(expected_neg, &b - a.to_ref());
285 assert_eq!(expected_neg, &b - a.clone());
286 }
287 };
288 }
289
290 impl_case!(case_1234en2_1234en3: "12.34" - "1.234" => "11.106");
291 impl_case!(case_1234en2_n1234en3: "12.34" - "-1.234" => "13.574");
292 impl_case!(case_1234e6_1234en6: "1234e6" - "1234e-6" => "1233999999.998766");
293 impl_case!(case_1234en6_1234e6: "1234e-6" - "1234e6" => "-1233999999.998766");
294 impl_case!(case_712911676en6_4856259269250829: "712911676e-6" - "4856259269250829" => "-4856259269250116.088324");
295 impl_case!(case_85616001e4_0: "85616001e4" - "0" => "85616001e4");
296 impl_case!(case_0_520707672en5: "0" - "5207.07672" => "-520707672e-5");
297 impl_case!(case_99291289e5_int0: "99291289e5" - (int)"0" => "99291289e5");
298 impl_case!(case_7051277471570131en16_int1: "0.7051277471570131" - (int)"1" => "-0.2948722528429869");
299 impl_case!(case_4068603022763836en8_intneg10: "40686030.22763836" - (int)"-10" => "40686040.22763836");
300
301 #[cfg(property_tests)]
302 mod prop {
303 use super::*;
304 use proptest::*;
305 use num_traits::FromPrimitive;
306
307 proptest! {
308 #[test]
309 fn sub_refs_and_owners(f: f32, g: f32) {
310 prop_assume!(f.is_normal());
312 prop_assume!(g.is_normal());
313
314 let a = BigDecimal::from_f32(f).unwrap();
315 let b = BigDecimal::from_f32(g).unwrap();
316 let own_minus_ref = a.clone() - &b;
317 let ref_minus_own = &a - b.clone();
318
319 let mut c = a.clone();
320 c -= &b;
321
322 let mut d = a.clone();
323 d -= b;
324
325 prop_assert_eq!(&own_minus_ref, &ref_minus_own);
326 prop_assert_eq!(&c, &ref_minus_own);
327 prop_assert_eq!(&d, &ref_minus_own);
328 }
329
330 #[test]
331 fn subtraction_is_anticommunative(f: f32, g: f32) {
332 prop_assume!(f.is_normal());
334 prop_assume!(g.is_normal());
335
336 let a = BigDecimal::from_f32(f).unwrap();
337 let b = BigDecimal::from_f32(g).unwrap();
338 let a_minus_b = &a - &b;
339 let b_minus_a = &b - &a;
340
341 prop_assert_eq!(a_minus_b, -b_minus_a)
342 }
343 }
344 }
345}