bigdecimal/
impl_ops_div.rs

1//! Implement division
2
3use super::*;
4
5impl Div<BigDecimal> for BigDecimal {
6    type Output = BigDecimal;
7    #[inline]
8    fn div(self, other: BigDecimal) -> BigDecimal {
9        if other.is_zero() {
10            panic!("Division by zero");
11        }
12        if self.is_zero() || other.is_one() {
13            return self;
14        }
15
16        let scale = self.scale - other.scale;
17
18        if self.int_val == other.int_val {
19            return BigDecimal {
20                int_val: 1.into(),
21                scale: scale,
22            };
23        }
24
25        let max_precision = DEFAULT_PRECISION;
26
27        return impl_division(self.int_val, &other.int_val, scale, max_precision);
28    }
29}
30
31impl<'a> Div<&'a BigDecimal> for BigDecimal {
32    type Output = BigDecimal;
33    #[inline]
34    fn div(self, other: &'a BigDecimal) -> BigDecimal {
35        if other.is_zero() {
36            panic!("Division by zero");
37        }
38        if self.is_zero() || other.is_one() {
39            return self;
40        }
41
42        let scale = self.scale - other.scale;
43
44        if self.int_val == other.int_val {
45            return BigDecimal {
46                int_val: 1.into(),
47                scale: scale,
48            };
49        }
50
51        let max_precision = DEFAULT_PRECISION;
52
53        return impl_division(self.int_val, &other.int_val, scale, max_precision);
54    }
55}
56
57forward_ref_val_binop!(impl Div for BigDecimal, div);
58
59impl Div<&BigDecimal> for &BigDecimal {
60    type Output = BigDecimal;
61
62    #[inline]
63    fn div(self, other: &BigDecimal) -> BigDecimal {
64        if other.is_zero() {
65            panic!("Division by zero");
66        }
67        // TODO: Fix setting scale
68        if self.is_zero() || other.is_one() {
69            return self.clone();
70        }
71
72        let scale = self.scale - other.scale;
73
74        let num_int = &self.int_val;
75        let den_int = &other.int_val;
76
77        if num_int == den_int {
78            return BigDecimal {
79                int_val: 1.into(),
80                scale: scale,
81            };
82        }
83
84        let max_precision = DEFAULT_PRECISION;
85
86        return impl_division(num_int.clone(), den_int, scale, max_precision);
87    }
88}
89
90
91#[cfg(test)]
92mod test {
93    use super::*;
94
95    #[test]
96    fn test_div() {
97        let vals = vec![
98            ("0", "1", "0"),
99            ("0", "10", "0"),
100            ("2", "1", "2"),
101            ("2e1", "1", "2e1"),
102            ("10", "10", "1"),
103            ("100", "10.0", "1e1"),
104            ("20.0", "200", ".1"),
105            ("4", "2", "2.0"),
106            ("15", "3", "5.0"),
107            ("1", "2", "0.5"),
108            ("1", "2e-2", "5e1"),
109            ("1", "0.2", "5"),
110            ("1.0", "0.02", "50"),
111            ("1", "0.020", "5e1"),
112            ("5.0", "4.00", "1.25"),
113            ("5.0", "4.000", "1.25"),
114            ("5", "4.000", "1.25"),
115            ("5", "4", "125e-2"),
116            ("100", "5", "20"),
117            ("-50", "5", "-10"),
118            ("200", "-5", "-40."),
119            ("1", "3", ".3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333"),
120            ("-2", "-3", ".6666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667"),
121            ("-12.34", "1.233", "-10.00811030008110300081103000811030008110300081103000811030008110300081103000811030008110300081103001"),
122            ("125348", "352.2283", "355.8714617763535752237966114591019517738921035021887792661748076460636467881768727839301952739175132"),
123        ];
124
125        for &(x, y, z) in vals.iter() {
126
127            let a = BigDecimal::from_str(x).unwrap();
128            let b = BigDecimal::from_str(y).unwrap();
129            let c = BigDecimal::from_str(z).unwrap();
130
131            assert_eq!(a.clone() / b.clone(), c);
132            assert_eq!(a.clone() / &b, c);
133            assert_eq!(&a / b.clone(), c);
134            assert_eq!(&a / &b, c);
135            // assert_eq!(q.scale, c.scale);
136
137            // let mut q = a;
138            // q /= b;
139            // assert_eq!(q, c);
140        }
141    }
142
143    #[test]
144    #[should_panic(expected = "Division by zero")]
145    fn test_division_by_zero_panics() {
146        let x = BigDecimal::from_str("3.14").unwrap();
147        let _r = x / 0;
148    }
149
150    #[test]
151    #[should_panic(expected = "Division by zero")]
152    fn test_division_by_zero_panics_v2() {
153        let x = BigDecimal::from_str("3.14").unwrap();
154        let _r = x / BigDecimal::zero();
155    }
156
157    #[test]
158    fn test_division_by_large_number() {
159        let n = 1u8;
160        let d: BigDecimal = "79437738588056219546528239237352667078".parse().unwrap();
161
162        let quotient_n_ref_d = n / &d;
163        let quotient_n_d = n / d.clone();
164        assert_eq!(quotient_n_ref_d, quotient_n_d);
165
166        assert_eq!(quotient_n_ref_d, "1.258847517281104957975270408416632052090243053529147458917576143852500316808428812104171430669001064E-38".parse().unwrap());
167    }
168}