polars_python/series/
comparison.rs

1use pyo3::prelude::*;
2
3use crate::PySeries;
4use crate::error::PyPolarsErr;
5use crate::prelude::*;
6use crate::utils::EnterPolarsExt;
7
8#[pymethods]
9impl PySeries {
10    fn eq(&self, py: Python<'_>, rhs: &PySeries) -> PyResult<Self> {
11        py.enter_polars_series(|| self.series.equal(&rhs.series))
12    }
13
14    fn neq(&self, py: Python<'_>, rhs: &PySeries) -> PyResult<Self> {
15        py.enter_polars_series(|| self.series.not_equal(&rhs.series))
16    }
17
18    fn gt(&self, py: Python<'_>, rhs: &PySeries) -> PyResult<Self> {
19        py.enter_polars_series(|| self.series.gt(&rhs.series))
20    }
21
22    fn gt_eq(&self, py: Python<'_>, rhs: &PySeries) -> PyResult<Self> {
23        py.enter_polars_series(|| self.series.gt_eq(&rhs.series))
24    }
25
26    fn lt(&self, py: Python<'_>, rhs: &PySeries) -> PyResult<Self> {
27        py.enter_polars_series(|| self.series.lt(&rhs.series))
28    }
29
30    fn lt_eq(&self, py: Python<'_>, rhs: &PySeries) -> PyResult<Self> {
31        py.enter_polars_series(|| self.series.lt_eq(&rhs.series))
32    }
33}
34
35macro_rules! impl_op {
36    ($op:ident, $name:ident, $type:ty) => {
37        #[pymethods]
38        impl PySeries {
39            fn $name(&self, py: Python<'_>, rhs: $type) -> PyResult<Self> {
40                py.enter_polars_series(|| self.series.$op(rhs))
41            }
42        }
43    };
44}
45
46impl_op!(equal, eq_u8, u8);
47impl_op!(equal, eq_u16, u16);
48impl_op!(equal, eq_u32, u32);
49impl_op!(equal, eq_u64, u64);
50impl_op!(equal, eq_i8, i8);
51impl_op!(equal, eq_i16, i16);
52impl_op!(equal, eq_i32, i32);
53impl_op!(equal, eq_i64, i64);
54impl_op!(equal, eq_i128, i128);
55impl_op!(equal, eq_f32, f32);
56impl_op!(equal, eq_f64, f64);
57impl_op!(equal, eq_str, &str);
58
59impl_op!(not_equal, neq_u8, u8);
60impl_op!(not_equal, neq_u16, u16);
61impl_op!(not_equal, neq_u32, u32);
62impl_op!(not_equal, neq_u64, u64);
63impl_op!(not_equal, neq_i8, i8);
64impl_op!(not_equal, neq_i16, i16);
65impl_op!(not_equal, neq_i32, i32);
66impl_op!(not_equal, neq_i64, i64);
67impl_op!(not_equal, neq_i128, i128);
68impl_op!(not_equal, neq_f32, f32);
69impl_op!(not_equal, neq_f64, f64);
70impl_op!(not_equal, neq_str, &str);
71
72impl_op!(gt, gt_u8, u8);
73impl_op!(gt, gt_u16, u16);
74impl_op!(gt, gt_u32, u32);
75impl_op!(gt, gt_u64, u64);
76impl_op!(gt, gt_i8, i8);
77impl_op!(gt, gt_i16, i16);
78impl_op!(gt, gt_i32, i32);
79impl_op!(gt, gt_i64, i64);
80impl_op!(gt, gt_i128, i128);
81impl_op!(gt, gt_f32, f32);
82impl_op!(gt, gt_f64, f64);
83impl_op!(gt, gt_str, &str);
84
85impl_op!(gt_eq, gt_eq_u8, u8);
86impl_op!(gt_eq, gt_eq_u16, u16);
87impl_op!(gt_eq, gt_eq_u32, u32);
88impl_op!(gt_eq, gt_eq_u64, u64);
89impl_op!(gt_eq, gt_eq_i8, i8);
90impl_op!(gt_eq, gt_eq_i16, i16);
91impl_op!(gt_eq, gt_eq_i32, i32);
92impl_op!(gt_eq, gt_eq_i64, i64);
93impl_op!(gt_eq, gt_eq_i128, i128);
94impl_op!(gt_eq, gt_eq_f32, f32);
95impl_op!(gt_eq, gt_eq_f64, f64);
96impl_op!(gt_eq, gt_eq_str, &str);
97
98impl_op!(lt, lt_u8, u8);
99impl_op!(lt, lt_u16, u16);
100impl_op!(lt, lt_u32, u32);
101impl_op!(lt, lt_u64, u64);
102impl_op!(lt, lt_i8, i8);
103impl_op!(lt, lt_i16, i16);
104impl_op!(lt, lt_i32, i32);
105impl_op!(lt, lt_i64, i64);
106impl_op!(lt, lt_i128, i128);
107impl_op!(lt, lt_f32, f32);
108impl_op!(lt, lt_f64, f64);
109impl_op!(lt, lt_str, &str);
110
111impl_op!(lt_eq, lt_eq_u8, u8);
112impl_op!(lt_eq, lt_eq_u16, u16);
113impl_op!(lt_eq, lt_eq_u32, u32);
114impl_op!(lt_eq, lt_eq_u64, u64);
115impl_op!(lt_eq, lt_eq_i8, i8);
116impl_op!(lt_eq, lt_eq_i16, i16);
117impl_op!(lt_eq, lt_eq_i32, i32);
118impl_op!(lt_eq, lt_eq_i64, i64);
119impl_op!(lt_eq, lt_eq_i128, i128);
120impl_op!(lt_eq, lt_eq_f32, f32);
121impl_op!(lt_eq, lt_eq_f64, f64);
122impl_op!(lt_eq, lt_eq_str, &str);
123
124struct PyDecimal(i128, usize);
125
126impl<'source> FromPyObject<'source> for PyDecimal {
127    fn extract_bound(obj: &Bound<'source, PyAny>) -> PyResult<Self> {
128        if let Ok(val) = obj.extract() {
129            return Ok(PyDecimal(val, 0));
130        }
131
132        let (sign, digits, exponent) = obj
133            .call_method0("as_tuple")?
134            .extract::<(i8, Vec<u8>, i8)>()?;
135        let mut val = 0_i128;
136        for d in digits {
137            if let Some(v) = val.checked_mul(10).and_then(|val| val.checked_add(d as _)) {
138                val = v;
139            } else {
140                return Err(PyPolarsErr::from(polars_err!(ComputeError: "overflow")).into());
141            }
142        }
143        let exponent = if exponent > 0 {
144            if let Some(v) = val.checked_mul(10_i128.pow((-exponent) as u32)) {
145                val = v;
146            } else {
147                return Err(PyPolarsErr::from(polars_err!(ComputeError: "overflow")).into());
148            };
149            0_usize
150        } else {
151            -exponent as _
152        };
153        if sign == 1 {
154            val = -val
155        };
156        Ok(PyDecimal(val, exponent))
157    }
158}
159
160macro_rules! impl_decimal {
161    ($name:ident, $method:ident) => {
162        #[pymethods]
163        impl PySeries {
164            fn $name(&self, py: Python<'_>, rhs: PyDecimal) -> PyResult<Self> {
165                let rhs = Series::new(
166                    PlSmallStr::from_static("decimal"),
167                    &[AnyValue::Decimal(rhs.0, rhs.1)],
168                );
169                py.enter_polars_series(|| self.series.$method(&rhs))
170            }
171        }
172    };
173}
174
175impl_decimal!(eq_decimal, equal);
176impl_decimal!(neq_decimal, not_equal);
177impl_decimal!(gt_decimal, gt);
178impl_decimal!(gt_eq_decimal, gt_eq);
179impl_decimal!(lt_decimal, lt);
180impl_decimal!(lt_eq_decimal, lt_eq);