bigdecimal/
impl_ops.rs
1use crate::*;
4
5
6macro_rules! impl_add_for_primitive {
7 ($t:ty) => {
8 impl_add_for_primitive!(IMPL:ADD $t);
9 impl_add_for_primitive!(IMPL:ADD-ASSIGN $t);
10 impl_add_for_primitive!(IMPL:ADD &$t);
11 impl_add_for_primitive!(IMPL:ADD-ASSIGN &$t);
12 };
13 (IMPL:ADD $t:ty) => {
14 impl Add<$t> for BigDecimal {
15 type Output = BigDecimal;
16
17 fn add(mut self, rhs: $t) -> BigDecimal {
18 self += rhs;
19 self
20 }
21 }
22
23 impl Add<$t> for &BigDecimal {
24 type Output = BigDecimal;
25
26 fn add(self, rhs: $t) -> BigDecimal {
27 self.to_ref() + rhs
28 }
29 }
30
31 impl Add<$t> for BigDecimalRef<'_> {
32 type Output = BigDecimal;
33
34 fn add(self, rhs: $t) -> BigDecimal {
35 BigDecimal::from(rhs) + self
36 }
37 }
38
39 impl Add<BigDecimal> for $t {
40 type Output = BigDecimal;
41
42 fn add(self, rhs: BigDecimal) -> BigDecimal {
43 rhs + self
44 }
45 }
46
47 impl Add<&BigDecimal> for $t {
48 type Output = BigDecimal;
49
50 fn add(self, rhs: &BigDecimal) -> BigDecimal {
51 rhs + self
52 }
53 }
54 };
55 (IMPL:ADD-ASSIGN &$t:ty) => {
56 impl AddAssign<&$t> for BigDecimal {
58 fn add_assign(&mut self, rhs: &$t) {
59 *self += *rhs;
60 }
61 }
62 };
63 (IMPL:ADD-ASSIGN $t:ty) => {
64 impl AddAssign<$t> for BigDecimal {
65 fn add_assign(&mut self, rhs: $t) {
66 if rhs == 0 {
67 } else if self.scale == 0 {
69 self.int_val += rhs;
70 } else {
71 *self += BigDecimal::from(rhs);
72 }
73 }
74 }
75 };
76}
77
78impl_add_for_primitive!(u8);
79impl_add_for_primitive!(u16);
80impl_add_for_primitive!(u32);
81impl_add_for_primitive!(u64);
82impl_add_for_primitive!(u128);
83impl_add_for_primitive!(i8);
84impl_add_for_primitive!(i16);
85impl_add_for_primitive!(i32);
86impl_add_for_primitive!(i64);
87impl_add_for_primitive!(i128);
88
89
90macro_rules! impl_sub_for_primitive {
91 ($t:ty) => {
92 impl_sub_for_primitive!(IMPL:SUB $t);
93 impl_sub_for_primitive!(IMPL:SUB-ASSIGN $t);
94 impl_sub_for_primitive!(IMPL:SUB &$t);
95 impl_sub_for_primitive!(IMPL:SUB-ASSIGN &$t);
96 };
97 (IMPL:SUB $t:ty) => {
98 impl Sub<$t> for BigDecimal {
99 type Output = BigDecimal;
100
101 fn sub(mut self, rhs: $t) -> BigDecimal {
102 self -= rhs;
103 self
104 }
105 }
106
107 impl Sub<$t> for &BigDecimal {
108 type Output = BigDecimal;
109
110 fn sub(self, rhs: $t) -> BigDecimal {
111 let res = BigDecimal::from(rhs).neg();
112 res + self
113 }
114 }
115
116 impl Sub<BigDecimal> for $t {
117 type Output = BigDecimal;
118
119 fn sub(self, rhs: BigDecimal) -> BigDecimal {
120 rhs.neg() + self
121 }
122 }
123
124 impl Sub<&BigDecimal> for $t {
125 type Output = BigDecimal;
126
127 fn sub(self, rhs: &BigDecimal) -> BigDecimal {
128 rhs.neg() + self
129 }
130 }
131 };
132 (IMPL:SUB-ASSIGN &$t:ty) => {
133 impl SubAssign<&$t> for BigDecimal {
134 fn sub_assign(&mut self, rhs: &$t) {
135 *self -= *rhs;
136 }
137 }
138 };
139 (IMPL:SUB-ASSIGN $t:ty) => {
140 impl SubAssign<$t> for BigDecimal {
141 fn sub_assign(&mut self, rhs: $t) {
142 if self.scale == 0 {
143 self.int_val -= rhs;
144 } else {
145 *self -= BigDecimal::from(rhs);
146 }
147 }
148 }
149 };
150}
151
152
153impl_sub_for_primitive!(u8);
154impl_sub_for_primitive!(u16);
155impl_sub_for_primitive!(u32);
156impl_sub_for_primitive!(u64);
157impl_sub_for_primitive!(u128);
158impl_sub_for_primitive!(i8);
159impl_sub_for_primitive!(i16);
160impl_sub_for_primitive!(i32);
161impl_sub_for_primitive!(i64);
162impl_sub_for_primitive!(i128);
163
164
165macro_rules! impl_mul_for_primitive {
166 ($t:ty) => {
167 impl_mul_for_primitive!(IMPL:MUL $t);
168 impl_mul_for_primitive!(IMPL:MUL-ASSIGN $t);
169 impl_mul_for_primitive!(IMPL:MUL &$t);
170 impl_mul_for_primitive!(IMPL:MUL-ASSIGN &$t);
171 };
172 (IMPL:MUL $t:ty) => {
173 impl Mul<$t> for BigDecimal {
174 type Output = BigDecimal;
175
176 fn mul(mut self, rhs: $t) -> BigDecimal {
177 self *= rhs;
178 self
179 }
180 }
181
182 impl Mul<$t> for &BigDecimal {
183 type Output = BigDecimal;
184
185 fn mul(self, rhs: $t) -> BigDecimal {
186 let res = BigDecimal::from(rhs);
187 res * self
188 }
189 }
190
191 impl Mul<BigDecimal> for $t {
192 type Output = BigDecimal;
193
194 fn mul(self, rhs: BigDecimal) -> BigDecimal {
195 rhs * self
196 }
197 }
198
199 impl Mul<&BigDecimal> for $t {
200 type Output = BigDecimal;
201
202 fn mul(self, rhs: &BigDecimal) -> BigDecimal {
203 rhs * self
204 }
205 }
206 };
207 (IMPL:MUL-ASSIGN $t:ty) => {
208 impl MulAssign<$t> for BigDecimal {
209 fn mul_assign(&mut self, rhs: $t) {
210 if rhs.is_zero() {
211 *self = BigDecimal::zero()
212 } else if rhs.is_one() {
213 } else {
215 *self *= BigDecimal::from(rhs);
216 }
217 }
218 }
219 };
220}
221
222
223impl_mul_for_primitive!(u8);
224impl_mul_for_primitive!(u16);
225impl_mul_for_primitive!(u32);
226impl_mul_for_primitive!(u64);
227impl_mul_for_primitive!(u128);
228impl_mul_for_primitive!(i8);
229impl_mul_for_primitive!(i16);
230impl_mul_for_primitive!(i32);
231impl_mul_for_primitive!(i64);
232impl_mul_for_primitive!(i128);
233
234macro_rules! impl_div_for_primitive {
235 (f32) => {
236 impl_div_for_primitive!(IMPL:DIV:FLOAT f32);
237 impl_div_for_primitive!(IMPL:DIV:REF &f32);
238 };
239 (f64) => {
240 impl_div_for_primitive!(IMPL:DIV:FLOAT f64);
241 impl_div_for_primitive!(IMPL:DIV:REF &f64);
242 };
243 ($t:ty) => {
244 impl_div_for_primitive!(IMPL:DIV $t);
245 impl_div_for_primitive!(IMPL:DIV:REF &$t);
246 impl_div_for_primitive!(IMPL:DIV-ASSIGN $t);
247 };
248 (IMPL:DIV $t:ty) => {
249 impl Div<$t> for BigDecimal {
250 type Output = BigDecimal;
251
252 #[cfg(rustc_1_70)] #[allow(clippy::incompatible_msrv)]
254 fn div(self, denom: $t) -> BigDecimal {
255 if denom.is_one() {
256 self
257 } else if denom.checked_neg().is_some_and(|n| n == 1) {
258 self.neg()
259 } else if denom.clone() == 2 {
260 self.half()
261 } else if denom.checked_neg().is_some_and(|n| n == 2) {
262 self.half().neg()
263 } else {
264 self / BigDecimal::from(denom)
265 }
266 }
267
268 #[cfg(not(rustc_1_70))]
269 fn div(self, denom: $t) -> BigDecimal {
270 if denom.is_one() {
271 self
272 } else if denom.checked_neg().map(|n| n == 1).unwrap_or(false) {
273 self.neg()
274 } else if denom.clone() == 2 {
275 self.half()
276 } else if denom.checked_neg().map(|n| n == 2).unwrap_or(false) {
277 self.half().neg()
278 } else {
279 self / BigDecimal::from(denom)
280 }
281 }
282 }
283
284 impl Div<$t> for &BigDecimal {
285 type Output = BigDecimal;
286
287 fn div(self, denom: $t) -> BigDecimal {
288 self.clone() / denom
289 }
290 }
291
292 impl Div<BigDecimal> for $t {
293 type Output = BigDecimal;
294
295 fn div(self, denom: BigDecimal) -> BigDecimal {
296 if self.is_one() {
297 denom.inverse()
298 } else {
299 BigDecimal::from(self) / denom
300 }
301 }
302 }
303
304 impl Div<&BigDecimal> for $t {
305 type Output = BigDecimal;
306
307 fn div(self, denom: &BigDecimal) -> BigDecimal {
308 self / denom.clone()
309 }
310 }
311 };
312 (IMPL:DIV-ASSIGN $t:ty) => {
313 impl DivAssign<$t> for BigDecimal {
314 fn div_assign(&mut self, rhs: $t) {
315 if rhs.is_zero() {
316 *self = BigDecimal::zero()
317 } else if rhs.is_one() {
318 } else {
320 *self = self.clone() / BigDecimal::from(rhs);
321 }
322 }
323 }
324 };
325 (IMPL:DIV:REF $t:ty) => {
326 impl Div<$t> for BigDecimal {
327 type Output = BigDecimal;
328
329 fn div(self, denom: $t) -> BigDecimal {
330 self / *denom
331 }
332 }
333
334 impl Div<BigDecimal> for $t {
335 type Output = BigDecimal;
336
337 fn div(self, denom: BigDecimal) -> Self::Output {
338 *self / denom
339 }
340 }
341
342 impl Div<&BigDecimal> for $t {
343 type Output = BigDecimal;
344
345 fn div(self, denom: &BigDecimal) -> Self::Output {
346 *self / denom
347 }
348 }
349
350 impl DivAssign<$t> for BigDecimal {
351 fn div_assign(&mut self, denom: $t) {
352 self.div_assign(*denom)
353 }
354 }
355 };
356 (IMPL:DIV:FLOAT $t:ty) => {
357 impl Div<$t> for BigDecimal {
358 type Output = BigDecimal;
359
360 #[allow(clippy::float_cmp)]
361 fn div(self, denom: $t) -> BigDecimal {
362 if !denom.is_normal() {
363 BigDecimal::zero()
364 } else if denom == (1.0 as $t) {
365 self
366 } else if denom == (-1.0 as $t) {
367 self.neg()
368 } else if denom == (2.0 as $t) {
369 self.half()
370 } else if denom == (-2.0 as $t) {
371 self.half().neg()
372 } else {
373 self / BigDecimal::try_from(denom).unwrap()
374 }
375 }
376 }
377
378 impl Div<$t> for &BigDecimal {
379 type Output = BigDecimal;
380
381 fn div(self, denom: $t) -> BigDecimal {
382 self.clone() / denom
383 }
384 }
385
386 impl Div<BigDecimal> for $t {
387 type Output = BigDecimal;
388
389 fn div(self, denom: BigDecimal) -> Self::Output {
390 if !self.is_normal() {
391 BigDecimal::zero()
392 } else if self.is_one() {
393 denom.inverse()
394 } else {
395 BigDecimal::try_from(self).unwrap() / denom
396 }
397 }
398 }
399
400 impl Div<&BigDecimal> for $t {
401 type Output = BigDecimal;
402
403 fn div(self, denom: &BigDecimal) -> Self::Output {
404 if !self.is_normal() {
405 BigDecimal::zero()
406 } else if self.is_one() {
407 denom.inverse()
408 } else {
409 BigDecimal::try_from(self).unwrap() / denom
410 }
411 }
412 }
413
414 impl DivAssign<$t> for BigDecimal {
415 fn div_assign(&mut self, denom: $t) {
416 if !denom.is_normal() {
417 *self = BigDecimal::zero()
418 } else {
419 *self = self.clone() / BigDecimal::try_from(denom).unwrap()
420 };
421 }
422 }
423 };
424}
425
426
427impl_div_for_primitive!(u8);
428impl_div_for_primitive!(u16);
429impl_div_for_primitive!(u32);
430impl_div_for_primitive!(u64);
431impl_div_for_primitive!(u128);
432impl_div_for_primitive!(i8);
433impl_div_for_primitive!(i16);
434impl_div_for_primitive!(i32);
435impl_div_for_primitive!(i64);
436impl_div_for_primitive!(i128);
437
438impl_div_for_primitive!(f32);
439impl_div_for_primitive!(f64);
440
441
442impl Neg for BigDecimal {
443 type Output = BigDecimal;
444
445 #[inline]
446 fn neg(mut self) -> BigDecimal {
447 self.int_val = -self.int_val;
448 self
449 }
450}
451
452impl Neg for &BigDecimal {
453 type Output = BigDecimal;
454
455 #[inline]
456 fn neg(self) -> BigDecimal {
457 -self.clone()
458 }
459}
460
461impl Neg for BigDecimalRef<'_> {
462 type Output = Self;
463
464 fn neg(self) -> Self::Output {
465 Self {
466 sign: self.sign.neg(),
467 digits: self.digits,
468 scale: self.scale,
469 }
470 }
471}