Path: blob/main/crates/polars-core/src/series/implementations/decimal.rs
8433 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, 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_arg_min(&self, groups: &GroupsType) -> Series {168self.0.physical().agg_arg_min(groups)169}170171#[cfg(feature = "algorithm_group_by")]172unsafe fn agg_arg_max(&self, groups: &GroupsType) -> Series {173self.0.physical().agg_arg_max(groups)174}175176#[cfg(feature = "algorithm_group_by")]177unsafe fn agg_list(&self, groups: &GroupsType) -> Series {178self.agg_helper(|ca| ca.agg_list(groups))179}180181#[cfg(feature = "algorithm_group_by")]182unsafe fn agg_var(&self, groups: &GroupsType, ddof: u8) -> Series {183self.0184.cast(&DataType::Float64)185.unwrap()186.agg_var(groups, ddof)187}188189#[cfg(feature = "algorithm_group_by")]190unsafe fn agg_std(&self, groups: &GroupsType, ddof: u8) -> Series {191self.0192.cast(&DataType::Float64)193.unwrap()194.agg_std(groups, ddof)195}196197fn subtract(&self, rhs: &Series) -> PolarsResult<Series> {198let rhs = rhs.decimal()?;199((&self.0) - rhs).map(|ca| ca.into_series())200}201fn add_to(&self, rhs: &Series) -> PolarsResult<Series> {202let rhs = rhs.decimal()?;203((&self.0) + rhs).map(|ca| ca.into_series())204}205fn multiply(&self, rhs: &Series) -> PolarsResult<Series> {206let rhs = rhs.decimal()?;207((&self.0) * rhs).map(|ca| ca.into_series())208}209fn divide(&self, rhs: &Series) -> PolarsResult<Series> {210let rhs = rhs.decimal()?;211((&self.0) / rhs).map(|ca| ca.into_series())212}213#[cfg(feature = "algorithm_group_by")]214fn group_tuples(&self, multithreaded: bool, sorted: bool) -> PolarsResult<GroupsType> {215self.0.physical().group_tuples(multithreaded, sorted)216}217fn arg_sort_multiple(218&self,219by: &[Column],220options: &SortMultipleOptions,221) -> PolarsResult<IdxCa> {222self.0.physical().arg_sort_multiple(by, options)223}224}225226impl SeriesTrait for SeriesWrap<DecimalChunked> {227fn rename(&mut self, name: PlSmallStr) {228self.0.rename(name)229}230231fn chunk_lengths(&self) -> ChunkLenIter<'_> {232self.0.physical().chunk_lengths()233}234235fn name(&self) -> &PlSmallStr {236self.0.name()237}238239fn chunks(&self) -> &Vec<ArrayRef> {240self.0.physical().chunks()241}242unsafe fn chunks_mut(&mut self) -> &mut Vec<ArrayRef> {243self.0.physical_mut().chunks_mut()244}245246fn slice(&self, offset: i64, length: usize) -> Series {247self.apply_physical_to_s(|ca| ca.slice(offset, length))248}249250fn split_at(&self, offset: i64) -> (Series, Series) {251let (a, b) = self.0.split_at(offset);252(a.into_series(), b.into_series())253}254255fn append(&mut self, other: &Series) -> PolarsResult<()> {256polars_ensure!(self.0.dtype() == other.dtype(), append);257let mut other = other.to_physical_repr().into_owned();258self.0259.physical_mut()260.append_owned(std::mem::take(other._get_inner_mut().as_mut()))261}262fn append_owned(&mut self, mut other: Series) -> PolarsResult<()> {263polars_ensure!(self.0.dtype() == other.dtype(), append);264self.0.physical_mut().append_owned(std::mem::take(265&mut other266._get_inner_mut()267.as_any_mut()268.downcast_mut::<DecimalChunked>()269.unwrap()270.phys,271))272}273274fn extend(&mut self, other: &Series) -> PolarsResult<()> {275polars_ensure!(self.0.dtype() == other.dtype(), extend);276// 3 refs277// ref Cow278// ref SeriesTrait279// ref ChunkedArray280let other = other.to_physical_repr();281self.0282.physical_mut()283.extend(other.as_ref().as_ref().as_ref())?;284Ok(())285}286287fn filter(&self, filter: &BooleanChunked) -> PolarsResult<Series> {288Ok(self289.0290.physical()291.filter(filter)?292.into_decimal_unchecked(self.0.precision(), self.0.scale())293.into_series())294}295296fn take(&self, indices: &IdxCa) -> PolarsResult<Series> {297Ok(self298.0299.physical()300.take(indices)?301.into_decimal_unchecked(self.0.precision(), self.0.scale())302.into_series())303}304305unsafe fn take_unchecked(&self, indices: &IdxCa) -> Series {306self.0307.physical()308.take_unchecked(indices)309.into_decimal_unchecked(self.0.precision(), self.0.scale())310.into_series()311}312313fn take_slice(&self, indices: &[IdxSize]) -> PolarsResult<Series> {314Ok(self315.0316.physical()317.take(indices)?318.into_decimal_unchecked(self.0.precision(), self.0.scale())319.into_series())320}321322unsafe fn take_slice_unchecked(&self, indices: &[IdxSize]) -> Series {323self.0324.physical()325.take_unchecked(indices)326.into_decimal_unchecked(self.0.precision(), self.0.scale())327.into_series()328}329330fn deposit(&self, validity: &Bitmap) -> Series {331self.0332.physical()333.deposit(validity)334.into_decimal_unchecked(self.0.precision(), self.0.scale())335.into_series()336}337338fn len(&self) -> usize {339self.0.len()340}341342fn rechunk(&self) -> Series {343let ca = self.0.physical().rechunk().into_owned();344ca.into_decimal_unchecked(self.0.precision(), self.0.scale())345.into_series()346}347348fn new_from_index(&self, index: usize, length: usize) -> Series {349self.0350.physical()351.new_from_index(index, length)352.into_decimal_unchecked(self.0.precision(), self.0.scale())353.into_series()354}355356fn cast(&self, dtype: &DataType, cast_options: CastOptions) -> PolarsResult<Series> {357self.0.cast_with_options(dtype, cast_options)358}359360#[inline]361unsafe fn get_unchecked(&self, index: usize) -> AnyValue<'_> {362self.0.get_any_value_unchecked(index)363}364365fn sort_with(&self, options: SortOptions) -> PolarsResult<Series> {366Ok(self367.0368.physical()369.sort_with(options)370.into_decimal_unchecked(self.0.precision(), self.0.scale())371.into_series())372}373374fn arg_sort(&self, options: SortOptions) -> IdxCa {375self.0.physical().arg_sort(options)376}377378fn null_count(&self) -> usize {379self.0.null_count()380}381382fn has_nulls(&self) -> bool {383self.0.has_nulls()384}385386#[cfg(feature = "algorithm_group_by")]387fn unique(&self) -> PolarsResult<Series> {388Ok(self.apply_physical_to_s(|ca| ca.unique().unwrap()))389}390391#[cfg(feature = "algorithm_group_by")]392fn n_unique(&self) -> PolarsResult<usize> {393self.0.physical().n_unique()394}395396#[cfg(feature = "algorithm_group_by")]397fn arg_unique(&self) -> PolarsResult<IdxCa> {398self.0.physical().arg_unique()399}400401fn unique_id(&self) -> PolarsResult<(IdxSize, Vec<IdxSize>)> {402ChunkUnique::unique_id(self.0.physical())403}404405fn is_null(&self) -> BooleanChunked {406self.0.is_null()407}408409fn is_not_null(&self) -> BooleanChunked {410self.0.is_not_null()411}412413fn reverse(&self) -> Series {414self.apply_physical_to_s(|ca| ca.reverse())415}416417fn shift(&self, periods: i64) -> Series {418self.apply_physical_to_s(|ca| ca.shift(periods))419}420421#[cfg(feature = "approx_unique")]422fn approx_n_unique(&self) -> PolarsResult<IdxSize> {423Ok(ChunkApproxNUnique::approx_n_unique(self.0.physical()))424}425426fn clone_inner(&self) -> Arc<dyn SeriesTrait> {427Arc::new(SeriesWrap(Clone::clone(&self.0)))428}429430fn sum_reduce(&self) -> PolarsResult<Scalar> {431Ok(self.apply_physical(|ca| {432let sum = ca.sum();433let DataType::Decimal(prec, scale) = self.dtype() else {434unreachable!()435};436let av = AnyValue::Decimal(sum.unwrap(), *prec, *scale);437Scalar::new(self.dtype().clone(), av)438}))439}440441fn min_reduce(&self) -> PolarsResult<Scalar> {442Ok(self.apply_physical(|ca| {443let min = ca.min();444let DataType::Decimal(prec, scale) = self.dtype() else {445unreachable!()446};447let av = if let Some(min) = min {448AnyValue::Decimal(min, *prec, *scale)449} else {450AnyValue::Null451};452Scalar::new(self.dtype().clone(), av)453}))454}455456fn max_reduce(&self) -> PolarsResult<Scalar> {457Ok(self.apply_physical(|ca| {458let max = ca.max();459let DataType::Decimal(prec, scale) = self.dtype() else {460unreachable!()461};462let av = if let Some(m) = max {463AnyValue::Decimal(m, *prec, *scale)464} else {465AnyValue::Null466};467Scalar::new(self.dtype().clone(), av)468}))469}470471fn _sum_as_f64(&self) -> f64 {472self.0.physical()._sum_as_f64() / self.scale_factor() as f64473}474475fn mean(&self) -> Option<f64> {476self.0477.physical()478.mean()479.map(|v| v / self.scale_factor() as f64)480}481fn mean_reduce(&self) -> PolarsResult<Scalar> {482Ok(Scalar::new(DataType::Float64, self.mean().into()))483}484485fn median(&self) -> Option<f64> {486self.0487.physical()488.median()489.map(|v| v / self.scale_factor() as f64)490}491492fn median_reduce(&self) -> PolarsResult<Scalar> {493Ok(self.apply_scale(self.0.physical().median_reduce()))494}495496fn std(&self, ddof: u8) -> Option<f64> {497self.0.cast(&DataType::Float64).ok()?.std(ddof)498}499500fn std_reduce(&self, ddof: u8) -> PolarsResult<Scalar> {501self.0.cast(&DataType::Float64)?.std_reduce(ddof)502}503504fn var(&self, ddof: u8) -> Option<f64> {505self.0.cast(&DataType::Float64).ok()?.var(ddof)506}507508fn var_reduce(&self, ddof: u8) -> PolarsResult<Scalar> {509self.0.cast(&DataType::Float64)?.var_reduce(ddof)510}511512fn quantile_reduce(&self, quantile: f64, method: QuantileMethod) -> PolarsResult<Scalar> {513self.0514.physical()515.quantile_reduce(quantile, method)516.map(|v| self.apply_scale(v))517}518519fn quantiles_reduce(&self, quantiles: &[f64], method: QuantileMethod) -> PolarsResult<Scalar> {520let result = self.0.physical().quantiles_reduce(quantiles, method)?;521if let AnyValue::List(float_s) = result.value() {522let scale_factor = self.scale_factor() as f64;523let float_ca = float_s.f64().unwrap();524let scaled_s = float_ca525.iter()526.map(|v: Option<f64>| v.map(|f| f / scale_factor))527.collect::<Float64Chunked>()528.into_series();529Ok(Scalar::new(530DataType::List(Box::new(self.dtype().clone())),531AnyValue::List(scaled_s),532))533} else {534polars_bail!(ComputeError: "expected list scalar from quantiles_reduce")535}536}537538fn find_validity_mismatch(&self, other: &Series, idxs: &mut Vec<IdxSize>) {539self.0.physical().find_validity_mismatch(other, idxs)540}541542fn as_any(&self) -> &dyn Any {543&self.0544}545546fn as_any_mut(&mut self) -> &mut dyn Any {547&mut self.0548}549550fn as_phys_any(&self) -> &dyn Any {551self.0.physical()552}553554fn as_arc_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {555self as _556}557}558559560