bigdecimal/
impl_ops_mul.rs
1use 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 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}