Path: blob/main/crates/polars-python/src/series/comparison.rs
7889 views
use polars_compute::decimal::{DEC128_MAX_PREC, dec128_fits};1use pyo3::prelude::*;23use crate::PySeries;4use crate::error::PyPolarsErr;5use crate::prelude::*;6use crate::utils::EnterPolarsExt;78#[pymethods]9impl PySeries {10fn eq(&self, py: Python<'_>, rhs: &PySeries) -> PyResult<Self> {11py.enter_polars_series(|| self.series.read().equal(&*rhs.series.read()))12}1314fn neq(&self, py: Python<'_>, rhs: &PySeries) -> PyResult<Self> {15py.enter_polars_series(|| self.series.read().not_equal(&*rhs.series.read()))16}1718fn gt(&self, py: Python<'_>, rhs: &PySeries) -> PyResult<Self> {19py.enter_polars_series(|| self.series.read().gt(&*rhs.series.read()))20}2122fn gt_eq(&self, py: Python<'_>, rhs: &PySeries) -> PyResult<Self> {23py.enter_polars_series(|| self.series.read().gt_eq(&*rhs.series.read()))24}2526fn lt(&self, py: Python<'_>, rhs: &PySeries) -> PyResult<Self> {27py.enter_polars_series(|| self.series.read().lt(&*rhs.series.read()))28}2930fn lt_eq(&self, py: Python<'_>, rhs: &PySeries) -> PyResult<Self> {31py.enter_polars_series(|| self.series.read().lt_eq(&*rhs.series.read()))32}33}3435macro_rules! impl_op {36($op:ident, $name:ident, $type:ty) => {37#[pymethods]38impl PySeries {39fn $name(&self, py: Python<'_>, rhs: $type) -> PyResult<Self> {40py.enter_polars_series(|| self.series.read().$op(rhs))41}42}43};44}4546impl_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_f16, pf16);56impl_op!(equal, eq_f32, f32);57impl_op!(equal, eq_f64, f64);58impl_op!(equal, eq_str, &str);5960impl_op!(not_equal, neq_u8, u8);61impl_op!(not_equal, neq_u16, u16);62impl_op!(not_equal, neq_u32, u32);63impl_op!(not_equal, neq_u64, u64);64impl_op!(not_equal, neq_i8, i8);65impl_op!(not_equal, neq_i16, i16);66impl_op!(not_equal, neq_i32, i32);67impl_op!(not_equal, neq_i64, i64);68impl_op!(not_equal, neq_i128, i128);69impl_op!(not_equal, neq_f16, pf16);70impl_op!(not_equal, neq_f32, f32);71impl_op!(not_equal, neq_f64, f64);72impl_op!(not_equal, neq_str, &str);7374impl_op!(gt, gt_u8, u8);75impl_op!(gt, gt_u16, u16);76impl_op!(gt, gt_u32, u32);77impl_op!(gt, gt_u64, u64);78impl_op!(gt, gt_u128, u128);79impl_op!(gt, gt_i8, i8);80impl_op!(gt, gt_i16, i16);81impl_op!(gt, gt_i32, i32);82impl_op!(gt, gt_i64, i64);83impl_op!(gt, gt_i128, i128);84impl_op!(gt, gt_f16, pf16);85impl_op!(gt, gt_f32, f32);86impl_op!(gt, gt_f64, f64);87impl_op!(gt, gt_str, &str);8889impl_op!(gt_eq, gt_eq_u8, u8);90impl_op!(gt_eq, gt_eq_u16, u16);91impl_op!(gt_eq, gt_eq_u32, u32);92impl_op!(gt_eq, gt_eq_u64, u64);93impl_op!(gt_eq, gt_eq_i8, i8);94impl_op!(gt_eq, gt_eq_i16, i16);95impl_op!(gt_eq, gt_eq_i32, i32);96impl_op!(gt_eq, gt_eq_i64, i64);97impl_op!(gt_eq, gt_eq_i128, i128);98impl_op!(gt_eq, gt_eq_f16, pf16);99impl_op!(gt_eq, gt_eq_f32, f32);100impl_op!(gt_eq, gt_eq_f64, f64);101impl_op!(gt_eq, gt_eq_str, &str);102103impl_op!(lt, lt_u8, u8);104impl_op!(lt, lt_u16, u16);105impl_op!(lt, lt_u32, u32);106impl_op!(lt, lt_u64, u64);107impl_op!(lt, lt_u128, u128);108impl_op!(lt, lt_i8, i8);109impl_op!(lt, lt_i16, i16);110impl_op!(lt, lt_i32, i32);111impl_op!(lt, lt_i64, i64);112impl_op!(lt, lt_i128, i128);113impl_op!(lt, lt_f16, pf16);114impl_op!(lt, lt_f32, f32);115impl_op!(lt, lt_f64, f64);116impl_op!(lt, lt_str, &str);117118impl_op!(lt_eq, lt_eq_u8, u8);119impl_op!(lt_eq, lt_eq_u16, u16);120impl_op!(lt_eq, lt_eq_u32, u32);121impl_op!(lt_eq, lt_eq_u64, u64);122impl_op!(lt_eq, lt_eq_i8, i8);123impl_op!(lt_eq, lt_eq_i16, i16);124impl_op!(lt_eq, lt_eq_i32, i32);125impl_op!(lt_eq, lt_eq_i64, i64);126impl_op!(lt_eq, lt_eq_i128, i128);127impl_op!(lt_eq, lt_eq_f16, pf16);128impl_op!(lt_eq, lt_eq_f32, f32);129impl_op!(lt_eq, lt_eq_f64, f64);130impl_op!(lt_eq, lt_eq_str, &str);131132struct PyDecimal(i128, usize, usize);133134impl<'source> FromPyObject<'source> for PyDecimal {135fn extract_bound(obj: &Bound<'source, PyAny>) -> PyResult<Self> {136if let Ok(val) = obj.extract() {137return Ok(PyDecimal(val, DEC128_MAX_PREC, 0));138}139140let err = || {141Err(PyPolarsErr::from(polars_err!(ComputeError: "overflow in Python Decimal to Polars Decimal conversion")).into())142};143144let (sign, digits, exponent) = obj145.call_method0("as_tuple")?146.extract::<(i8, Vec<u8>, i8)>()?;147let mut val = 0_i128;148for d in digits {149if let Some(v) = val.checked_mul(10).and_then(|val| val.checked_add(d as _)) {150val = v;151} else {152return err();153}154}155let scale = if exponent > 0 {156if let Some(v) = val.checked_mul(10_i128.pow((-exponent) as u32)) {157val = v;158} else {159return err();160};1610_usize162} else {163(-exponent) as usize164};165if sign == 1 {166val = -val167};168if dec128_fits(val, DEC128_MAX_PREC) {169Ok(PyDecimal(val, DEC128_MAX_PREC, scale))170} else {171err()172}173}174}175176macro_rules! impl_decimal {177($name:ident, $method:ident) => {178#[pymethods]179impl PySeries {180fn $name(&self, py: Python<'_>, rhs: PyDecimal) -> PyResult<Self> {181let rhs = Series::new(182PlSmallStr::from_static("decimal"),183&[AnyValue::Decimal(rhs.0, rhs.1, rhs.2)],184);185py.enter_polars_series(|| self.series.read().$method(&rhs))186}187}188};189}190191impl_decimal!(eq_decimal, equal);192impl_decimal!(neq_decimal, not_equal);193impl_decimal!(gt_decimal, gt);194impl_decimal!(gt_eq_decimal, gt_eq);195impl_decimal!(lt_decimal, lt);196impl_decimal!(lt_eq_decimal, lt_eq);197198199