Skip to main content

pgnumeric/
ops.rs

1// Copyright 2020 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//! Implementing operators for numeric.
16
17use crate::num::{Numeric, NumericBuf, VALUE_OVERFLOW_MSG};
18use std::cmp::Ordering;
19use std::ops::{
20    Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
21};
22
23// The main implementation
24// &self + &other
25impl Add<&NumericBuf> for &NumericBuf {
26    type Output = NumericBuf;
27
28    #[inline]
29    fn add(self, other: &NumericBuf) -> Self::Output {
30        self.checked_add(other).expect(VALUE_OVERFLOW_MSG)
31    }
32}
33
34// self + &other
35impl Add<&NumericBuf> for NumericBuf {
36    type Output = NumericBuf;
37
38    #[inline]
39    fn add(self, other: &NumericBuf) -> Self::Output {
40        Add::add(&self, other)
41    }
42}
43
44impl Add<&NumericBuf> for &Numeric {
45    type Output = NumericBuf;
46
47    #[inline]
48    fn add(self, other: &NumericBuf) -> Self::Output {
49        Add::add(self, other.as_numeric())
50    }
51}
52
53// self + other
54impl Add<NumericBuf> for NumericBuf {
55    type Output = NumericBuf;
56
57    #[inline]
58    fn add(self, other: NumericBuf) -> Self::Output {
59        Add::add(&self, &other)
60    }
61}
62
63// &self + other
64impl Add<NumericBuf> for &NumericBuf {
65    type Output = NumericBuf;
66
67    #[inline]
68    fn add(self, other: NumericBuf) -> Self::Output {
69        Add::add(self, &other)
70    }
71}
72
73impl Add<NumericBuf> for &Numeric {
74    type Output = NumericBuf;
75
76    #[inline]
77    fn add(self, other: NumericBuf) -> Self::Output {
78        Add::add(self, other.as_numeric())
79    }
80}
81
82impl Add<&Numeric> for &NumericBuf {
83    type Output = NumericBuf;
84
85    #[inline]
86    fn add(self, other: &Numeric) -> Self::Output {
87        Add::add(self.as_numeric(), other)
88    }
89}
90
91impl Add<&Numeric> for NumericBuf {
92    type Output = NumericBuf;
93
94    #[inline]
95    fn add(self, other: &Numeric) -> Self::Output {
96        Add::add(self.as_numeric(), other)
97    }
98}
99
100impl Add<&Numeric> for &Numeric {
101    type Output = NumericBuf;
102
103    #[inline]
104    fn add(self, other: &Numeric) -> Self::Output {
105        self.checked_add(other).expect(VALUE_OVERFLOW_MSG)
106    }
107}
108
109// &mut self += &other
110impl AddAssign<&NumericBuf> for NumericBuf {
111    #[inline]
112    fn add_assign(&mut self, other: &NumericBuf) {
113        let result = Add::add(self as &NumericBuf, other);
114        *self = result;
115    }
116}
117
118// &mut self += other
119impl AddAssign<NumericBuf> for NumericBuf {
120    #[inline]
121    fn add_assign(&mut self, other: NumericBuf) {
122        let result = Add::add(self as &NumericBuf, &other);
123        *self = result;
124    }
125}
126
127impl AddAssign<&Numeric> for NumericBuf {
128    #[inline]
129    fn add_assign(&mut self, other: &Numeric) {
130        let result = Add::add(self.as_numeric(), other);
131        *self = result;
132    }
133}
134
135// The main implementation
136// &self - &other
137impl Sub<&NumericBuf> for &NumericBuf {
138    type Output = NumericBuf;
139
140    #[inline]
141    fn sub(self, other: &NumericBuf) -> Self::Output {
142        self.checked_sub(other).expect(VALUE_OVERFLOW_MSG)
143    }
144}
145
146// self - &other
147impl Sub<&NumericBuf> for NumericBuf {
148    type Output = NumericBuf;
149
150    #[inline]
151    fn sub(self, other: &NumericBuf) -> Self::Output {
152        Sub::sub(&self, other)
153    }
154}
155
156impl Sub<&NumericBuf> for &Numeric {
157    type Output = NumericBuf;
158
159    #[inline]
160    fn sub(self, other: &NumericBuf) -> Self::Output {
161        Sub::sub(self, other.as_numeric())
162    }
163}
164
165// self - other
166impl Sub<NumericBuf> for NumericBuf {
167    type Output = NumericBuf;
168
169    #[inline]
170    fn sub(self, other: NumericBuf) -> Self::Output {
171        Sub::sub(&self, &other)
172    }
173}
174
175// &self - other
176impl Sub<NumericBuf> for &NumericBuf {
177    type Output = NumericBuf;
178
179    #[inline]
180    fn sub(self, other: NumericBuf) -> Self::Output {
181        Sub::sub(self, &other)
182    }
183}
184
185impl Sub<NumericBuf> for &Numeric {
186    type Output = NumericBuf;
187
188    #[inline]
189    fn sub(self, other: NumericBuf) -> Self::Output {
190        Sub::sub(self, other.as_numeric())
191    }
192}
193
194impl Sub<&Numeric> for &Numeric {
195    type Output = NumericBuf;
196
197    #[inline]
198    fn sub(self, other: &Numeric) -> Self::Output {
199        self.checked_sub(other).expect(VALUE_OVERFLOW_MSG)
200    }
201}
202
203impl Sub<&Numeric> for NumericBuf {
204    type Output = NumericBuf;
205
206    #[inline]
207    fn sub(self, other: &Numeric) -> Self::Output {
208        Sub::sub(self.as_numeric(), other)
209    }
210}
211
212impl Sub<&Numeric> for &NumericBuf {
213    type Output = NumericBuf;
214
215    #[inline]
216    fn sub(self, other: &Numeric) -> Self::Output {
217        Sub::sub(self.as_numeric(), other)
218    }
219}
220
221// &mut self -= &other
222impl SubAssign<&NumericBuf> for NumericBuf {
223    #[inline]
224    fn sub_assign(&mut self, other: &NumericBuf) {
225        let result = Sub::sub(self as &NumericBuf, other);
226        *self = result;
227    }
228}
229
230// &mut self -= other
231impl SubAssign<NumericBuf> for NumericBuf {
232    #[inline]
233    fn sub_assign(&mut self, other: NumericBuf) {
234        let result = Sub::sub(self as &NumericBuf, &other);
235        *self = result;
236    }
237}
238
239impl SubAssign<&Numeric> for NumericBuf {
240    #[inline]
241    fn sub_assign(&mut self, other: &Numeric) {
242        let result = Sub::sub(self.as_numeric(), other);
243        *self = result;
244    }
245}
246
247// The main implementation
248// &self * &other
249impl Mul<&NumericBuf> for &NumericBuf {
250    type Output = NumericBuf;
251
252    #[inline]
253    fn mul(self, other: &NumericBuf) -> Self::Output {
254        self.checked_mul(other).expect(VALUE_OVERFLOW_MSG)
255    }
256}
257
258// self * &other
259impl Mul<&NumericBuf> for NumericBuf {
260    type Output = NumericBuf;
261
262    #[inline]
263    fn mul(self, other: &NumericBuf) -> Self::Output {
264        Mul::mul(&self, other)
265    }
266}
267
268impl Mul<&NumericBuf> for &Numeric {
269    type Output = NumericBuf;
270
271    #[inline]
272    fn mul(self, other: &NumericBuf) -> Self::Output {
273        Mul::mul(self, other.as_numeric())
274    }
275}
276
277// self * other
278impl Mul<NumericBuf> for NumericBuf {
279    type Output = NumericBuf;
280
281    #[inline]
282    fn mul(self, other: NumericBuf) -> Self::Output {
283        Mul::mul(&self, &other)
284    }
285}
286
287// &self * other
288impl Mul<NumericBuf> for &NumericBuf {
289    type Output = NumericBuf;
290
291    #[inline]
292    fn mul(self, other: NumericBuf) -> Self::Output {
293        Mul::mul(self, &other)
294    }
295}
296
297impl Mul<NumericBuf> for &Numeric {
298    type Output = NumericBuf;
299
300    #[inline]
301    fn mul(self, other: NumericBuf) -> Self::Output {
302        Mul::mul(self, other.as_numeric())
303    }
304}
305
306impl Mul<&Numeric> for &Numeric {
307    type Output = NumericBuf;
308
309    #[inline]
310    fn mul(self, other: &Numeric) -> Self::Output {
311        self.checked_mul(other).expect(VALUE_OVERFLOW_MSG)
312    }
313}
314
315impl Mul<&Numeric> for NumericBuf {
316    type Output = NumericBuf;
317
318    #[inline]
319    fn mul(self, other: &Numeric) -> Self::Output {
320        Mul::mul(self.as_numeric(), other)
321    }
322}
323
324impl Mul<&Numeric> for &NumericBuf {
325    type Output = NumericBuf;
326
327    #[inline]
328    fn mul(self, other: &Numeric) -> Self::Output {
329        Mul::mul(self.as_numeric(), other)
330    }
331}
332
333// &mut self *= &other
334impl MulAssign<&NumericBuf> for NumericBuf {
335    #[inline]
336    fn mul_assign(&mut self, other: &NumericBuf) {
337        let result = Mul::mul(self as &NumericBuf, other);
338        *self = result;
339    }
340}
341
342// &mut self *= other
343impl MulAssign<NumericBuf> for NumericBuf {
344    #[inline]
345    fn mul_assign(&mut self, other: NumericBuf) {
346        let result = Mul::mul(self as &NumericBuf, &other);
347        *self = result;
348    }
349}
350
351impl MulAssign<&Numeric> for NumericBuf {
352    #[inline]
353    fn mul_assign(&mut self, other: &Numeric) {
354        let result = Mul::mul(self.as_numeric(), other);
355        *self = result;
356    }
357}
358
359// The main implementation
360// &self / &other
361impl Div<&NumericBuf> for &NumericBuf {
362    type Output = NumericBuf;
363
364    #[inline]
365    fn div(self, other: &NumericBuf) -> Self::Output {
366        let (result, overflow) = self.overflowing_div(other);
367        if overflow {
368            panic!(VALUE_OVERFLOW_MSG)
369        }
370
371        result
372    }
373}
374
375// self / &other
376impl Div<&NumericBuf> for NumericBuf {
377    type Output = NumericBuf;
378
379    #[inline]
380    fn div(self, other: &NumericBuf) -> Self::Output {
381        Div::div(&self, other)
382    }
383}
384
385impl Div<&NumericBuf> for &Numeric {
386    type Output = NumericBuf;
387
388    #[inline]
389    fn div(self, other: &NumericBuf) -> Self::Output {
390        Div::div(self, other.as_numeric())
391    }
392}
393
394// &self / other
395impl Div<NumericBuf> for &NumericBuf {
396    type Output = NumericBuf;
397
398    #[inline]
399    fn div(self, other: NumericBuf) -> Self::Output {
400        Div::div(self, &other)
401    }
402}
403
404// self / other
405impl Div<NumericBuf> for NumericBuf {
406    type Output = NumericBuf;
407
408    #[inline]
409    fn div(self, other: NumericBuf) -> Self::Output {
410        Div::div(&self, &other)
411    }
412}
413
414impl Div<NumericBuf> for &Numeric {
415    type Output = NumericBuf;
416
417    #[inline]
418    fn div(self, other: NumericBuf) -> Self::Output {
419        Div::div(self, other.as_numeric())
420    }
421}
422
423impl Div<&Numeric> for &NumericBuf {
424    type Output = NumericBuf;
425
426    #[inline]
427    fn div(self, other: &Numeric) -> Self::Output {
428        Div::div(self.as_numeric(), other)
429    }
430}
431
432impl Div<&Numeric> for NumericBuf {
433    type Output = NumericBuf;
434
435    #[inline]
436    fn div(self, other: &Numeric) -> Self::Output {
437        Div::div(self.as_numeric(), other)
438    }
439}
440
441impl Div<&Numeric> for &Numeric {
442    type Output = NumericBuf;
443
444    #[inline]
445    fn div(self, other: &Numeric) -> Self::Output {
446        let (result, overflow) = self.overflowing_div(other);
447        if overflow {
448            panic!(VALUE_OVERFLOW_MSG)
449        }
450
451        result
452    }
453}
454
455// &mut self /= &other
456impl DivAssign<&NumericBuf> for NumericBuf {
457    #[inline]
458    fn div_assign(&mut self, other: &NumericBuf) {
459        let result = Div::div(self as &NumericBuf, other);
460        *self = result;
461    }
462}
463
464// &mut self /= other
465impl DivAssign<NumericBuf> for NumericBuf {
466    #[inline]
467    fn div_assign(&mut self, other: NumericBuf) {
468        let result = Div::div(self as &NumericBuf, &other);
469        *self = result;
470    }
471}
472
473impl DivAssign<&Numeric> for NumericBuf {
474    #[inline]
475    fn div_assign(&mut self, other: &Numeric) {
476        let result = Div::div(self.as_numeric(), other);
477        *self = result;
478    }
479}
480
481// The main implementation
482// &self % &other
483impl Rem<&NumericBuf> for &NumericBuf {
484    type Output = NumericBuf;
485
486    #[inline]
487    fn rem(self, other: &NumericBuf) -> Self::Output {
488        let (result, overflow) = self.overflowing_rem(other);
489        if overflow {
490            panic!(VALUE_OVERFLOW_MSG)
491        }
492
493        result
494    }
495}
496
497// self % &other
498impl Rem<&NumericBuf> for NumericBuf {
499    type Output = NumericBuf;
500
501    #[inline]
502    fn rem(self, other: &NumericBuf) -> Self::Output {
503        Rem::rem(&self, other)
504    }
505}
506
507impl Rem<&NumericBuf> for &Numeric {
508    type Output = NumericBuf;
509
510    #[inline]
511    fn rem(self, other: &NumericBuf) -> Self::Output {
512        Rem::rem(self, other.as_numeric())
513    }
514}
515
516// &self % other
517impl Rem<NumericBuf> for &NumericBuf {
518    type Output = NumericBuf;
519
520    #[inline]
521    fn rem(self, other: NumericBuf) -> Self::Output {
522        Rem::rem(self, &other)
523    }
524}
525
526// self % other
527impl Rem<NumericBuf> for NumericBuf {
528    type Output = NumericBuf;
529
530    #[inline]
531    fn rem(self, other: NumericBuf) -> Self::Output {
532        Rem::rem(&self, &other)
533    }
534}
535
536impl Rem<NumericBuf> for &Numeric {
537    type Output = NumericBuf;
538
539    #[inline]
540    fn rem(self, other: NumericBuf) -> Self::Output {
541        Rem::rem(self, other.as_numeric())
542    }
543}
544
545impl Rem<&Numeric> for &NumericBuf {
546    type Output = NumericBuf;
547
548    #[inline]
549    fn rem(self, other: &Numeric) -> Self::Output {
550        Rem::rem(self.as_numeric(), other)
551    }
552}
553
554impl Rem<&Numeric> for NumericBuf {
555    type Output = NumericBuf;
556
557    #[inline]
558    fn rem(self, other: &Numeric) -> Self::Output {
559        Rem::rem(self.as_numeric(), other)
560    }
561}
562
563impl Rem<&Numeric> for &Numeric {
564    type Output = NumericBuf;
565
566    #[inline]
567    fn rem(self, other: &Numeric) -> Self::Output {
568        let (result, overflow) = self.overflowing_rem(other);
569        if overflow {
570            panic!(VALUE_OVERFLOW_MSG)
571        }
572
573        result
574    }
575}
576
577// &mut self %= &other
578impl RemAssign<&NumericBuf> for NumericBuf {
579    #[inline]
580    fn rem_assign(&mut self, other: &NumericBuf) {
581        let result = Rem::rem(self as &NumericBuf, other);
582        *self = result;
583    }
584}
585
586// &mut self %= other
587impl RemAssign<NumericBuf> for NumericBuf {
588    #[inline]
589    fn rem_assign(&mut self, other: NumericBuf) {
590        let result = Rem::rem(self as &NumericBuf, &other);
591        *self = result;
592    }
593}
594
595impl RemAssign<&Numeric> for NumericBuf {
596    #[inline]
597    fn rem_assign(&mut self, other: &Numeric) {
598        let result = Rem::rem(self.as_numeric(), other);
599        *self = result;
600    }
601}
602
603// -self
604impl Neg for NumericBuf {
605    type Output = NumericBuf;
606
607    #[inline]
608    fn neg(mut self) -> Self::Output {
609        self.negate_mut();
610        self
611    }
612}
613
614// -&self
615impl Neg for &NumericBuf {
616    type Output = NumericBuf;
617
618    #[inline]
619    fn neg(self) -> Self::Output {
620        self.negate()
621    }
622}
623
624impl Neg for &Numeric {
625    type Output = NumericBuf;
626
627    #[inline]
628    fn neg(self) -> Self::Output {
629        self.negate()
630    }
631}
632
633impl PartialEq<NumericBuf> for NumericBuf {
634    #[inline]
635    fn eq(&self, other: &NumericBuf) -> bool {
636        Ord::cmp(self, other) == Ordering::Equal
637    }
638}
639
640impl Eq for NumericBuf {}
641
642impl PartialOrd<NumericBuf> for NumericBuf {
643    #[inline]
644    fn partial_cmp(&self, other: &NumericBuf) -> Option<Ordering> {
645        Some(Ord::cmp(self, other))
646    }
647}
648
649impl Ord for NumericBuf {
650    #[inline]
651    fn cmp(&self, other: &Self) -> Ordering {
652        Numeric::cmp(self, other)
653    }
654}
655
656impl PartialEq<Numeric> for Numeric {
657    #[inline]
658    fn eq(&self, other: &Numeric) -> bool {
659        Ord::cmp(self, other) == Ordering::Equal
660    }
661}
662
663impl Eq for Numeric {}
664
665impl PartialOrd<Numeric> for Numeric {
666    #[inline]
667    fn partial_cmp(&self, other: &Numeric) -> Option<Ordering> {
668        Some(Ord::cmp(self, other))
669    }
670}
671
672impl Ord for Numeric {
673    #[inline]
674    fn cmp(&self, other: &Self) -> Ordering {
675        Numeric::cmp(self, other)
676    }
677}
678
679impl PartialEq<Numeric> for NumericBuf {
680    #[inline]
681    fn eq(&self, other: &Numeric) -> bool {
682        self.as_numeric() == other
683    }
684}
685
686impl PartialEq<&Numeric> for NumericBuf {
687    #[inline]
688    fn eq(&self, other: &&Numeric) -> bool {
689        self.as_numeric() == *other
690    }
691}
692
693impl PartialEq<NumericBuf> for Numeric {
694    #[inline]
695    fn eq(&self, other: &NumericBuf) -> bool {
696        self == other.as_numeric()
697    }
698}
699
700impl PartialEq<NumericBuf> for &Numeric {
701    #[inline]
702    fn eq(&self, other: &NumericBuf) -> bool {
703        *self == other.as_numeric()
704    }
705}
706
707impl PartialEq<Numeric> for &Numeric {
708    #[inline]
709    fn eq(&self, other: &Numeric) -> bool {
710        (*self).eq(other)
711    }
712}
713
714impl PartialEq<&Numeric> for Numeric {
715    #[inline]
716    fn eq(&self, other: &&Numeric) -> bool {
717        self.eq(*other)
718    }
719}
720
721impl PartialEq<NumericBuf> for &NumericBuf {
722    #[inline]
723    fn eq(&self, other: &NumericBuf) -> bool {
724        (*self).eq(other)
725    }
726}
727
728impl PartialEq<&NumericBuf> for NumericBuf {
729    #[inline]
730    fn eq(&self, other: &&NumericBuf) -> bool {
731        self.eq(*other)
732    }
733}
734
735impl PartialOrd<Numeric> for NumericBuf {
736    #[inline]
737    fn partial_cmp(&self, other: &Numeric) -> Option<Ordering> {
738        self.as_numeric().partial_cmp(other)
739    }
740}
741
742impl PartialOrd<&Numeric> for NumericBuf {
743    #[inline]
744    fn partial_cmp(&self, other: &&Numeric) -> Option<Ordering> {
745        self.as_numeric().partial_cmp(*other)
746    }
747}
748
749impl PartialOrd<NumericBuf> for Numeric {
750    #[inline]
751    fn partial_cmp(&self, other: &NumericBuf) -> Option<Ordering> {
752        self.partial_cmp(other.as_numeric())
753    }
754}
755
756impl PartialOrd<NumericBuf> for &Numeric {
757    #[inline]
758    fn partial_cmp(&self, other: &NumericBuf) -> Option<Ordering> {
759        (*self).partial_cmp(other.as_numeric())
760    }
761}
762
763impl PartialOrd<Numeric> for &Numeric {
764    #[inline]
765    fn partial_cmp(&self, other: &Numeric) -> Option<Ordering> {
766        (*self).partial_cmp(other)
767    }
768}
769
770impl PartialOrd<&Numeric> for Numeric {
771    #[inline]
772    fn partial_cmp(&self, other: &&Numeric) -> Option<Ordering> {
773        self.partial_cmp(*other)
774    }
775}
776
777impl PartialOrd<NumericBuf> for &NumericBuf {
778    #[inline]
779    fn partial_cmp(&self, other: &NumericBuf) -> Option<Ordering> {
780        (*self).partial_cmp(other)
781    }
782}
783
784impl PartialOrd<&NumericBuf> for NumericBuf {
785    #[inline]
786    fn partial_cmp(&self, other: &&NumericBuf) -> Option<Ordering> {
787        self.partial_cmp(*other)
788    }
789}
790
791#[cfg(test)]
792mod tests {
793    use super::*;
794    use std::ops::Deref;
795
796    // use this function to test `as_bytes` in ops.
797    fn transform(val: &NumericBuf) -> &Numeric {
798        val.deref()
799    }
800
801    fn assert_add(val1: &str, val2: &str, expected: &str) {
802        let var1 = val1.parse::<NumericBuf>().unwrap();
803        let var2 = val2.parse::<NumericBuf>().unwrap();
804
805        let result1 = &var1 + &var2;
806        assert_eq!(transform(&result1).to_string(), expected);
807
808        let result2 = &var2 + &var1;
809        assert_eq!(transform(&result2).to_string(), expected);
810
811        let mut result3 = var1.clone();
812        result3 += &var2;
813        assert_eq!(transform(&result3).to_string(), expected);
814
815        let mut result4 = var2.clone();
816        result4 += &var1;
817        assert_eq!(transform(&result4).to_string(), expected);
818    }
819
820    #[test]
821    fn add() {
822        assert_add("NaN", "10000.00001", "NaN");
823        assert_add("NaN", "00000.00000", "NaN");
824        assert_add("NaN", "-10000.00001", "NaN");
825        assert_add("0.000000001", "100000000", "100000000.000000001");
826        assert_add("123456789.987654321", "-123456789.987654321", "0.000000000");
827        assert_add("987654321.123456789", "-987654321.123456789", "0.000000000");
828        assert_add(
829            "123456789.987654321",
830            "987654321.123456789",
831            "1111111111.111111110",
832        );
833        assert_add("123456789.987654321", "00000.00000", "123456789.987654321");
834        assert_add(
835            "123456789.987654321",
836            "-987654321.123456789",
837            "-864197531.135802468",
838        );
839        assert_add("00000.00000", "987654321.123456789", "987654321.123456789");
840        assert_add("00000.00000", "00000.00000", "0.00000");
841        assert_add(
842            "00000.00000",
843            "-987654321.123456789",
844            "-987654321.123456789",
845        );
846        assert_add(
847            "-123456789.987654321",
848            "987654321.123456789",
849            "864197531.135802468",
850        );
851        assert_add(
852            "-123456789.987654321",
853            "00000.00000",
854            "-123456789.987654321",
855        );
856        assert_add(
857            "-123456789.987654321",
858            "-987654321.123456789",
859            "-1111111111.111111110",
860        );
861    }
862
863    fn assert_sub(val1: &str, val2: &str, expected1: &str, expected2: &str) {
864        let var1 = val1.parse::<NumericBuf>().unwrap();
865        let var2 = val2.parse::<NumericBuf>().unwrap();
866
867        let result1 = &var1 - &var2;
868        assert_eq!(transform(&result1).to_string(), expected1);
869
870        let result2 = &var2 - &var1;
871        assert_eq!(transform(&result2).to_string(), expected2);
872
873        let mut result3 = var1.clone();
874        result3 -= &var2;
875        assert_eq!(transform(&result3).to_string(), expected1);
876
877        let mut result4 = var2.clone();
878        result4 -= &var1;
879        assert_eq!(transform(&result4).to_string(), expected2);
880    }
881
882    #[test]
883    fn sub() {
884        assert_sub("NaN", "10000.00001", "NaN", "NaN");
885        assert_sub("NaN", "00000.00000", "NaN", "NaN");
886        assert_sub("NaN", "-10000.00001", "NaN", "NaN");
887        assert_sub(
888            "0.000000001",
889            "100000000",
890            "-99999999.999999999",
891            "99999999.999999999",
892        );
893        assert_sub(
894            "123456789.987654321",
895            "123456789.987654321",
896            "0.000000000",
897            "0.000000000",
898        );
899        assert_sub(
900            "987654321.123456789",
901            "987654321.123456789",
902            "0.000000000",
903            "0.000000000",
904        );
905        assert_sub(
906            "123456789.987654321",
907            "987654321.123456789",
908            "-864197531.135802468",
909            "864197531.135802468",
910        );
911        assert_sub(
912            "123456789.987654321",
913            "00000.00000",
914            "123456789.987654321",
915            "-123456789.987654321",
916        );
917        assert_sub(
918            "123456789.987654321",
919            "-987654321.123456789",
920            "1111111111.111111110",
921            "-1111111111.111111110",
922        );
923        assert_sub(
924            "00000.00000",
925            "987654321.123456789",
926            "-987654321.123456789",
927            "987654321.123456789",
928        );
929        assert_sub("00000.00000", "00000.00000", "0.00000", "0.00000");
930        assert_sub(
931            "00000.00000",
932            "-987654321.123456789",
933            "987654321.123456789",
934            "-987654321.123456789",
935        );
936        assert_sub(
937            "-123456789.987654321",
938            "987654321.123456789",
939            "-1111111111.111111110",
940            "1111111111.111111110",
941        );
942        assert_sub(
943            "-123456789.987654321",
944            "00000.00000",
945            "-123456789.987654321",
946            "123456789.987654321",
947        );
948        assert_sub(
949            "-123456789.987654321",
950            "-987654321.123456789",
951            "864197531.135802468",
952            "-864197531.135802468",
953        );
954    }
955
956    fn assert_mul(val1: &str, val2: &str, expected: &str) {
957        let var1 = val1.parse::<NumericBuf>().unwrap();
958        let var2 = val2.parse::<NumericBuf>().unwrap();
959
960        let result1 = &var1 * &var2;
961        assert_eq!(transform(&result1).to_string(), expected);
962
963        let result2 = &var2 * &var1;
964        assert_eq!(transform(&result2).to_string(), expected);
965
966        let mut result3 = var1.clone();
967        result3 *= &var2;
968        assert_eq!(transform(&result3).to_string(), expected);
969
970        let mut result4 = var2.clone();
971        result4 *= &var1;
972        assert_eq!(transform(&result4).to_string(), expected);
973    }
974
975    #[test]
976    fn mul() {
977        assert_mul("NaN", "10000.00001", "NaN");
978        assert_mul("NaN", "00000.00000", "NaN");
979        assert_mul("NaN", "-10000.00001", "NaN");
980        assert_mul("0.000000001", "100000000", "0.100000000");
981        assert_mul(
982            "123456789.987654321",
983            "-123456789.987654321",
984            "-15241578994055784.200731595789971041",
985        );
986        assert_mul(
987            "987654321.123456789",
988            "-987654321.123456789",
989            "-975461058033836303.240512116750190521",
990        );
991        assert_mul(
992            "123456789.987654321",
993            "987654321.123456789",
994            "121932632103337905.662094193112635269",
995        );
996        assert_mul("123456789.987654321", "00000.00000", "0.00000000000000");
997        assert_mul(
998            "123456789.987654321",
999            "-987654321.123456789",
1000            "-121932632103337905.662094193112635269",
1001        );
1002        assert_mul("00000.00000", "987654321.123456789", "0.00000000000000");
1003        assert_mul("00000.00000", "00000.00000", "0.0000000000");
1004        assert_mul("00000.00000", "-987654321.123456789", "0.00000000000000");
1005        assert_mul(
1006            "-123456789.987654321",
1007            "987654321.123456789",
1008            "-121932632103337905.662094193112635269",
1009        );
1010        assert_mul("-123456789.987654321", "00000.00000", "0.00000000000000");
1011        assert_mul(
1012            "-123456789.987654321",
1013            "-987654321.123456789",
1014            "121932632103337905.662094193112635269",
1015        );
1016    }
1017
1018    fn assert_div(val1: &str, val2: &str, expected: &str) {
1019        let var1 = val1.parse::<NumericBuf>().unwrap();
1020        let var2 = val2.parse::<NumericBuf>().unwrap();
1021
1022        let result1 = &var1 / &var2;
1023        assert_eq!(transform(&result1).to_string(), expected);
1024
1025        let mut result2 = var1.clone();
1026        result2 /= &var2;
1027        assert_eq!(transform(&result2).to_string(), expected);
1028    }
1029
1030    #[test]
1031    fn div() {
1032        assert_div("NaN", "10000.00001", "NaN");
1033        assert_div("NaN", "00000.00000", "NaN");
1034        assert_div("NaN", "-10000.00001", "NaN");
1035        assert_div("10000.00001", "NaN", "NaN");
1036        assert_div("00000.00000", "NaN", "NaN");
1037        assert_div("-10000.00001", "NaN", "NaN");
1038        assert_div("NaN", "NaN", "NaN");
1039        assert_div(
1040            "0.000000001",
1041            "100000000",
1042            "0.000000000000000010000000000000000000",
1043        );
1044        assert_div("100000000", "0.000000001", "100000000000000000.000000000");
1045        assert_div(
1046            "123456789.987654321",
1047            "123456789.987654321",
1048            "1.00000000000000000000",
1049        );
1050        assert_div(
1051            "987654321.123456789",
1052            "987654321.123456789",
1053            "1.00000000000000000000",
1054        );
1055        assert_div(
1056            "123456789.987654321",
1057            "987654321.123456789",
1058            "0.12499999984531250018",
1059        );
1060        assert_div(
1061            "987654321.123456789",
1062            "123456789.987654321",
1063            "8.0000000099000000",
1064        );
1065        assert_div(
1066            "00000.00000",
1067            "123456789.987654321",
1068            "0.0000000000000000000000000000",
1069        );
1070        assert_div(
1071            "123456789.987654321",
1072            "-987654321.123456789",
1073            "-0.12499999984531250018",
1074        );
1075        assert_div(
1076            "-987654321.123456789",
1077            "123456789.987654321",
1078            "-8.0000000099000000",
1079        );
1080        assert_div(
1081            "00000.00000",
1082            "987654321.123456789",
1083            "0.0000000000000000000000000000",
1084        );
1085        assert_div(
1086            "00000.00000",
1087            "-987654321.123456789",
1088            "0.0000000000000000000000000000",
1089        );
1090        assert_div(
1091            "-123456789.987654321",
1092            "987654321.123456789",
1093            "-0.12499999984531250018",
1094        );
1095        assert_div(
1096            "987654321.123456789",
1097            "-123456789.987654321",
1098            "-8.0000000099000000",
1099        );
1100        assert_div(
1101            "00000.00000",
1102            "-123456789.987654321",
1103            "0.0000000000000000000000000000",
1104        );
1105        assert_div(
1106            "-123456789.987654321",
1107            "-987654321.123456789",
1108            "0.12499999984531250018",
1109        );
1110        assert_div(
1111            "-987654321.123456789",
1112            "-123456789.987654321",
1113            "8.0000000099000000",
1114        );
1115    }
1116
1117    #[test]
1118    #[should_panic(expected = "attempt to divide by zero")]
1119    fn div_by_zero() {
1120        assert_div("1", "0", "");
1121    }
1122
1123    fn assert_rem(val1: &str, val2: &str, expected: &str) {
1124        let var1 = val1.parse::<NumericBuf>().unwrap();
1125        let var2 = val2.parse::<NumericBuf>().unwrap();
1126
1127        let result1 = &var1 % &var2;
1128        assert_eq!(transform(&result1).to_string(), expected);
1129
1130        let mut result2 = var1.clone();
1131        result2 %= &var2;
1132        assert_eq!(transform(&result2).to_string(), expected);
1133    }
1134
1135    #[test]
1136    fn rem() {
1137        assert_rem("NaN", "10000.00001", "NaN");
1138        assert_rem("NaN", "00000.00000", "NaN");
1139        assert_rem("NaN", "-10000.00001", "NaN");
1140        assert_rem("10000.00001", "NaN", "NaN");
1141        assert_rem("00000.00000", "NaN", "NaN");
1142        assert_rem("-10000.00001", "NaN", "NaN");
1143        assert_rem("NaN", "NaN", "NaN");
1144        assert_rem("0.000000001", "100000000", "0.000000001");
1145        assert_rem("100000000", "0.000000001", "0.000000000");
1146        assert_rem("123456789.987654321", "123456789.987654321", "0.000000000");
1147        assert_rem("987654321.123456789", "987654321.123456789", "0.000000000");
1148        assert_rem(
1149            "123456789.987654321",
1150            "987654321.123456789",
1151            "123456789.987654321",
1152        );
1153        assert_rem("987654321.123456789", "123456789.987654321", "1.222222221");
1154        assert_rem("00000.00000", "123456789.987654321", "0.000000000");
1155        assert_rem(
1156            "123456789.987654321",
1157            "-987654321.123456789",
1158            "123456789.987654321",
1159        );
1160        assert_rem(
1161            "-987654321.123456789",
1162            "123456789.987654321",
1163            "-1.222222221",
1164        );
1165        assert_rem("00000.00000", "987654321.123456789", "0.000000000");
1166        assert_rem("00000.00000", "-987654321.123456789", "0.000000000");
1167        assert_rem(
1168            "-123456789.987654321",
1169            "987654321.123456789",
1170            "-123456789.987654321",
1171        );
1172        assert_rem("987654321.123456789", "-123456789.987654321", "1.222222221");
1173        assert_rem("00000.00000", "-123456789.987654321", "0.000000000");
1174        assert_rem(
1175            "-123456789.987654321",
1176            "-987654321.123456789",
1177            "-123456789.987654321",
1178        );
1179        assert_rem(
1180            "-987654321.123456789",
1181            "-123456789.987654321",
1182            "-1.222222221",
1183        );
1184    }
1185
1186    #[test]
1187    #[should_panic(expected = "attempt to divide by zero")]
1188    fn rem_div_by_zero() {
1189        assert_rem("1", "0", "");
1190    }
1191
1192    macro_rules! assert_cmp {
1193        ($left: expr, $cmp: tt, $right: expr) => {{
1194            let left = $left.parse::<NumericBuf>().unwrap();
1195            let right = $right.parse::<NumericBuf>().unwrap();
1196            assert!(left $cmp right, "left = {}, right = {}", left, right);
1197        }};
1198    }
1199
1200    fn assert_ord(val1: &str, val2: &str, expected: &str) {
1201        let var1 = val1.parse::<NumericBuf>().unwrap();
1202        let var2 = val2.parse::<NumericBuf>().unwrap();
1203
1204        let result = std::cmp::max(var1, var2);
1205        assert_eq!(transform(&result).to_string(), expected);
1206    }
1207
1208    #[test]
1209    fn cmp() {
1210        assert_cmp!("NaN", ==, "NaN");
1211        assert_cmp!("NaN", >, "1e100000");
1212        assert_cmp!("NaN", >, "00000.00000");
1213        assert_cmp!("NaN", >, "-1e100000");
1214        assert_cmp!("1e100000", <, "NaN");
1215        assert_cmp!("00000.00000", <, "NaN");
1216        assert_cmp!("-1e100000", <, "NaN");
1217        assert_cmp!("00000.00000", ==, "0");
1218        assert_cmp!("0.000000001", <,"100000000");
1219        assert_cmp!("100000000", >, "0.000000001");
1220        assert_cmp!("123456789.987654321", ==, "123456789.987654321");
1221        assert_cmp!("987654321.123456789", ==, "987654321.123456789");
1222        assert_cmp!("123456789.987654321", <, "987654321.123456789");
1223        assert_cmp!("987654321.123456789", >, "123456789.987654321");
1224        assert_cmp!("00000.00000", <, "123456789.987654321");
1225        assert_cmp!("123456789.987654321", >, "-987654321.123456789");
1226        assert_cmp!("-987654321.123456789", <, "123456789.987654321");
1227        assert_cmp!("00000.00000", <, "987654321.123456789");
1228        assert_cmp!("00000.00000", >, "-987654321.123456789");
1229        assert_cmp!("-123456789.987654321", <, "987654321.123456789");
1230        assert_cmp!("987654321.123456789", >, "-123456789.987654321");
1231        assert_cmp!("00000.00000", >, "-123456789.987654321");
1232        assert_cmp!("-123456789.987654321", >, "-987654321.123456789");
1233        assert_cmp!("-987654321.123456789", <, "-123456789.987654321");
1234        assert_cmp!("1.0e-10000", >=, "1.0e-10001");
1235        assert_cmp!("1.0e-10001", <=, "1.0e-10000");
1236        assert_cmp!("1.0e-10000", !=, "1.0e-10001");
1237        assert_cmp!("1.0e100000", <=, "1.0e100001");
1238        assert_cmp!("1.0e100001", >=, "1.0e100000");
1239        assert_cmp!("1.0e100000", !=, "1.0e100001");
1240
1241        assert_ord("NaN", "1e100000", "NaN");
1242        assert_ord(
1243            "123456789.987654321",
1244            "987654321.123456789",
1245            "987654321.123456789",
1246        );
1247    }
1248
1249    fn assert_neg(val: &str, expected: &str) {
1250        let var = val.parse::<NumericBuf>().unwrap();
1251        let expected_var = expected.parse::<NumericBuf>().unwrap();
1252        assert_eq!(transform(&-&var), expected_var.as_numeric());
1253    }
1254
1255    #[test]
1256    fn neg() {
1257        assert_neg("NaN", "NaN");
1258        assert_neg("00000.00000", "0.00000");
1259        assert_neg("1.0", "-1.0");
1260        assert_neg("-1.0", "1.0");
1261        assert_neg("1.23e10", "-1.23e10");
1262        assert_neg("-1.23e10", "1.23e10");
1263    }
1264}