Path: blob/main/crates/polars-arrow/src/legacy/kernels/take_agg/mod.rs
6940 views
#![allow(unsafe_op_in_unsafe_fn)]1//! kernels that combine take and aggregations.2mod boolean;3mod var;45pub use boolean::*;6use num_traits::{NumCast, ToPrimitive};7use polars_utils::IdxSize;8pub use var::*;910use crate::array::{Array, BinaryViewArray, BooleanArray, PrimitiveArray};11use crate::types::NativeType;1213/// Take kernel for single chunk without nulls and an iterator as index.14/// # Safety15/// caller must ensure iterators indexes are in bounds16#[inline]17pub unsafe fn take_agg_no_null_primitive_iter_unchecked<18T: NativeType + ToPrimitive,19TOut: NumCast + NativeType,20I: IntoIterator<Item = usize>,21F: Fn(TOut, TOut) -> TOut,22>(23arr: &PrimitiveArray<T>,24indices: I,25f: F,26) -> Option<TOut> {27debug_assert!(arr.null_count() == 0);28let array_values = arr.values().as_slice();2930indices31.into_iter()32.map(|idx| TOut::from(*array_values.get_unchecked(idx)).unwrap_unchecked())33.reduce(f)34}3536/// Take kernel for single chunk and an iterator as index.37/// # Safety38/// caller must ensure iterators indexes are in bounds39#[inline]40pub unsafe fn take_agg_primitive_iter_unchecked<41T: NativeType,42I: IntoIterator<Item = usize>,43F: Fn(T, T) -> T,44>(45arr: &PrimitiveArray<T>,46indices: I,47f: F,48) -> Option<T> {49let array_values = arr.values().as_slice();50let validity = arr.validity().unwrap();5152indices53.into_iter()54.filter(|&idx| validity.get_bit_unchecked(idx))55.map(|idx| *array_values.get_unchecked(idx))56.reduce(f)57}5859/// Take kernel for single chunk and an iterator as index.60/// # Safety61/// caller must ensure iterators indexes are in bounds62#[inline]63pub unsafe fn take_agg_primitive_iter_unchecked_count_nulls<64T: NativeType + ToPrimitive,65TOut: NumCast + NativeType,66I: IntoIterator<Item = usize>,67F: Fn(TOut, TOut) -> TOut,68>(69arr: &PrimitiveArray<T>,70indices: I,71f: F,72init: TOut,73len: IdxSize,74) -> Option<(TOut, IdxSize)> {75let array_values = arr.values().as_slice();76let validity = arr.validity().expect("null buffer should be there");7778let mut null_count = 0 as IdxSize;79let out = indices.into_iter().fold(init, |acc, idx| {80if validity.get_bit_unchecked(idx) {81f(82acc,83NumCast::from(*array_values.get_unchecked(idx)).unwrap_unchecked(),84)85} else {86null_count += 1;87acc88}89});90if null_count == len {91None92} else {93Some((out, null_count))94}95}9697/// Take kernel for single chunk and an iterator as index.98/// # Safety99/// caller must ensure iterators indexes are in bounds100#[inline]101pub unsafe fn take_agg_bin_iter_unchecked<102'a,103I: IntoIterator<Item = usize>,104F: Fn(&'a [u8], &'a [u8]) -> &'a [u8],105>(106arr: &'a BinaryViewArray,107indices: I,108f: F,109len: IdxSize,110) -> Option<&'a [u8]> {111let mut null_count = 0 as IdxSize;112let validity = arr.validity().unwrap();113114let out = indices115.into_iter()116.map(|idx| {117if validity.get_bit_unchecked(idx) {118Some(arr.value_unchecked(idx))119} else {120None121}122})123.reduce(|acc, opt_val| match (acc, opt_val) {124(Some(acc), Some(str_val)) => Some(f(acc, str_val)),125(_, None) => {126null_count += 1;127acc128},129(None, Some(str_val)) => Some(str_val),130});131if null_count == len {132None133} else {134out.flatten()135}136}137138/// Take kernel for single chunk and an iterator as index.139/// # Safety140/// caller must ensure iterators indexes are in bounds141#[inline]142pub unsafe fn take_agg_bin_iter_unchecked_no_null<143'a,144I: IntoIterator<Item = usize>,145F: Fn(&'a [u8], &'a [u8]) -> &'a [u8],146>(147arr: &'a BinaryViewArray,148indices: I,149f: F,150) -> Option<&'a [u8]> {151indices152.into_iter()153.map(|idx| arr.value_unchecked(idx))154.reduce(|acc, str_val| f(acc, str_val))155}156157158