bigdecimal/
impl_ops_mul.rs1use 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
115impl 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
169impl 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 }
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 *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 let prod = &a * b.clone();
264 assert_eq!(prod, expected);
265 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 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 let prod = &a * &b;
308 assert_eq!(prod, c);
309 let prod = &b * &a;
312 assert_eq!(prod, c);
313 }
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 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}