bigdecimal/
impl_ops_mul.rs

1//! Multiplication operator trait implementation
2//!
3
4use super::*;
5use crate::stdlib::mem::swap;
6
7
8impl Mul<BigDecimal> for BigDecimal {
9    type Output = BigDecimal;
10
11    #[inline]
12    fn mul(mut self, rhs: BigDecimal) -> BigDecimal {
13        if self.is_one_quickcheck() == Some(true) {
14            return rhs;
15        }
16        if rhs.is_one_quickcheck() != Some(true) {
17            self.scale += rhs.scale;
18            self.int_val *= rhs.int_val;
19        }
20        self
21    }
22}
23
24impl Mul<&BigDecimal> for BigDecimal {
25    type Output = BigDecimal;
26
27    #[inline]
28    fn mul(mut self, rhs: &BigDecimal) -> BigDecimal {
29        if self.is_one_quickcheck() == Some(true) {
30            self.scale = rhs.scale;
31            self.int_val.set_zero();
32            self.int_val += &rhs.int_val;
33        } else if rhs.is_zero() {
34            self.scale = 0;
35            self.int_val.set_zero();
36        } else if !self.is_zero() && rhs.is_one_quickcheck() != Some(true) {
37            self.scale += rhs.scale;
38            self.int_val *= &rhs.int_val;
39        }
40        self
41    }
42}
43
44impl Mul<BigDecimal> for &BigDecimal {
45    type Output = BigDecimal;
46
47    #[inline]
48    fn mul(self, rhs: BigDecimal) -> BigDecimal {
49        rhs * self
50    }
51}
52
53impl Mul<&BigDecimal> for &BigDecimal {
54    type Output = BigDecimal;
55
56    #[inline]
57    fn mul(self, rhs: &BigDecimal) -> BigDecimal {
58        if self.is_one_quickcheck() == Some(true) {
59            rhs.normalized()
60        } else if rhs.is_one_quickcheck() == Some(true) {
61            self.normalized()
62        } else {
63            let scale = self.scale + rhs.scale;
64            BigDecimal::new(&self.int_val * &rhs.int_val, scale)
65        }
66    }
67}
68
69impl Mul<BigInt> for BigDecimal {
70    type Output = BigDecimal;
71
72    #[inline]
73    fn mul(mut self, rhs: BigInt) -> BigDecimal {
74        self.int_val *= rhs;
75        self
76    }
77}
78
79impl Mul<&BigInt> for BigDecimal {
80    type Output = BigDecimal;
81
82    #[inline]
83    fn mul(mut self, rhs: &BigInt) -> BigDecimal {
84        self.int_val *= rhs;
85        self
86    }
87}
88
89impl Mul<BigInt> for &BigDecimal {
90    type Output = BigDecimal;
91
92    #[inline]
93    fn mul(self, mut rhs: BigInt) -> BigDecimal {
94        rhs *= &self.int_val;
95        BigDecimal::new(rhs, self.scale)
96    }
97}
98
99impl Mul<&BigInt> for &BigDecimal {
100    type Output = BigDecimal;
101
102    #[inline]
103    fn mul(self, rhs: &BigInt) -> BigDecimal {
104        if rhs.is_one() {
105            self.normalized()
106        } else if self.is_one_quickcheck() == Some(true) {
107            BigDecimal::new(rhs.clone(), 0)
108        } else {
109            let value = &self.int_val * rhs;
110            BigDecimal::new(value, self.scale)
111        }
112    }
113}
114
115// swap (lhs * rhs) to (rhs * lhs) for (BigInt * BigDecimal)
116impl Mul<BigDecimal> for BigInt {
    type Output = BigDecimal;
    #[inline]
    fn mul(self, rhs: BigDecimal) -> Self::Output { Mul::mul(rhs, self) }
}forward_communative_binop!(impl Mul<BigDecimal>::mul for BigInt);
117impl Mul<&BigDecimal> for BigInt {
    type Output = BigDecimal;
    #[inline]
    fn mul(self, rhs: &BigDecimal) -> Self::Output { Mul::mul(rhs, self) }
}forward_communative_binop!(impl Mul<&BigDecimal>::mul for BigInt);
118impl Mul<BigDecimal> for &BigInt {
    type Output = BigDecimal;
    #[inline]
    fn mul(self, rhs: BigDecimal) -> Self::Output { Mul::mul(rhs, self) }
}forward_communative_binop!(impl Mul<BigDecimal>::mul for &BigInt);
119impl Mul<&BigDecimal> for &BigInt {
    type Output = BigDecimal;
    #[inline]
    fn mul(self, rhs: &BigDecimal) -> Self::Output { Mul::mul(rhs, self) }
}forward_communative_binop!(impl Mul<&BigDecimal>::mul for &BigInt);
120
121
122impl Mul<BigUint> for BigDecimal {
123    type Output = BigDecimal;
124
125    #[inline]
126    fn mul(mut self, rhs: BigUint) -> BigDecimal {
127        self *= rhs;
128        self
129    }
130}
131
132impl Mul<&BigUint> for BigDecimal {
133    type Output = BigDecimal;
134
135    #[inline]
136    fn mul(mut self, rhs: &BigUint) -> BigDecimal {
137        self *= rhs;
138        self
139    }
140}
141
142impl Mul<BigUint> for &BigDecimal {
143    type Output = BigDecimal;
144
145    #[inline]
146    fn mul(self, rhs: BigUint) -> BigDecimal {
147        self * BigInt::from_biguint(Sign::Plus, rhs)
148    }
149}
150
151impl Mul<&BigUint> for &BigDecimal {
152    type Output = BigDecimal;
153
154    #[inline]
155    fn mul(self, rhs: &BigUint) -> BigDecimal {
156        if rhs.is_one() {
157            self.normalized()
158        } else if self.is_one_quickcheck() == Some(true) {
159            let value = BigInt::from_biguint(Sign::Plus, rhs.clone());
160            BigDecimal::new(value, 0)
161        } else {
162            let biguint = self.int_val.magnitude() * rhs;
163            let value = BigInt::from_biguint(self.sign(), biguint);
164            BigDecimal::new(value, self.scale)
165        }
166    }
167}
168
169// swap (lhs * rhs) to (rhs * lhs) for (BigUint * BigDecimal)
170impl Mul<BigDecimal> for BigUint {
    type Output = BigDecimal;
    #[inline]
    fn mul(self, rhs: BigDecimal) -> Self::Output { Mul::mul(rhs, self) }
}forward_communative_binop!(impl Mul<BigDecimal>::mul for BigUint);
171impl Mul<&BigDecimal> for BigUint {
    type Output = BigDecimal;
    #[inline]
    fn mul(self, rhs: &BigDecimal) -> Self::Output { Mul::mul(rhs, self) }
}forward_communative_binop!(impl Mul<&BigDecimal>::mul for BigUint);
172impl Mul<BigDecimal> for &BigUint {
    type Output = BigDecimal;
    #[inline]
    fn mul(self, rhs: BigDecimal) -> Self::Output { Mul::mul(rhs, self) }
}forward_communative_binop!(impl Mul<BigDecimal>::mul for &BigUint);
173impl Mul<&BigDecimal> for &BigUint {
    type Output = BigDecimal;
    #[inline]
    fn mul(self, rhs: &BigDecimal) -> Self::Output { Mul::mul(rhs, self) }
}forward_communative_binop!(impl Mul<&BigDecimal>::mul for &BigUint);
174
175
176impl MulAssign<BigDecimal> for BigDecimal {
177    #[inline]
178    fn mul_assign(&mut self, rhs: BigDecimal) {
179        if self.is_one_quickcheck() == Some(true) {
180            self.int_val = rhs.int_val;
181            self.scale = rhs.scale;
182        } else if rhs.is_one_quickcheck() != Some(true) {
183            self.scale += rhs.scale;
184            self.int_val *= rhs.int_val;
185        }
186    }
187}
188
189impl MulAssign<&BigDecimal> for BigDecimal {
190    #[inline]
191    fn mul_assign(&mut self, rhs: &BigDecimal) {
192        if rhs.is_one_quickcheck() == Some(true) {
193            return;
194        }
195        self.scale += rhs.scale;
196        self.int_val *= &rhs.int_val;
197    }
198}
199
200impl MulAssign<&BigInt> for BigDecimal {
201    #[inline]
202    fn mul_assign(&mut self, rhs: &BigInt) {
203        if rhs.is_one() {
204            return;
205        }
206        self.int_val *= rhs;
207    }
208}
209
210impl MulAssign<BigInt> for BigDecimal {
211    #[inline]
212    fn mul_assign(&mut self, rhs: BigInt) {
213        *self *= &rhs
214    }
215}
216
217impl MulAssign<BigUint> for BigDecimal {
218    #[inline]
219    fn mul_assign(&mut self, rhs: BigUint) {
220        if rhs.is_one() {
221            return;
222        }
223        *self *= BigInt::from_biguint(Sign::Plus, rhs);
224        // *self *= &rhs
225    }
226}
227
228impl MulAssign<&BigUint> for BigDecimal {
229    #[inline]
230    fn mul_assign(&mut self, rhs: &BigUint) {
231        if rhs.is_one() {
232            return;
233        }
234        // No way to multiply bigint and biguint, we have to clone
235        *self *= BigInt::from_biguint(Sign::Plus, rhs.clone());
236    }
237}
238
239#[cfg(test)]
240#[allow(non_snake_case)]
241mod bigdecimal_tests {
242    use super::*;
243    use num_traits::{ToPrimitive, FromPrimitive, Signed, Zero, One};
244    use num_bigint;
245    use paste::paste;
246
247    macro_rules! impl_test {
248        ($name:ident; $a:literal * $b:literal => $expected:literal) => {
249            #[test]
250            fn $name() {
251                let mut a: BigDecimal = $a.parse().unwrap();
252                let b: BigDecimal = $b.parse().unwrap();
253                let expected = $expected.parse().unwrap();
254
255                let prod = a.clone() * b.clone();
256                assert_eq!(prod, expected);
257                assert_eq!(prod.scale, expected.scale);
258
259                let prod = a.clone() * &b;
260                assert_eq!(prod, expected);
261                // assert_eq!(prod.scale, expected.scale);
262
263                let prod = &a * b.clone();
264                assert_eq!(prod, expected);
265                // assert_eq!(prod.scale, expected.scale);
266
267                let prod = &a * &b;
268                assert_eq!(prod, expected);
269                assert_eq!(prod.scale, expected.scale);
270
271                a *= b;
272                assert_eq!(a, expected);
273                assert_eq!(a.scale, expected.scale);
274            }
275        };
276        ($name:ident; $bigt:ty; $a:literal * $b:literal => $expected:literal) => {
277            #[test]
278            fn $name() {
279                let a: BigDecimal = $a.parse().unwrap();
280                let b: $bigt = $b.parse().unwrap();
281                let c = $expected.parse().unwrap();
282
283                let prod = a.clone() * b.clone();
284                assert_eq!(prod, c);
285                assert_eq!(prod.scale, c.scale);
286
287                let prod = b.clone() * a.clone();
288                assert_eq!(prod, c);
289                assert_eq!(prod.scale, c.scale);
290
291                let prod = a.clone() * &b;
292                assert_eq!(prod, c);
293                assert_eq!(prod.scale, c.scale);
294
295                let prod = b.clone() * &a;
296                assert_eq!(prod, c);
297                // assert_eq!(prod.scale, c.scale);
298
299                let prod = &a * b.clone();
300                assert_eq!(prod, c);
301                assert_eq!(prod.scale, c.scale);
302
303                let prod = &b * a.clone();
304                assert_eq!(prod, c);
305                // assert_eq!(prod.scale, c.scale);
306
307                let prod = &a * &b;
308                assert_eq!(prod, c);
309                // assert_eq!(prod.scale, c.scale);
310
311                let prod = &b * &a;
312                assert_eq!(prod, c);
313                // assert_eq!(prod.scale, c.scale);
314            }
315        };
316    }
317
318    impl_test!(case_2_1; "2" * "1" => "2");
319    impl_test!(case_12d34_1d234; "12.34" * "1.234" => "15.22756");
320    impl_test!(case_2e1_1; "2e1" * "1" => "2e1");
321    impl_test!(case_3_d333333; "3" * ".333333" => "0.999999");
322    impl_test!(case_2389472934723_209481029831; "2389472934723" * "209481029831" => "500549251119075878721813");
323    impl_test!(case_1ed450_1e500; "1e-450" * "1e500" => "0.1e51");
324    impl_test!(case_n995052931ddd_4d523087321; "-995052931372975485719.533153137" * "4.523087321" => "-4500711297616988541501.836966993116075977");
325    impl_test!(case_995052931ddd_n4d523087321; "995052931372975485719.533153137" * "-4.523087321" => "-4500711297616988541501.836966993116075977");
326    impl_test!(case_n8d37664968_n4d523087321; "-8.37664968" * "-1.9086963714056968482094712882596748" => "15.988480848752691653730876239769592670324064");
327    impl_test!(case_n8d37664968_0; "-8.37664968" * "0" => "0.00000000");
328
329    impl_test!(case_8d561_10; BigInt; "8.561" * "10" => "85.610");
330
331    // Test multiplication between big decimal and big integer
332    impl_test!(case_10000_638655273892892437; BigInt; "10000" * "638655273892892437" => "6386552738928924370000");
333    impl_test!(case_1en10_n9056180052657301; BigInt; "1e-10" * "-9056180052657301" => "-905618.0052657301");
334    impl_test!(case_n9en1_n368408638655273892892437473; BigInt; "-9e-1" * "-368408638655273892892437473" => "331567774789746503603193725.7");
335    impl_test!(case_n1d175470587012343730098_577575785; BigInt; "-1.175470587012343730098" * "577575785" => "-678923347.038065234601180476930");
336
337    impl_test!(case_1d000000_7848321491728058276; BigInt; "1.000000" * "7848321491728058276" => "7848321491728058276.000000");
338    impl_test!(case_16535178640845d04844_1; BigInt; "16535178640845.04844" * "1" => "16535178640845.04844");
339
340    impl_test!(case_1d000000_u7848321491728058276; BigUint; "1.000000" * "7848321491728058276" => "7848321491728058276.000000");
341    impl_test!(case_16535178640845d04844_u1; BigUint; "16535178640845.04844" * "1" => "16535178640845.04844");
342}