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() {
14            rhs
15        } else if rhs.is_one() {
16            self
17        } else {
18            self.scale += rhs.scale;
19            self.int_val *= rhs.int_val;
20            self
21        }
22    }
23}
24
25impl<'a> Mul<&'a BigDecimal> for BigDecimal {
26    type Output = BigDecimal;
27
28    #[inline]
29    fn mul(mut self, rhs: &'a BigDecimal) -> BigDecimal {
30        if self.is_one() {
31            self.scale = rhs.scale;
32            self.int_val.set_zero();
33            self.int_val += &rhs.int_val;
34        } else if rhs.is_zero() {
35            self.scale = 0;
36            self.int_val.set_zero();
37        } else if !self.is_zero() && !rhs.is_one() {
38            self.scale += rhs.scale;
39            self.int_val *= &rhs.int_val;
40        }
41        self
42    }
43}
44
45impl Mul<BigDecimal> for &BigDecimal {
46    type Output = BigDecimal;
47
48    #[inline]
49    fn mul(self, rhs: BigDecimal) -> BigDecimal {
50        rhs * self
51    }
52}
53
54impl Mul<&BigDecimal> for &BigDecimal {
55    type Output = BigDecimal;
56
57    #[inline]
58    fn mul(self, rhs: &BigDecimal) -> BigDecimal {
59        if self.is_one() {
60            rhs.normalized()
61        } else if rhs.is_one() {
62            self.normalized()
63        } else {
64            let scale = self.scale + rhs.scale;
65            BigDecimal::new(&self.int_val * &rhs.int_val, scale)
66        }
67    }
68}
69
70impl Mul<BigInt> for BigDecimal {
71    type Output = BigDecimal;
72
73    #[inline]
74    fn mul(mut self, rhs: BigInt) -> BigDecimal {
75        self.int_val *= rhs;
76        self
77    }
78}
79
80impl Mul<&BigInt> for BigDecimal {
81    type Output = BigDecimal;
82
83    #[inline]
84    fn mul(mut self, rhs: &BigInt) -> BigDecimal {
85        self.int_val *= rhs;
86        self
87    }
88}
89
90impl Mul<BigInt> for &BigDecimal {
91    type Output = BigDecimal;
92
93    #[inline]
94    fn mul(self, mut rhs: BigInt) -> BigDecimal {
95        rhs *= &self.int_val;
96        BigDecimal::new(rhs, self.scale)
97    }
98}
99
100impl Mul<&BigInt> for &BigDecimal {
101    type Output = BigDecimal;
102
103    #[inline]
104    fn mul(self, rhs: &BigInt) -> BigDecimal {
105        if rhs.is_one() {
106            self.normalized()
107        } else if self.is_one() {
108            BigDecimal::new(rhs.clone(), 0)
109        } else {
110            let value = &self.int_val * rhs;
111            BigDecimal::new(value, self.scale)
112        }
113    }
114}
115
116impl Mul<BigDecimal> for BigInt {
117    type Output = BigDecimal;
118
119    #[inline]
120    fn mul(mut self, mut rhs: BigDecimal) -> BigDecimal {
121        if rhs.is_one() {
122            rhs.scale = 0;
123            swap(&mut rhs.int_val, &mut self);
124        } else if !self.is_one() {
125            rhs.int_val *= self;
126        }
127        rhs
128    }
129}
130
131impl Mul<BigDecimal> for &BigInt {
132    type Output = BigDecimal;
133
134    #[inline]
135    fn mul(self, mut rhs: BigDecimal) -> BigDecimal {
136        if self.is_one() {
137            rhs.normalized()
138        } else if rhs.is_one() {
139            rhs.int_val.set_zero();
140            rhs.int_val += self;
141            rhs.scale = 0;
142            rhs
143        } else {
144            rhs.int_val *= self;
145            rhs
146        }
147    }
148}
149
150impl Mul<&BigDecimal> for &BigInt {
151    type Output = BigDecimal;
152
153    #[inline]
154    fn mul(self, rhs: &BigDecimal) -> BigDecimal {
155        if self.is_one() {
156            rhs.normalized()
157        } else if rhs.is_one() {
158            BigDecimal::new(self.clone(), 0)
159        } else {
160            let value = &rhs.int_val * self;
161            BigDecimal::new(value, rhs.scale)
162        }
163    }
164}
165
166impl Mul<&BigDecimal> for BigInt {
167    type Output = BigDecimal;
168
169    #[inline]
170    fn mul(mut self, rhs: &BigDecimal) -> BigDecimal {
171        if self.is_one() {
172            rhs.normalized()
173        } else if rhs.is_one() {
174            BigDecimal::new(self, 0)
175        } else {
176            self *= &rhs.int_val;
177            BigDecimal::new(self, rhs.scale)
178        }
179    }
180}
181
182forward_val_assignop!(impl MulAssign for BigDecimal, mul_assign);
183
184impl MulAssign<&BigDecimal> for BigDecimal {
185    #[inline]
186    fn mul_assign(&mut self, rhs: &BigDecimal) {
187        if rhs.is_one() {
188            return;
189        }
190        self.scale += rhs.scale;
191        self.int_val = &self.int_val * &rhs.int_val;
192    }
193}
194
195impl MulAssign<&BigInt> for BigDecimal {
196    #[inline]
197    fn mul_assign(&mut self, rhs: &BigInt) {
198        if rhs.is_one() {
199            return;
200        }
201        self.int_val *= rhs;
202    }
203}
204
205impl MulAssign<BigInt> for BigDecimal {
206    #[inline]
207    fn mul_assign(&mut self, rhs: BigInt) {
208        *self *= &rhs
209    }
210}
211
212
213#[cfg(test)]
214#[allow(non_snake_case)]
215mod bigdecimal_tests {
216    use super::*;
217    use num_traits::{ToPrimitive, FromPrimitive, Signed, Zero, One};
218    use num_bigint;
219    use paste::paste;
220
221    macro_rules! impl_test {
222        ($name:ident; $a:literal * $b:literal => $expected:literal) => {
223            #[test]
224            fn $name() {
225                let mut a: BigDecimal = $a.parse().unwrap();
226                let b: BigDecimal = $b.parse().unwrap();
227                let expected = $expected.parse().unwrap();
228
229                let prod = a.clone() * b.clone();
230                assert_eq!(prod, expected);
231                assert_eq!(prod.scale, expected.scale);
232
233                assert_eq!(a.clone() * &b, expected);
234                assert_eq!(&a * b.clone(), expected);
235                assert_eq!(&a * &b, expected);
236
237                a *= b;
238                assert_eq!(a, expected);
239                assert_eq!(a.scale, expected.scale);
240            }
241        };
242        ($name:ident; $bigt:ty; $a:literal * $b:literal => $expected:literal) => {
243            #[test]
244            fn $name() {
245                let a: BigDecimal = $a.parse().unwrap();
246                let b: $bigt = $b.parse().unwrap();
247                let c = $expected.parse().unwrap();
248
249                let prod = a.clone() * b.clone();
250                assert_eq!(prod, c);
251                assert_eq!(prod.scale, c.scale);
252
253                assert_eq!(b.clone() * a.clone(), c);
254                assert_eq!(a.clone() * &b, c);
255                assert_eq!(b.clone() * &a, c);
256                assert_eq!(&a * b.clone(), c);
257                assert_eq!(&b * a.clone(), c);
258                assert_eq!(&a * &b, c);
259                assert_eq!(&b * &a, c);
260            }
261        };
262    }
263
264    impl_test!(case_2_1; "2" * "1" => "2");
265    impl_test!(case_12d34_1d234; "12.34" * "1.234" => "15.22756");
266    impl_test!(case_2e1_1; "2e1" * "1" => "2e1");
267    impl_test!(case_3_d333333; "3" * ".333333" => "0.999999");
268    impl_test!(case_2389472934723_209481029831; "2389472934723" * "209481029831" => "500549251119075878721813");
269    impl_test!(case_1ed450_1e500; "1e-450" * "1e500" => "0.1e51");
270    impl_test!(case_n995052931ddd_4d523087321; "-995052931372975485719.533153137" * "4.523087321" => "-4500711297616988541501.836966993116075977");
271    impl_test!(case_995052931ddd_n4d523087321; "995052931372975485719.533153137" * "-4.523087321" => "-4500711297616988541501.836966993116075977");
272    impl_test!(case_n8d37664968_n4d523087321; "-8.37664968" * "-1.9086963714056968482094712882596748" => "15.988480848752691653730876239769592670324064");
273    impl_test!(case_n8d37664968_0; "-8.37664968" * "0" => "0.00000000");
274
275    impl_test!(case_8d561_10; BigInt; "8.561" * "10" => "85.610");
276
277    // Test multiplication between big decimal and big integer
278    impl_test!(case_10000_638655273892892437; BigInt; "10000" * "638655273892892437" => "6386552738928924370000");
279    impl_test!(case_1en10_n9056180052657301; BigInt; "1e-10" * "-9056180052657301" => "-905618.0052657301");
280    impl_test!(case_n9en1_n368408638655273892892437473; BigInt; "-9e-1" * "-368408638655273892892437473" => "331567774789746503603193725.7");
281    impl_test!(case_n1d175470587012343730098_577575785; BigInt; "-1.175470587012343730098" * "577575785" => "-678923347.038065234601180476930");
282}