Skip to main content

polars_core/series/implementations/
mod.rs

1#![allow(unsafe_op_in_unsafe_fn)]
2#[cfg(feature = "dtype-array")]
3mod array;
4mod binary;
5mod binary_offset;
6mod boolean;
7#[cfg(feature = "dtype-categorical")]
8mod categorical;
9#[cfg(feature = "dtype-date")]
10mod date;
11#[cfg(feature = "dtype-datetime")]
12mod datetime;
13#[cfg(feature = "dtype-decimal")]
14mod decimal;
15#[cfg(feature = "dtype-duration")]
16mod duration;
17#[cfg(feature = "dtype-extension")]
18mod extension;
19mod floats;
20mod list;
21pub(crate) mod null;
22#[cfg(feature = "object")]
23mod object;
24mod string;
25#[cfg(feature = "dtype-struct")]
26mod struct_;
27#[cfg(feature = "dtype-time")]
28mod time;
29
30use std::any::Any;
31use std::borrow::Cow;
32
33use arrow::bitmap::Bitmap;
34use polars_compute::rolling::QuantileMethod;
35use polars_utils::aliases::PlSeedableRandomStateQuality;
36
37use super::*;
38use crate::chunked_array::AsSinglePtr;
39use crate::chunked_array::comparison::*;
40use crate::chunked_array::ops::compare_inner::{
41    IntoTotalEqInner, IntoTotalOrdInner, TotalEqInner, TotalOrdInner,
42};
43
44// Utility wrapper struct
45#[repr(transparent)]
46pub(crate) struct SeriesWrap<T>(pub T);
47
48impl<T: PolarsDataType> From<ChunkedArray<T>> for SeriesWrap<ChunkedArray<T>> {
49    fn from(ca: ChunkedArray<T>) -> Self {
50        SeriesWrap(ca)
51    }
52}
53
54impl<T: PolarsDataType> Deref for SeriesWrap<ChunkedArray<T>> {
55    type Target = ChunkedArray<T>;
56
57    fn deref(&self) -> &Self::Target {
58        &self.0
59    }
60}
61
62unsafe impl<T: PolarsPhysicalType> IntoSeries for ChunkedArray<T> {
63    fn into_series(self) -> Series {
64        T::ca_into_series(self)
65    }
66}
67
68macro_rules! impl_dyn_series {
69    ($ca: ident, $pdt:ty) => {
70        impl private::PrivateSeries for SeriesWrap<$ca> {
71            fn compute_len(&mut self) {
72                self.0.compute_len()
73            }
74
75            fn _field(&self) -> Cow<'_, Field> {
76                Cow::Borrowed(self.0.ref_field())
77            }
78
79            fn _dtype(&self) -> &DataType {
80                self.0.ref_field().dtype()
81            }
82
83            fn _get_flags(&self) -> StatisticsFlags {
84                self.0.get_flags()
85            }
86
87            fn _set_flags(&mut self, flags: StatisticsFlags) {
88                self.0.set_flags(flags)
89            }
90
91            unsafe fn equal_element(
92                &self,
93                idx_self: usize,
94                idx_other: usize,
95                other: &Series,
96            ) -> bool {
97                self.0.equal_element(idx_self, idx_other, other)
98            }
99
100            #[cfg(feature = "zip_with")]
101            fn zip_with_same_type(
102                &self,
103                mask: &BooleanChunked,
104                other: &Series,
105            ) -> PolarsResult<Series> {
106                ChunkZip::zip_with(&self.0, mask, other.as_ref().as_ref())
107                    .map(|ca| ca.into_series())
108            }
109            fn into_total_eq_inner<'a>(&'a self) -> Box<dyn TotalEqInner + 'a> {
110                (&self.0).into_total_eq_inner()
111            }
112            fn into_total_ord_inner<'a>(&'a self) -> Box<dyn TotalOrdInner + 'a> {
113                (&self.0).into_total_ord_inner()
114            }
115
116            fn vec_hash(
117                &self,
118                random_state: PlSeedableRandomStateQuality,
119                buf: &mut Vec<u64>,
120            ) -> PolarsResult<()> {
121                self.0.vec_hash(random_state, buf)?;
122                Ok(())
123            }
124
125            fn vec_hash_combine(
126                &self,
127                build_hasher: PlSeedableRandomStateQuality,
128                hashes: &mut [u64],
129            ) -> PolarsResult<()> {
130                self.0.vec_hash_combine(build_hasher, hashes)?;
131                Ok(())
132            }
133
134            #[cfg(feature = "algorithm_group_by")]
135            unsafe fn agg_min(&self, groups: &GroupsType) -> Series {
136                self.0.agg_min(groups)
137            }
138
139            #[cfg(feature = "algorithm_group_by")]
140            unsafe fn agg_max(&self, groups: &GroupsType) -> Series {
141                self.0.agg_max(groups)
142            }
143
144            #[cfg(feature = "algorithm_group_by")]
145            unsafe fn agg_arg_min(&self, groups: &GroupsType) -> Series {
146                self.0.agg_arg_min(groups)
147            }
148
149            #[cfg(feature = "algorithm_group_by")]
150            unsafe fn agg_arg_max(&self, groups: &GroupsType) -> Series {
151                self.0.agg_arg_max(groups)
152            }
153
154            #[cfg(feature = "algorithm_group_by")]
155            unsafe fn agg_sum(&self, groups: &GroupsType) -> Series {
156                use DataType::*;
157                match self.dtype() {
158                    Int8 | UInt8 | Int16 | UInt16 => self
159                        .cast(&Int64, CastOptions::Overflowing)
160                        .unwrap()
161                        .agg_sum(groups),
162                    _ => self.0.agg_sum(groups),
163                }
164            }
165
166            #[cfg(feature = "algorithm_group_by")]
167            unsafe fn agg_std(&self, groups: &GroupsType, ddof: u8) -> Series {
168                self.0.agg_std(groups, ddof)
169            }
170
171            #[cfg(feature = "algorithm_group_by")]
172            unsafe fn agg_var(&self, groups: &GroupsType, ddof: u8) -> Series {
173                self.0.agg_var(groups, ddof)
174            }
175
176            #[cfg(feature = "algorithm_group_by")]
177            unsafe fn agg_list(&self, groups: &GroupsType) -> Series {
178                self.0.agg_list(groups)
179            }
180
181            #[cfg(feature = "bitwise")]
182            unsafe fn agg_and(&self, groups: &GroupsType) -> Series {
183                self.0.agg_and(groups)
184            }
185            #[cfg(feature = "bitwise")]
186            unsafe fn agg_or(&self, groups: &GroupsType) -> Series {
187                self.0.agg_or(groups)
188            }
189            #[cfg(feature = "bitwise")]
190            unsafe fn agg_xor(&self, groups: &GroupsType) -> Series {
191                self.0.agg_xor(groups)
192            }
193
194            fn subtract(&self, rhs: &Series) -> PolarsResult<Series> {
195                NumOpsDispatch::subtract(&self.0, rhs)
196            }
197            fn add_to(&self, rhs: &Series) -> PolarsResult<Series> {
198                NumOpsDispatch::add_to(&self.0, rhs)
199            }
200            fn multiply(&self, rhs: &Series) -> PolarsResult<Series> {
201                NumOpsDispatch::multiply(&self.0, rhs)
202            }
203            fn divide(&self, rhs: &Series) -> PolarsResult<Series> {
204                NumOpsDispatch::divide(&self.0, rhs)
205            }
206            fn remainder(&self, rhs: &Series) -> PolarsResult<Series> {
207                NumOpsDispatch::remainder(&self.0, rhs)
208            }
209            #[cfg(feature = "algorithm_group_by")]
210            fn group_tuples(&self, multithreaded: bool, sorted: bool) -> PolarsResult<GroupsType> {
211                IntoGroupsType::group_tuples(&self.0, multithreaded, sorted)
212            }
213
214            fn arg_sort_multiple(
215                &self,
216                by: &[Column],
217                options: &SortMultipleOptions,
218            ) -> PolarsResult<IdxCa> {
219                self.0.arg_sort_multiple(by, options)
220            }
221        }
222
223        impl SeriesTrait for SeriesWrap<$ca> {
224            #[cfg(feature = "rolling_window")]
225            fn rolling_map(
226                &self,
227                _f: &dyn Fn(&Series) -> PolarsResult<Series>,
228                _options: RollingOptionsFixedWindow,
229            ) -> PolarsResult<Series> {
230                ChunkRollApply::rolling_map(&self.0, _f, _options).map(|ca| ca.into_series())
231            }
232
233            fn rename(&mut self, name: PlSmallStr) {
234                self.0.rename(name);
235            }
236
237            fn chunk_lengths(&self) -> ChunkLenIter<'_> {
238                self.0.chunk_lengths()
239            }
240            fn name(&self) -> &PlSmallStr {
241                self.0.name()
242            }
243
244            fn chunks(&self) -> &Vec<ArrayRef> {
245                self.0.chunks()
246            }
247            unsafe fn chunks_mut(&mut self) -> &mut Vec<ArrayRef> {
248                self.0.chunks_mut()
249            }
250            fn shrink_to_fit(&mut self) {
251                self.0.shrink_to_fit()
252            }
253
254            fn slice(&self, offset: i64, length: usize) -> Series {
255                self.0.slice(offset, length).into_series()
256            }
257
258            fn split_at(&self, offset: i64) -> (Series, Series) {
259                let (a, b) = self.0.split_at(offset);
260                (a.into_series(), b.into_series())
261            }
262
263            fn append(&mut self, other: &Series) -> PolarsResult<()> {
264                polars_ensure!(self.0.dtype() == other.dtype(), append);
265                self.0.append(other.as_ref().as_ref())?;
266                Ok(())
267            }
268            fn append_owned(&mut self, other: Series) -> PolarsResult<()> {
269                polars_ensure!(self.0.dtype() == other.dtype(), append);
270                self.0.append_owned(other.take_inner())
271            }
272
273            fn extend(&mut self, other: &Series) -> PolarsResult<()> {
274                polars_ensure!(self.0.dtype() == other.dtype(), extend);
275                self.0.extend(other.as_ref().as_ref())?;
276                Ok(())
277            }
278
279            fn filter(&self, filter: &BooleanChunked) -> PolarsResult<Series> {
280                ChunkFilter::filter(&self.0, filter).map(|ca| ca.into_series())
281            }
282
283            fn _sum_as_f64(&self) -> f64 {
284                self.0._sum_as_f64()
285            }
286
287            fn mean(&self) -> Option<f64> {
288                self.0.mean()
289            }
290
291            fn median(&self) -> Option<f64> {
292                self.0.median()
293            }
294
295            fn std(&self, ddof: u8) -> Option<f64> {
296                self.0.std(ddof)
297            }
298
299            fn var(&self, ddof: u8) -> Option<f64> {
300                self.0.var(ddof)
301            }
302
303            fn take(&self, indices: &IdxCa) -> PolarsResult<Series> {
304                Ok(self.0.take(indices)?.into_series())
305            }
306
307            unsafe fn take_unchecked(&self, indices: &IdxCa) -> Series {
308                self.0.take_unchecked(indices).into_series()
309            }
310
311            fn take_slice(&self, indices: &[IdxSize]) -> PolarsResult<Series> {
312                Ok(self.0.take(indices)?.into_series())
313            }
314
315            unsafe fn take_slice_unchecked(&self, indices: &[IdxSize]) -> Series {
316                self.0.take_unchecked(indices).into_series()
317            }
318
319            fn deposit(&self, validity: &Bitmap) -> Series {
320                self.0.deposit(validity).into_series()
321            }
322
323            fn len(&self) -> usize {
324                self.0.len()
325            }
326
327            fn rechunk(&self) -> Series {
328                self.0.rechunk().into_owned().into_series()
329            }
330
331            fn new_from_index(&self, index: usize, length: usize) -> Series {
332                ChunkExpandAtIndex::new_from_index(&self.0, index, length).into_series()
333            }
334
335            fn cast(&self, dtype: &DataType, options: CastOptions) -> PolarsResult<Series> {
336                self.0.cast_with_options(dtype, options)
337            }
338
339            #[inline]
340            unsafe fn get_unchecked(&self, index: usize) -> AnyValue<'_> {
341                self.0.get_any_value_unchecked(index)
342            }
343
344            fn sort_with(&self, options: SortOptions) -> PolarsResult<Series> {
345                Ok(ChunkSort::sort_with(&self.0, options).into_series())
346            }
347
348            fn arg_sort(&self, options: SortOptions) -> IdxCa {
349                ChunkSort::arg_sort(&self.0, options)
350            }
351
352            fn null_count(&self) -> usize {
353                self.0.null_count()
354            }
355
356            fn has_nulls(&self) -> bool {
357                self.0.has_nulls()
358            }
359
360            #[cfg(feature = "algorithm_group_by")]
361            fn unique(&self) -> PolarsResult<Series> {
362                ChunkUnique::unique(&self.0).map(|ca| ca.into_series())
363            }
364
365            #[cfg(feature = "algorithm_group_by")]
366            fn n_unique(&self) -> PolarsResult<usize> {
367                ChunkUnique::n_unique(&self.0)
368            }
369
370            #[cfg(feature = "algorithm_group_by")]
371            fn arg_unique(&self) -> PolarsResult<IdxCa> {
372                ChunkUnique::arg_unique(&self.0)
373            }
374
375            fn unique_id(&self) -> PolarsResult<(IdxSize, Vec<IdxSize>)> {
376                ChunkUnique::unique_id(&self.0)
377            }
378
379            fn is_null(&self) -> BooleanChunked {
380                self.0.is_null()
381            }
382
383            fn is_not_null(&self) -> BooleanChunked {
384                self.0.is_not_null()
385            }
386
387            fn reverse(&self) -> Series {
388                ChunkReverse::reverse(&self.0).into_series()
389            }
390
391            fn as_single_ptr(&mut self) -> PolarsResult<usize> {
392                self.0.as_single_ptr()
393            }
394
395            fn shift(&self, periods: i64) -> Series {
396                ChunkShift::shift(&self.0, periods).into_series()
397            }
398
399            fn sum_reduce(&self) -> PolarsResult<Scalar> {
400                Ok(ChunkAggSeries::sum_reduce(&self.0))
401            }
402            fn max_reduce(&self) -> PolarsResult<Scalar> {
403                Ok(ChunkAggSeries::max_reduce(&self.0))
404            }
405            fn min_reduce(&self) -> PolarsResult<Scalar> {
406                Ok(ChunkAggSeries::min_reduce(&self.0))
407            }
408            fn mean_reduce(&self) -> PolarsResult<Scalar> {
409                Ok(Scalar::new(DataType::Float64, self.mean().into()))
410            }
411            fn median_reduce(&self) -> PolarsResult<Scalar> {
412                Ok(QuantileAggSeries::median_reduce(&self.0))
413            }
414            fn var_reduce(&self, ddof: u8) -> PolarsResult<Scalar> {
415                Ok(VarAggSeries::var_reduce(&self.0, ddof))
416            }
417            fn std_reduce(&self, ddof: u8) -> PolarsResult<Scalar> {
418                Ok(VarAggSeries::std_reduce(&self.0, ddof))
419            }
420
421            fn quantile_reduce(
422                &self,
423                quantile: f64,
424                method: QuantileMethod,
425            ) -> PolarsResult<Scalar> {
426                QuantileAggSeries::quantile_reduce(&self.0, quantile, method)
427            }
428
429            fn quantiles_reduce(
430                &self,
431                quantiles: &[f64],
432                method: QuantileMethod,
433            ) -> PolarsResult<Scalar> {
434                QuantileAggSeries::quantiles_reduce(&self.0, quantiles, method)
435            }
436
437            #[cfg(feature = "bitwise")]
438            fn and_reduce(&self) -> PolarsResult<Scalar> {
439                let dt = <$pdt as PolarsDataType>::get_static_dtype();
440                let av = self.0.and_reduce().map_or(AnyValue::Null, Into::into);
441
442                Ok(Scalar::new(dt, av))
443            }
444
445            #[cfg(feature = "bitwise")]
446            fn or_reduce(&self) -> PolarsResult<Scalar> {
447                let dt = <$pdt as PolarsDataType>::get_static_dtype();
448                let av = self.0.or_reduce().map_or(AnyValue::Null, Into::into);
449
450                Ok(Scalar::new(dt, av))
451            }
452
453            #[cfg(feature = "bitwise")]
454            fn xor_reduce(&self) -> PolarsResult<Scalar> {
455                let dt = <$pdt as PolarsDataType>::get_static_dtype();
456                let av = self.0.xor_reduce().map_or(AnyValue::Null, Into::into);
457
458                Ok(Scalar::new(dt, av))
459            }
460
461            #[cfg(feature = "approx_unique")]
462            fn approx_n_unique(&self) -> PolarsResult<IdxSize> {
463                Ok(ChunkApproxNUnique::approx_n_unique(&self.0))
464            }
465
466            fn clone_inner(&self) -> Arc<dyn SeriesTrait> {
467                Arc::new(SeriesWrap(Clone::clone(&self.0)))
468            }
469
470            fn find_validity_mismatch(&self, other: &Series, idxs: &mut Vec<IdxSize>) {
471                self.0.find_validity_mismatch(other, idxs)
472            }
473
474            #[cfg(feature = "checked_arithmetic")]
475            fn checked_div(&self, rhs: &Series) -> PolarsResult<Series> {
476                self.0.checked_div(rhs)
477            }
478
479            fn as_any(&self) -> &dyn Any {
480                &self.0
481            }
482
483            fn as_any_mut(&mut self) -> &mut dyn Any {
484                &mut self.0
485            }
486
487            fn as_phys_any(&self) -> &dyn Any {
488                &self.0
489            }
490
491            fn as_arc_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
492                self as _
493            }
494        }
495    };
496}
497
498#[cfg(feature = "dtype-u8")]
499impl_dyn_series!(UInt8Chunked, UInt8Type);
500#[cfg(feature = "dtype-u16")]
501impl_dyn_series!(UInt16Chunked, UInt16Type);
502impl_dyn_series!(UInt32Chunked, UInt32Type);
503impl_dyn_series!(UInt64Chunked, UInt64Type);
504#[cfg(feature = "dtype-u128")]
505impl_dyn_series!(UInt128Chunked, UInt128Type);
506#[cfg(feature = "dtype-i8")]
507impl_dyn_series!(Int8Chunked, Int8Type);
508#[cfg(feature = "dtype-i16")]
509impl_dyn_series!(Int16Chunked, Int16Type);
510impl_dyn_series!(Int32Chunked, Int32Type);
511impl_dyn_series!(Int64Chunked, Int64Type);
512#[cfg(feature = "dtype-i128")]
513impl_dyn_series!(Int128Chunked, Int128Type);
514
515impl<T: PolarsNumericType> private::PrivateSeriesNumeric for SeriesWrap<ChunkedArray<T>> {
516    fn bit_repr(&self) -> Option<BitRepr> {
517        Some(self.0.to_bit_repr())
518    }
519}
520
521impl private::PrivateSeriesNumeric for SeriesWrap<StringChunked> {
522    fn bit_repr(&self) -> Option<BitRepr> {
523        None
524    }
525}
526impl private::PrivateSeriesNumeric for SeriesWrap<BinaryChunked> {
527    fn bit_repr(&self) -> Option<BitRepr> {
528        None
529    }
530}
531impl private::PrivateSeriesNumeric for SeriesWrap<BinaryOffsetChunked> {
532    fn bit_repr(&self) -> Option<BitRepr> {
533        None
534    }
535}
536impl private::PrivateSeriesNumeric for SeriesWrap<ListChunked> {
537    fn bit_repr(&self) -> Option<BitRepr> {
538        None
539    }
540}
541#[cfg(feature = "dtype-array")]
542impl private::PrivateSeriesNumeric for SeriesWrap<ArrayChunked> {
543    fn bit_repr(&self) -> Option<BitRepr> {
544        None
545    }
546}
547impl private::PrivateSeriesNumeric for SeriesWrap<BooleanChunked> {
548    fn bit_repr(&self) -> Option<BitRepr> {
549        let repr = self
550            .0
551            .cast_with_options(&DataType::UInt32, CastOptions::NonStrict)
552            .unwrap()
553            .u32()
554            .unwrap()
555            .clone();
556
557        Some(BitRepr::U32(repr))
558    }
559}