polars_core/chunked_array/arithmetic/
decimal.rs

1use super::*;
2
3impl Add for &DecimalChunked {
4    type Output = PolarsResult<DecimalChunked>;
5
6    fn add(self, rhs: Self) -> Self::Output {
7        let scale = _get_decimal_scale_add_sub(self.scale(), rhs.scale());
8        let lhs = self.to_scale(scale)?;
9        let rhs = rhs.to_scale(scale)?;
10        Ok((&lhs.0 + &rhs.0).into_decimal_unchecked(None, scale))
11    }
12}
13
14impl Sub for &DecimalChunked {
15    type Output = PolarsResult<DecimalChunked>;
16
17    fn sub(self, rhs: Self) -> Self::Output {
18        let scale = _get_decimal_scale_add_sub(self.scale(), rhs.scale());
19        let lhs = self.to_scale(scale)?;
20        let rhs = rhs.to_scale(scale)?;
21        Ok((&lhs.0 - &rhs.0).into_decimal_unchecked(None, scale))
22    }
23}
24
25impl Mul for &DecimalChunked {
26    type Output = PolarsResult<DecimalChunked>;
27
28    fn mul(self, rhs: Self) -> Self::Output {
29        let scale = _get_decimal_scale_mul(self.scale(), rhs.scale());
30        Ok((&self.0 * &rhs.0).into_decimal_unchecked(None, scale))
31    }
32}
33
34impl Div for &DecimalChunked {
35    type Output = PolarsResult<DecimalChunked>;
36
37    fn div(self, rhs: Self) -> Self::Output {
38        let scale = _get_decimal_scale_div(self.scale());
39        let lhs = self.to_scale(scale + rhs.scale())?;
40        Ok((&lhs.0 / &rhs.0).into_decimal_unchecked(None, scale))
41    }
42}
43
44// Used by polars-plan to determine schema.
45pub fn _get_decimal_scale_add_sub(scale_left: usize, scale_right: usize) -> usize {
46    scale_left.max(scale_right)
47}
48
49pub fn _get_decimal_scale_mul(scale_left: usize, scale_right: usize) -> usize {
50    scale_left + scale_right
51}
52
53pub fn _get_decimal_scale_div(scale_left: usize) -> usize {
54    // Follow postgres and MySQL adding a fixed scale increment of 4
55    scale_left + 4
56}