Path: blob/main/crates/polars-core/src/series/implementations/decimal.rs
6940 views
use polars_compute::rolling::QuantileMethod;12use super::*;3use crate::prelude::*;45unsafe impl IntoSeries for DecimalChunked {6fn into_series(self) -> Series {7Series(Arc::new(SeriesWrap(self)))8}9}1011impl private::PrivateSeriesNumeric for SeriesWrap<DecimalChunked> {12fn bit_repr(&self) -> Option<BitRepr> {13Some(self.0.physical().to_bit_repr())14}15}1617impl SeriesWrap<DecimalChunked> {18fn apply_physical_to_s<F: Fn(&Int128Chunked) -> Int128Chunked>(&self, f: F) -> Series {19f(self.0.physical())20.into_decimal_unchecked(self.0.precision(), self.0.scale())21.into_series()22}2324fn apply_physical<T, F: Fn(&Int128Chunked) -> T>(&self, f: F) -> T {25f(self.0.physical())26}2728fn scale_factor(&self) -> u128 {2910u128.pow(self.0.scale() as u32)30}3132fn apply_scale(&self, mut scalar: Scalar) -> Scalar {33if scalar.is_null() {34return scalar;35}3637debug_assert_eq!(scalar.dtype(), &DataType::Float64);38let v = scalar39.value()40.try_extract::<f64>()41.expect("should be f64 scalar");42scalar.update((v / self.scale_factor() as f64).into());43scalar44}4546fn agg_helper<F: Fn(&Int128Chunked) -> Series>(&self, f: F) -> Series {47let agg_s = f(self.0.physical());48match agg_s.dtype() {49DataType::Int128 => {50let ca = agg_s.i128().unwrap();51let ca = ca.as_ref().clone();52let precision = self.0.precision();53let scale = self.0.scale();54ca.into_decimal_unchecked(precision, scale).into_series()55},56DataType::List(dtype) if matches!(dtype.as_ref(), DataType::Int128) => {57let dtype = self.0.dtype();58let ca = agg_s.list().unwrap();59let arr = ca.downcast_iter().next().unwrap();60// SAFETY: dtype is passed correctly61let precision = self.0.precision();62let scale = self.0.scale();63let s = unsafe {64Series::from_chunks_and_dtype_unchecked(65PlSmallStr::EMPTY,66vec![arr.values().clone()],67dtype,68)69}70.into_decimal(precision, scale)71.unwrap();72let new_values = s.array_ref(0).clone();73let dtype = DataType::Int128;74let arrow_dtype =75ListArray::<i64>::default_datatype(dtype.to_arrow(CompatLevel::newest()));76let new_arr = ListArray::<i64>::new(77arrow_dtype,78arr.offsets().clone(),79new_values,80arr.validity().cloned(),81);82unsafe {83ListChunked::from_chunks_and_dtype_unchecked(84agg_s.name().clone(),85vec![Box::new(new_arr)],86DataType::List(Box::new(DataType::Decimal(precision, Some(scale)))),87)88.into_series()89}90},91_ => unreachable!(),92}93}94}9596impl private::PrivateSeries for SeriesWrap<DecimalChunked> {97fn compute_len(&mut self) {98self.0.physical_mut().compute_len()99}100101fn _field(&self) -> Cow<'_, Field> {102Cow::Owned(self.0.field())103}104105fn _dtype(&self) -> &DataType {106self.0.dtype()107}108fn _get_flags(&self) -> StatisticsFlags {109self.0.physical().get_flags()110}111fn _set_flags(&mut self, flags: StatisticsFlags) {112self.0.physical_mut().set_flags(flags)113}114115#[cfg(feature = "zip_with")]116fn zip_with_same_type(&self, mask: &BooleanChunked, other: &Series) -> PolarsResult<Series> {117let other = other.decimal()?;118119Ok(self120.0121.physical()122.zip_with(mask, other.physical())?123.into_decimal_unchecked(self.0.precision(), self.0.scale())124.into_series())125}126fn into_total_eq_inner<'a>(&'a self) -> Box<dyn TotalEqInner + 'a> {127self.0.physical().into_total_eq_inner()128}129fn into_total_ord_inner<'a>(&'a self) -> Box<dyn TotalOrdInner + 'a> {130self.0.physical().into_total_ord_inner()131}132133fn vec_hash(134&self,135random_state: PlSeedableRandomStateQuality,136buf: &mut Vec<u64>,137) -> PolarsResult<()> {138self.0.physical().vec_hash(random_state, buf)?;139Ok(())140}141142fn vec_hash_combine(143&self,144build_hasher: PlSeedableRandomStateQuality,145hashes: &mut [u64],146) -> PolarsResult<()> {147self.0.physical().vec_hash_combine(build_hasher, hashes)?;148Ok(())149}150151#[cfg(feature = "algorithm_group_by")]152unsafe fn agg_sum(&self, groups: &GroupsType) -> Series {153self.agg_helper(|ca| ca.agg_sum(groups))154}155156#[cfg(feature = "algorithm_group_by")]157unsafe fn agg_min(&self, groups: &GroupsType) -> Series {158self.agg_helper(|ca| ca.agg_min(groups))159}160161#[cfg(feature = "algorithm_group_by")]162unsafe fn agg_max(&self, groups: &GroupsType) -> Series {163self.agg_helper(|ca| ca.agg_max(groups))164}165166#[cfg(feature = "algorithm_group_by")]167unsafe fn agg_list(&self, groups: &GroupsType) -> Series {168self.agg_helper(|ca| ca.agg_list(groups))169}170171fn subtract(&self, rhs: &Series) -> PolarsResult<Series> {172let rhs = rhs.decimal()?;173((&self.0) - rhs).map(|ca| ca.into_series())174}175fn add_to(&self, rhs: &Series) -> PolarsResult<Series> {176let rhs = rhs.decimal()?;177((&self.0) + rhs).map(|ca| ca.into_series())178}179fn multiply(&self, rhs: &Series) -> PolarsResult<Series> {180let rhs = rhs.decimal()?;181((&self.0) * rhs).map(|ca| ca.into_series())182}183fn divide(&self, rhs: &Series) -> PolarsResult<Series> {184let rhs = rhs.decimal()?;185((&self.0) / rhs).map(|ca| ca.into_series())186}187#[cfg(feature = "algorithm_group_by")]188fn group_tuples(&self, multithreaded: bool, sorted: bool) -> PolarsResult<GroupsType> {189self.0.physical().group_tuples(multithreaded, sorted)190}191fn arg_sort_multiple(192&self,193by: &[Column],194options: &SortMultipleOptions,195) -> PolarsResult<IdxCa> {196self.0.physical().arg_sort_multiple(by, options)197}198}199200impl SeriesTrait for SeriesWrap<DecimalChunked> {201fn rename(&mut self, name: PlSmallStr) {202self.0.rename(name)203}204205fn chunk_lengths(&self) -> ChunkLenIter<'_> {206self.0.physical().chunk_lengths()207}208209fn name(&self) -> &PlSmallStr {210self.0.name()211}212213fn chunks(&self) -> &Vec<ArrayRef> {214self.0.physical().chunks()215}216unsafe fn chunks_mut(&mut self) -> &mut Vec<ArrayRef> {217self.0.physical_mut().chunks_mut()218}219220fn slice(&self, offset: i64, length: usize) -> Series {221self.apply_physical_to_s(|ca| ca.slice(offset, length))222}223224fn split_at(&self, offset: i64) -> (Series, Series) {225let (a, b) = self.0.split_at(offset);226(a.into_series(), b.into_series())227}228229fn append(&mut self, other: &Series) -> PolarsResult<()> {230polars_ensure!(self.0.dtype() == other.dtype(), append);231let mut other = other.to_physical_repr().into_owned();232self.0233.physical_mut()234.append_owned(std::mem::take(other._get_inner_mut().as_mut()))235}236fn append_owned(&mut self, mut other: Series) -> PolarsResult<()> {237polars_ensure!(self.0.dtype() == other.dtype(), append);238self.0.physical_mut().append_owned(std::mem::take(239&mut other240._get_inner_mut()241.as_any_mut()242.downcast_mut::<DecimalChunked>()243.unwrap()244.phys,245))246}247248fn extend(&mut self, other: &Series) -> PolarsResult<()> {249polars_ensure!(self.0.dtype() == other.dtype(), extend);250// 3 refs251// ref Cow252// ref SeriesTrait253// ref ChunkedArray254let other = other.to_physical_repr();255self.0256.physical_mut()257.extend(other.as_ref().as_ref().as_ref())?;258Ok(())259}260261fn filter(&self, filter: &BooleanChunked) -> PolarsResult<Series> {262Ok(self263.0264.physical()265.filter(filter)?266.into_decimal_unchecked(self.0.precision(), self.0.scale())267.into_series())268}269270fn take(&self, indices: &IdxCa) -> PolarsResult<Series> {271Ok(self272.0273.physical()274.take(indices)?275.into_decimal_unchecked(self.0.precision(), self.0.scale())276.into_series())277}278279unsafe fn take_unchecked(&self, indices: &IdxCa) -> Series {280self.0281.physical()282.take_unchecked(indices)283.into_decimal_unchecked(self.0.precision(), self.0.scale())284.into_series()285}286287fn take_slice(&self, indices: &[IdxSize]) -> PolarsResult<Series> {288Ok(self289.0290.physical()291.take(indices)?292.into_decimal_unchecked(self.0.precision(), self.0.scale())293.into_series())294}295296unsafe fn take_slice_unchecked(&self, indices: &[IdxSize]) -> Series {297self.0298.physical()299.take_unchecked(indices)300.into_decimal_unchecked(self.0.precision(), self.0.scale())301.into_series()302}303304fn len(&self) -> usize {305self.0.len()306}307308fn rechunk(&self) -> Series {309let ca = self.0.physical().rechunk().into_owned();310ca.into_decimal_unchecked(self.0.precision(), self.0.scale())311.into_series()312}313314fn new_from_index(&self, index: usize, length: usize) -> Series {315self.0316.physical()317.new_from_index(index, length)318.into_decimal_unchecked(self.0.precision(), self.0.scale())319.into_series()320}321322fn cast(&self, dtype: &DataType, cast_options: CastOptions) -> PolarsResult<Series> {323self.0.cast_with_options(dtype, cast_options)324}325326#[inline]327unsafe fn get_unchecked(&self, index: usize) -> AnyValue<'_> {328self.0.get_any_value_unchecked(index)329}330331fn sort_with(&self, options: SortOptions) -> PolarsResult<Series> {332Ok(self333.0334.physical()335.sort_with(options)336.into_decimal_unchecked(self.0.precision(), self.0.scale())337.into_series())338}339340fn arg_sort(&self, options: SortOptions) -> IdxCa {341self.0.physical().arg_sort(options)342}343344fn null_count(&self) -> usize {345self.0.null_count()346}347348fn has_nulls(&self) -> bool {349self.0.has_nulls()350}351352#[cfg(feature = "algorithm_group_by")]353fn unique(&self) -> PolarsResult<Series> {354Ok(self.apply_physical_to_s(|ca| ca.unique().unwrap()))355}356357#[cfg(feature = "algorithm_group_by")]358fn n_unique(&self) -> PolarsResult<usize> {359self.0.physical().n_unique()360}361362#[cfg(feature = "algorithm_group_by")]363fn arg_unique(&self) -> PolarsResult<IdxCa> {364self.0.physical().arg_unique()365}366367fn is_null(&self) -> BooleanChunked {368self.0.is_null()369}370371fn is_not_null(&self) -> BooleanChunked {372self.0.is_not_null()373}374375fn reverse(&self) -> Series {376self.apply_physical_to_s(|ca| ca.reverse())377}378379fn shift(&self, periods: i64) -> Series {380self.apply_physical_to_s(|ca| ca.shift(periods))381}382383fn clone_inner(&self) -> Arc<dyn SeriesTrait> {384Arc::new(SeriesWrap(Clone::clone(&self.0)))385}386387fn sum_reduce(&self) -> PolarsResult<Scalar> {388Ok(self.apply_physical(|ca| {389let sum = ca.sum();390let DataType::Decimal(_, Some(scale)) = self.dtype() else {391unreachable!()392};393let av = AnyValue::Decimal(sum.unwrap(), *scale);394Scalar::new(self.dtype().clone(), av)395}))396}397fn min_reduce(&self) -> PolarsResult<Scalar> {398Ok(self.apply_physical(|ca| {399let min = ca.min();400let DataType::Decimal(_, Some(scale)) = self.dtype() else {401unreachable!()402};403let av = if let Some(min) = min {404AnyValue::Decimal(min, *scale)405} else {406AnyValue::Null407};408Scalar::new(self.dtype().clone(), av)409}))410}411fn max_reduce(&self) -> PolarsResult<Scalar> {412Ok(self.apply_physical(|ca| {413let max = ca.max();414let DataType::Decimal(_, Some(scale)) = self.dtype() else {415unreachable!()416};417let av = if let Some(m) = max {418AnyValue::Decimal(m, *scale)419} else {420AnyValue::Null421};422Scalar::new(self.dtype().clone(), av)423}))424}425426fn _sum_as_f64(&self) -> f64 {427self.0.physical()._sum_as_f64() / self.scale_factor() as f64428}429430fn mean(&self) -> Option<f64> {431self.0432.physical()433.mean()434.map(|v| v / self.scale_factor() as f64)435}436437fn median(&self) -> Option<f64> {438self.0439.physical()440.median()441.map(|v| v / self.scale_factor() as f64)442}443fn median_reduce(&self) -> PolarsResult<Scalar> {444Ok(self.apply_scale(self.0.physical().median_reduce()))445}446447fn std(&self, ddof: u8) -> Option<f64> {448self.0449.physical()450.std(ddof)451.map(|v| v / self.scale_factor() as f64)452}453fn std_reduce(&self, ddof: u8) -> PolarsResult<Scalar> {454Ok(self.apply_scale(self.0.physical().std_reduce(ddof)))455}456457fn quantile_reduce(&self, quantile: f64, method: QuantileMethod) -> PolarsResult<Scalar> {458self.0459.physical()460.quantile_reduce(quantile, method)461.map(|v| self.apply_scale(v))462}463464fn find_validity_mismatch(&self, other: &Series, idxs: &mut Vec<IdxSize>) {465self.0.physical().find_validity_mismatch(other, idxs)466}467468fn as_any(&self) -> &dyn Any {469&self.0470}471472fn as_any_mut(&mut self) -> &mut dyn Any {473&mut self.0474}475476fn as_phys_any(&self) -> &dyn Any {477self.0.physical()478}479480fn as_arc_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {481self as _482}483}484485486