decimal_rs/
ops.rs

1// Copyright 2021 CoD Technologies Corp.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Ops implementation.
16
17use crate::decimal::Decimal;
18use std::convert::TryFrom;
19use std::iter::{Product, Sum};
20use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign};
21
22impl Neg for Decimal {
23    type Output = Decimal;
24
25    #[inline]
26    fn neg(mut self) -> Self::Output {
27        self.neg_mut();
28        self
29    }
30}
31
32impl Neg for &'_ Decimal {
33    type Output = Decimal;
34
35    #[inline]
36    fn neg(self) -> Self::Output {
37        if !self.is_zero() {
38            unsafe { Decimal::from_raw_parts(self.int_val(), self.scale(), !self.is_sign_negative()) }
39        } else {
40            Decimal::ZERO
41        }
42    }
43}
44
45impl Add<&Decimal> for &Decimal {
46    type Output = Decimal;
47
48    #[inline(always)]
49    fn add(self, other: &Decimal) -> Self::Output {
50        match self.checked_add(other) {
51            Some(sum) => sum,
52            None => panic!("Addition overflowed"),
53        }
54    }
55}
56
57impl AddAssign<&Decimal> for Decimal {
58    #[inline(always)]
59    fn add_assign(&mut self, other: &Decimal) {
60        let result = self.add(other);
61        *self = result;
62    }
63}
64
65impl Sub<&Decimal> for &Decimal {
66    type Output = Decimal;
67
68    #[inline(always)]
69    fn sub(self, other: &Decimal) -> Decimal {
70        match self.checked_sub(other) {
71            Some(diff) => diff,
72            None => panic!("Subtraction overflowed"),
73        }
74    }
75}
76
77impl SubAssign<&Decimal> for Decimal {
78    #[inline(always)]
79    fn sub_assign(&mut self, other: &Decimal) {
80        let result = self.sub(other);
81        *self = result;
82    }
83}
84
85impl Mul<&Decimal> for &Decimal {
86    type Output = Decimal;
87
88    #[inline(always)]
89    fn mul(self, other: &Decimal) -> Decimal {
90        match self.checked_mul(other) {
91            Some(prod) => prod,
92            None => panic!("Multiplication overflowed"),
93        }
94    }
95}
96
97impl MulAssign<&Decimal> for Decimal {
98    #[inline(always)]
99    fn mul_assign(&mut self, other: &Decimal) {
100        let result = self.mul(other);
101        *self = result;
102    }
103}
104
105impl Div<&Decimal> for &Decimal {
106    type Output = Decimal;
107
108    #[inline(always)]
109    fn div(self, other: &Decimal) -> Decimal {
110        match self.checked_div(other) {
111            Some(quot) => quot,
112            None => panic!("Division by zero or overflowed"),
113        }
114    }
115}
116
117impl DivAssign<&Decimal> for Decimal {
118    #[inline(always)]
119    fn div_assign(&mut self, other: &Decimal) {
120        let result = self.div(other);
121        *self = result;
122    }
123}
124
125impl Rem<&Decimal> for &Decimal {
126    type Output = Decimal;
127
128    #[inline(always)]
129    fn rem(self, other: &Decimal) -> Decimal {
130        match self.checked_rem(other) {
131            Some(rem) => rem,
132            None => panic!("Division by zero or overflowed"),
133        }
134    }
135}
136
137impl RemAssign<&Decimal> for Decimal {
138    #[inline(always)]
139    fn rem_assign(&mut self, other: &Decimal) {
140        let result = self.rem(other);
141        *self = result;
142    }
143}
144
145impl Sum for Decimal {
146    #[inline(always)]
147    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
148        iter.fold(Decimal::ZERO, Add::add)
149    }
150}
151
152impl<'a> Sum<&'a Decimal> for Decimal {
153    #[inline(always)]
154    fn sum<I: Iterator<Item = &'a Decimal>>(iter: I) -> Self {
155        iter.fold(Decimal::ZERO, Add::add)
156    }
157}
158
159impl Product for Decimal {
160    #[inline(always)]
161    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
162        iter.fold(Decimal::ONE, Mul::mul)
163    }
164}
165
166impl<'a> Product<&'a Decimal> for Decimal {
167    #[inline(always)]
168    fn product<I: Iterator<Item = &'a Decimal>>(iter: I) -> Self {
169        iter.fold(Decimal::ONE, Mul::mul)
170    }
171}
172
173macro_rules! impl_arith_with_num {
174    ($op: ident { $method: ident } $int: ty) => {
175        impl $op<$int> for Decimal {
176            type Output = Decimal;
177
178            #[inline(always)]
179            fn $method(self, other: $int) -> Self::Output {
180                self.$method(&Decimal::from(other))
181            }
182        }
183
184        impl $op<$int> for &'_ Decimal {
185            type Output = Decimal;
186
187            #[inline(always)]
188            fn $method(self, other: $int) -> Self::Output {
189                self.$method(&Decimal::from(other))
190            }
191        }
192
193        impl $op<Decimal> for $int {
194            type Output = Decimal;
195
196            #[inline(always)]
197            fn $method(self, other: Decimal) -> Self::Output {
198                Decimal::from(self).$method(other)
199            }
200        }
201
202        impl $op<&'_ Decimal> for $int {
203            type Output = Decimal;
204
205            #[inline(always)]
206            fn $method(self, other: &'_ Decimal) -> Self::Output {
207                Decimal::from(self).$method(other)
208            }
209        }
210    };
211    ($op: ident { $method: ident } $($int: ty), * $(,)?) => {
212        $(impl_arith_with_num!($op { $method } $int);)*
213    };
214}
215
216macro_rules! impl_arith_try_with_num {
217    ($op: ident { $method: ident } $int: ty) => {
218        impl $op<$int> for Decimal {
219            type Output = Decimal;
220
221            #[inline(always)]
222            fn $method(self, other: $int) -> Self::Output {
223                self.$method(&Decimal::try_from(other).unwrap())
224            }
225        }
226
227        impl $op<$int> for &'_ Decimal {
228            type Output = Decimal;
229
230            #[inline(always)]
231            fn $method(self, other: $int) -> Self::Output {
232                self.$method(&Decimal::try_from(other).unwrap())
233            }
234        }
235
236        impl $op<Decimal> for $int {
237            type Output = Decimal;
238
239            #[inline(always)]
240            fn $method(self, other: Decimal) -> Self::Output {
241                Decimal::try_from(self).unwrap().$method(other)
242            }
243        }
244
245        impl $op<&'_ Decimal> for $int {
246            type Output = Decimal;
247
248            #[inline(always)]
249            fn $method(self, other: &'_ Decimal) -> Self::Output {
250                Decimal::try_from(self).unwrap().$method(other)
251            }
252        }
253    };
254    ($op: ident { $method: ident } $($int: ty), * $(,)?) => {
255        $(impl_arith_try_with_num!($op { $method } $int);)*
256    };
257}
258
259macro_rules! impl_arith {
260    ($op: ident { $method: ident }) => {
261        impl $op for Decimal {
262            type Output = Decimal;
263
264            #[inline(always)]
265            fn $method(self, other: Self) -> Self::Output {
266                (&self).$method(&other)
267            }
268        }
269
270        impl $op<&'_ Decimal> for Decimal {
271            type Output = Decimal;
272
273            #[inline(always)]
274            fn $method(self, other: &Decimal) -> Self::Output {
275                (&self).$method(other)
276            }
277        }
278
279        impl $op<Decimal> for &'_ Decimal {
280            type Output = Decimal;
281
282            #[inline(always)]
283            fn $method(self, other: Decimal) -> Self::Output {
284                self.$method(&other)
285            }
286        }
287
288        impl_arith_with_num!($op { $method } u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
289        impl_arith_try_with_num!($op { $method } f32, f64, i128, u128);
290    };
291}
292
293impl_arith!(Add { add });
294impl_arith!(Sub { sub });
295impl_arith!(Mul { mul });
296impl_arith!(Div { div });
297impl_arith!(Rem { rem });
298
299macro_rules! impl_arith_assign_with_num {
300    ($op: ident { $method: ident } $int: ty) => {
301        impl $op<$int> for Decimal {
302            #[inline(always)]
303            fn $method(&mut self, other: $int) {
304                self.$method(&Decimal::from(other))
305            }
306        }
307
308        impl $op<$int> for &mut Decimal {
309            #[inline(always)]
310            fn $method(&mut self, other: $int) {
311                (*self).$method(&Decimal::from(other))
312            }
313        }
314    };
315    ($op: ident { $method: ident } $($int: ty), * $(,)?) => {
316        $(impl_arith_assign_with_num!($op { $method } $int);)*
317    };
318}
319
320macro_rules! impl_arith_assign_try_with_num {
321    ($op: ident { $method: ident } $int: ty) => {
322        impl $op<$int> for Decimal {
323            #[inline(always)]
324            fn $method(&mut self, other: $int) {
325                self.$method(&Decimal::try_from(other).unwrap())
326            }
327        }
328
329        impl $op<$int> for &mut Decimal {
330            #[inline(always)]
331            fn $method(&mut self, other: $int) {
332                (*self).$method(&Decimal::try_from(other).unwrap())
333            }
334        }
335    };
336    ($op: ident { $method: ident } $($int: ty), * $(,)?) => {
337        $(impl_arith_assign_try_with_num!($op { $method } $int);)*
338    };
339}
340
341macro_rules! impl_arith_assign {
342    ($op: ident { $method: ident }) => {
343        impl $op<Decimal> for &mut Decimal {
344            #[inline(always)]
345            fn $method(&mut self, other: Decimal) {
346                (*self).$method(&other)
347            }
348        }
349
350        impl $op<&Decimal> for &mut Decimal {
351            #[inline(always)]
352            fn $method(&mut self, other: &Decimal) {
353                (*self).$method(other)
354            }
355        }
356
357        impl $op<Decimal> for Decimal {
358            #[inline(always)]
359            fn $method(&mut self, other: Decimal) {
360                self.$method(&other)
361            }
362        }
363
364        impl_arith_assign_with_num!($op { $method } u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
365        impl_arith_assign_try_with_num!($op { $method } f32, f64, i128, u128);
366    };
367}
368
369impl_arith_assign!(AddAssign { add_assign });
370impl_arith_assign!(SubAssign { sub_assign });
371impl_arith_assign!(MulAssign { mul_assign });
372impl_arith_assign!(DivAssign { div_assign });
373impl_arith_assign!(RemAssign { rem_assign });
374
375#[cfg(test)]
376mod tests {
377    use super::*;
378
379    #[test]
380    fn test_neg() {
381        fn assert_neg(val: &str, expected: &str) {
382            let val = val.parse::<Decimal>().unwrap();
383            let expected = expected.parse::<Decimal>().unwrap();
384            {
385                let neg_val = -val;
386                assert_eq!(neg_val, expected);
387            }
388            {
389                let neg_val = -(&val);
390                assert_eq!(neg_val, expected);
391            }
392        }
393
394        assert_neg("00000.00000", "0");
395        assert_neg("1.0", "-1");
396        assert_neg("-1.0", "1");
397        assert_neg("1.234", "-1.234");
398        assert_neg("-1.234", "1.234");
399    }
400
401    #[test]
402    fn test_add() {
403        fn assert_add(val1: &str, val2: &str, expected: &str) {
404            let var1 = val1.parse::<Decimal>().unwrap();
405            let var2 = val2.parse::<Decimal>().unwrap();
406            let expected = expected.parse::<Decimal>().unwrap();
407
408            let result = var1 + var2;
409            assert_eq!(result, expected);
410        }
411
412        assert_add("0.000000001", "100000000", "100000000.000000001");
413        assert_add("123456789.987654321", "-123456789.987654321", "0");
414        assert_add("987654321.123456789", "-987654321.123456789", "0");
415        assert_add("123456789.987654321", "987654321.123456789", "1111111111.11111111");
416        assert_add("123456789.987654321", "00000.00000", "123456789.987654321");
417        assert_add("123456789.987654321", "-987654321.123456789", "-864197531.135802468");
418        assert_add("00000.00000", "987654321.123456789", "987654321.123456789");
419        assert_add("00000.00000", "00000.00000", "0");
420        assert_add("00000.00000", "-987654321.123456789", "-987654321.123456789");
421        assert_add("-123456789.987654321", "987654321.123456789", "864197531.135802468");
422        assert_add("-123456789.987654321", "00000.00000", "-123456789.987654321");
423        assert_add("-123456789.987654321", "-987654321.123456789", "-1111111111.11111111");
424        assert_add("-1e28", "-1e122", "-1e122");
425        assert_add(
426            "0",
427            "0.00038758507034516434217352824488052003540",
428            "0.00038758507034516434217352824488052003540",
429        );
430        assert_add(
431            "1",
432            "0.00038758507034516434217352824488052003540",
433            "1.00038758507034516434217352824488052",
434        );
435        assert_add(
436            "99999999999999999999999999999999999999e80",
437            "99999999999999999999999999999999999999e-80",
438            "99999999999999999999999999999999999999e80",
439        );
440        assert_add("1e-31", "1e-105", "1e-31");
441        assert_add("1e76", "123456789", "1e76");
442        assert_add("0", "1e-127", "1e-127");
443        assert_add("0", "1e-90", "1e-90");
444        assert_add("0", "-1e-127", "-1e-127");
445        assert_add("0", "-1e-90", "-1e-90");
446    }
447
448    #[test]
449    fn test_sub() {
450        fn assert_sub(val1: &str, val2: &str, expected1: &str, expected2: &str) {
451            let var1 = val1.parse::<Decimal>().unwrap();
452            let var2 = val2.parse::<Decimal>().unwrap();
453            let expected1 = expected1.parse::<Decimal>().unwrap();
454            let expected2 = expected2.parse::<Decimal>().unwrap();
455
456            let result1 = var1 - var2;
457            assert_eq!(result1, expected1);
458
459            let result2 = var2 - var1;
460            assert_eq!(result2, expected2);
461        }
462
463        assert_sub("0.000000001", "100000000", "-99999999.999999999", "99999999.999999999");
464        assert_sub(
465            "123456789.987654321",
466            "123456789.987654321",
467            "0.000000000",
468            "0.000000000",
469        );
470        assert_sub(
471            "987654321.123456789",
472            "987654321.123456789",
473            "0.000000000",
474            "0.000000000",
475        );
476        assert_sub(
477            "123456789.987654321",
478            "987654321.123456789",
479            "-864197531.135802468",
480            "864197531.135802468",
481        );
482        assert_sub(
483            "123456789.987654321",
484            "00000.00000",
485            "123456789.987654321",
486            "-123456789.987654321",
487        );
488        assert_sub(
489            "123456789.987654321",
490            "-987654321.123456789",
491            "1111111111.111111110",
492            "-1111111111.111111110",
493        );
494        assert_sub(
495            "00000.00000",
496            "987654321.123456789",
497            "-987654321.123456789",
498            "987654321.123456789",
499        );
500        assert_sub("00000.00000", "00000.00000", "0.00000", "0.00000");
501        assert_sub(
502            "00000.00000",
503            "-987654321.123456789",
504            "987654321.123456789",
505            "-987654321.123456789",
506        );
507        assert_sub(
508            "-123456789.987654321",
509            "987654321.123456789",
510            "-1111111111.111111110",
511            "1111111111.111111110",
512        );
513        assert_sub(
514            "-123456789.987654321",
515            "00000.00000",
516            "-123456789.987654321",
517            "123456789.987654321",
518        );
519        assert_sub(
520            "-123456789.987654321",
521            "-987654321.123456789",
522            "864197531.135802468",
523            "-864197531.135802468",
524        );
525        assert_sub("-1e28", "-1e122", "1e122", "-1e122");
526        assert_sub(
527            "0",
528            "0.00038758507034516434217352824488052003540",
529            "-0.00038758507034516434217352824488052003540",
530            "0.00038758507034516434217352824488052003540",
531        );
532        assert_sub(
533            "1",
534            "0.00038758507034516434217352824488052003540",
535            "0.99961241492965483565782647175511947996",
536            "-0.99961241492965483565782647175511947996",
537        );
538        assert_sub(
539            "99999999999999999999999999999999999999e80",
540            "99999999999999999999999999999999999999e-80",
541            "99999999999999999999999999999999999999e80",
542            "-99999999999999999999999999999999999999e80",
543        );
544    }
545
546    #[test]
547    fn test_mul() {
548        fn assert_mul(val1: &str, val2: &str, expected: &str) {
549            let var1 = val1.parse::<Decimal>().unwrap();
550            let var2 = val2.parse::<Decimal>().unwrap();
551            let expected = expected.parse::<Decimal>().unwrap();
552
553            let result = var1 * var2;
554            assert_eq!(result, expected);
555        }
556
557        assert_mul("0.000000001", "100000000", "0.1");
558        assert_mul(
559            "123456789.987654321",
560            "-123456789.987654321",
561            "-15241578994055784.200731595789971041",
562        );
563        assert_mul(
564            "987654321.123456789",
565            "-987654321.123456789",
566            "-975461058033836303.240512116750190521",
567        );
568        assert_mul(
569            "123456789.987654321",
570            "987654321.123456789",
571            "121932632103337905.662094193112635269",
572        );
573        assert_mul("123456789.987654321", "00000.00000", "0");
574        assert_mul(
575            "123456789.987654321",
576            "-987654321.123456789",
577            "-121932632103337905.662094193112635269",
578        );
579        assert_mul("00000.00000", "987654321.123456789", "0");
580        assert_mul("00000.00000", "00000.00000", "0");
581        assert_mul("00000.00000", "-987654321.123456789", "0");
582        assert_mul(
583            "-123456789.987654321",
584            "987654321.123456789",
585            "-121932632103337905.662094193112635269",
586        );
587        assert_mul("-123456789.987654321", "00000.00000", "0");
588        assert_mul(
589            "-123456789.987654321",
590            "-987654321.123456789",
591            "121932632103337905.662094193112635269",
592        );
593    }
594
595    #[test]
596    fn test_div() {
597        fn assert_div(val1: &str, val2: &str, expected: &str) {
598            let var1 = val1.parse::<Decimal>().unwrap();
599            let var2 = val2.parse::<Decimal>().unwrap();
600            let expected = expected.parse::<Decimal>().unwrap();
601
602            let result = var1 / var2;
603            assert_eq!(result, expected);
604        }
605
606        assert_div("0.000000001", "100000000", "0.00000000000000001");
607        assert_div("100000000", "0.000000001", "100000000000000000");
608        assert_div("123456789.987654321", "123456789.987654321", "1");
609        assert_div("987654321.123456789", "987654321.123456789", "1");
610        assert_div(
611            "123456789.987654321",
612            "987654321.123456789",
613            "0.12499999984531250017595703104984887718",
614        );
615        assert_div(
616            "987654321.123456789",
617            "123456789.987654321",
618            "8.000000009900000000990000000099",
619        );
620        assert_div("00000.00000", "123456789.987654321", "0");
621        assert_div(
622            "123456789.987654321",
623            "-987654321.123456789",
624            "-0.12499999984531250017595703104984887718",
625        );
626        assert_div(
627            "-987654321.123456789",
628            "123456789.987654321",
629            "-8.000000009900000000990000000099",
630        );
631        assert_div("00000.00000", "987654321.123456789", "0");
632        assert_div("00000.00000", "-987654321.123456789", "0");
633        assert_div(
634            "-123456789.987654321",
635            "987654321.123456789",
636            "-0.12499999984531250017595703104984887718",
637        );
638        assert_div(
639            "987654321.123456789",
640            "-123456789.987654321",
641            "-8.000000009900000000990000000099",
642        );
643        assert_div("00000.00000", "-123456789.987654321", "0");
644        assert_div(
645            "-123456789.987654321",
646            "-987654321.123456789",
647            "0.12499999984531250017595703104984887718",
648        );
649        assert_div(
650            "-987654321.123456789",
651            "-123456789.987654321",
652            "8.000000009900000000990000000099",
653        );
654        assert_div("1", "3", "0.33333333333333333333333333333333333333");
655        assert_div("1", "33", "0.030303030303030303030303030303030303030");
656        assert_div(
657            "-3.1415926",
658            "-0.12345678901234567890123456789012345678",
659            "25.446900289022102624101133879320318304",
660        );
661    }
662
663    #[test]
664    fn test_rem() {
665        fn assert_rem(val1: &str, val2: &str, expected: &str) {
666            let var1 = val1.parse::<Decimal>().unwrap();
667            let var2 = val2.parse::<Decimal>().unwrap();
668            let expected = expected.parse::<Decimal>().unwrap();
669
670            let result = var1 % var2;
671            assert_eq!(result, expected);
672        }
673
674        assert_rem("0.000000001", "100000000", "0.000000001");
675        assert_rem("100000000", "0.000000001", "0.000000000");
676        assert_rem("123456789.987654321", "123456789.987654321", "0");
677        assert_rem("987654321.123456789", "987654321.123456789", "0");
678        assert_rem("123456789.987654321", "987654321.123456789", "123456789.987654321");
679        assert_rem("987654321.123456789", "123456789.987654321", "1.222222221");
680        assert_rem("00000.00000", "123456789.987654321", "0");
681        assert_rem("123456789.987654321", "-987654321.123456789", "123456789.987654321");
682        assert_rem("-987654321.123456789", "123456789.987654321", "-1.222222221");
683        assert_rem("00000.00000", "987654321.123456789", "0.000000000");
684        assert_rem("00000.00000", "-987654321.123456789", "0.000000000");
685        assert_rem("-123456789.987654321", "987654321.123456789", "-123456789.987654321");
686        assert_rem("987654321.123456789", "-123456789.987654321", "1.222222221");
687        assert_rem("00000.00000", "-123456789.987654321", "0.000000000");
688        assert_rem("-123456789.987654321", "-987654321.123456789", "-123456789.987654321");
689        assert_rem("-987654321.123456789", "-123456789.987654321", "-1.222222221");
690        assert_rem("100", "5", "0");
691        assert_rem("2e1", "1", "0");
692        assert_rem("2", "1", "0");
693        assert_rem("1", "3", "1");
694        assert_rem("1", "0.5", "0");
695        assert_rem("1.5", "1", "0.5");
696        assert_rem("1", "3e-2", "1e-2");
697        assert_rem("10", "0.003", "0.001");
698        assert_rem("3", "2", "1");
699        assert_rem("-3", "2", "-1");
700        assert_rem("3", "-2", "1");
701        assert_rem("-3", "-2", "-1");
702        assert_rem("-3", "-1", "0");
703        assert_rem("12.34", "1.233", "0.01");
704        assert_rem("5e42", "0.3", "0.2");
705        assert_rem("-5e42", "0.3", "-0.2");
706        assert_rem("5e42", "-0.3", "0.2");
707        assert_rem("-5e42", "-0.3", "-0.2");
708        assert_rem("5e42", "0.03", "0.02");
709        assert_rem("5e42", "3", "2");
710        assert_rem("5e60", "3", "2");
711        assert_rem("5e60", "300", "200");
712        assert_rem("5e76", "3", "2");
713        assert_rem("5e77", "3", "2");
714        assert_rem("5e-42", "3e-84", "2e-84");
715        assert_rem("5e125", "3e-130", "2e-130");
716        assert_rem("4e125", "3e-130", "1e-130");
717        assert_rem("99999999999999999999999999999999999999e80", "7e-130", "1e-130");
718        assert_rem("3", "5e42", "3");
719        assert_rem("1e10", "9223", "8365");
720        assert_rem("1e20", "9223", "7547");
721        assert_rem("1e30", "9223", "8443");
722        assert_rem("1e40", "9223", "5184");
723        assert_rem("1e50", "9223", "6837");
724        assert_rem("1e60", "9223", "8905");
725        assert_rem("1e70", "9223", "5377");
726        assert_rem("1e80", "9223", "7257");
727        assert_rem("1e90", "9223", "8242");
728        assert_rem("1e100", "9223", "2405");
729        assert_rem("1e110", "9223", "2462");
730        assert_rem("1e120", "9223", "8894");
731        assert_rem("1e125", "9223", "7664");
732        assert_rem("1.234172907e125", "9223", "5190");
733        assert_rem("333.456", "7", "4.456");
734        assert_rem("333.456", "7.7", "2.356");
735        assert_rem("333.456", "7.7654", "7.3092");
736        assert_rem("323", "7.7654", "4.6186");
737        assert_rem("0.0003456", "0.00000000234", "7.2e-10");
738        assert_rem("0.3456", "9.234e-130", "2.484e-130");
739        assert_rem("0.0003456", "0.234", "0.0003456");
740    }
741
742    #[test]
743    fn test_sum() {
744        fn assert_sum(vals: &[&str], expected: &str) {
745            let result: Decimal = vals.iter().map(|val| val.parse::<Decimal>().unwrap()).sum();
746            let expected = expected.parse::<Decimal>().unwrap();
747            assert_eq!(result, expected);
748        }
749
750        assert_sum(&["1", "10", "100", "1000", "10000"], "11111");
751        assert_sum(&["-1", "-10", "-100", "-1000", "-10000"], "-11111");
752        assert_sum(&["0", "0", "0", "0", "0"], "0");
753    }
754
755    #[test]
756    fn test_product() {
757        fn assert_product(vals: &[&str], expected: &str) {
758            let result: Decimal = vals.iter().map(|val| val.parse::<Decimal>().unwrap()).product();
759            let expected = expected.parse::<Decimal>().unwrap();
760            assert_eq!(result, expected);
761        }
762
763        assert_product(&["1", "2", "3", "4", "5"], "120");
764        assert_product(&["-1", "-2", "-3", "-4", "-5"], "-120");
765        assert_product(&["0", "0", "0", "0", "0"], "0");
766    }
767}