Path: blob/main/crates/polars-ops/src/chunked_array/array/min_max.rs
6939 views
use arrow::array::{Array, PrimitiveArray};1use polars_compute::min_max::MinMaxKernel;2use polars_core::prelude::*;3use polars_core::with_match_physical_numeric_polars_type;45fn array_agg<T, S, F1, F2>(6values: &PrimitiveArray<T>,7width: usize,8slice_agg: F1,9arr_agg: F2,10) -> PrimitiveArray<S>11where12T: NumericNative,13S: NumericNative,14F1: Fn(&[T]) -> Option<S>,15F2: Fn(&PrimitiveArray<T>) -> Option<S>,16{17if values.null_count() == 0 {18let values = values.values().as_slice();19values20.chunks_exact(width)21.map(|sl| slice_agg(sl).unwrap())22.collect_arr()23} else {24(0..values.len())25.step_by(width)26.map(|start| {27// SAFETY: This value array from a FixedSizeListArray,28// we can ensure that `start + width` will not out out range29let sliced = unsafe { values.clone().sliced_unchecked(start, width) };30arr_agg(&sliced)31})32.collect_arr()33}34}3536pub(super) enum AggType {37Min,38Max,39}4041fn agg_min<T>(values: &PrimitiveArray<T>, width: usize) -> PrimitiveArray<T>42where43T: NumericNative,44PrimitiveArray<T>: for<'a> MinMaxKernel<Scalar<'a> = T>,45[T]: for<'a> MinMaxKernel<Scalar<'a> = T>,46{47array_agg(48values,49width,50MinMaxKernel::min_ignore_nan_kernel,51MinMaxKernel::min_ignore_nan_kernel,52)53}5455fn agg_max<T>(values: &PrimitiveArray<T>, width: usize) -> PrimitiveArray<T>56where57T: NumericNative,58PrimitiveArray<T>: for<'a> MinMaxKernel<Scalar<'a> = T>,59[T]: for<'a> MinMaxKernel<Scalar<'a> = T>,60{61array_agg(62values,63width,64MinMaxKernel::max_ignore_nan_kernel,65MinMaxKernel::max_ignore_nan_kernel,66)67}6869pub(super) fn array_dispatch(70name: PlSmallStr,71values: &Series,72width: usize,73agg_type: AggType,74) -> Series {75let chunks: Vec<ArrayRef> = with_match_physical_numeric_polars_type!(values.dtype(), |$T| {76let ca: &ChunkedArray<$T> = values.as_ref().as_ref().as_ref();77ca.downcast_iter().map(|arr| {78match agg_type {79AggType::Min => Box::new(agg_min(arr, width)) as ArrayRef,80AggType::Max => Box::new(agg_max(arr, width)) as ArrayRef,81}82}).collect()83});84Series::try_from((name, chunks)).unwrap()85}868788