Path: blob/main/crates/polars-arrow/src/compute/arity_assign.rs
6939 views
//! Defines generics suitable to perform operations to [`PrimitiveArray`] in-place.12use either::Either;34use super::utils::check_same_len;5use crate::array::PrimitiveArray;6use crate::types::NativeType;78/// Applies an unary function to a [`PrimitiveArray`], optionally in-place.9///10/// # Implementation11/// This function tries to apply the function directly to the values of the array.12/// If that region is shared, this function creates a new region and writes to it.13///14/// # Panics15/// This function panics iff16/// * the arrays have a different length.17/// * the function itself panics.18#[inline]19pub fn unary<I, F>(array: &mut PrimitiveArray<I>, op: F)20where21I: NativeType,22F: Fn(I) -> I,23{24if let Some(values) = array.get_mut_values() {25// mutate in place26values.iter_mut().for_each(|l| *l = op(*l));27} else {28// alloc and write to new region29let values = array.values().iter().map(|l| op(*l)).collect::<Vec<_>>();30array.set_values(values.into());31}32}3334/// Applies a binary function to two [`PrimitiveArray`]s, optionally in-place, returning35/// a new [`PrimitiveArray`].36///37/// # Implementation38/// This function tries to apply the function directly to the values of the array.39/// If that region is shared, this function creates a new region and writes to it.40/// # Panics41/// This function panics iff42/// * the arrays have a different length.43/// * the function itself panics.44#[inline]45pub fn binary<T, D, F>(lhs: &mut PrimitiveArray<T>, rhs: &PrimitiveArray<D>, op: F)46where47T: NativeType,48D: NativeType,49F: Fn(T, D) -> T,50{51check_same_len(lhs, rhs).unwrap();5253// both for the validity and for the values54// we branch to check if we can mutate in place55// if we can, great that is fastest.56// if we cannot, we allocate a new buffer and assign values to that57// new buffer, that is benchmarked to be ~2x faster than first memcpy and assign in place58// for the validity bits it can be much faster as we might need to iterate all bits if the59// bitmap has an offset.60if let Some(rhs) = rhs.validity() {61if lhs.validity().is_none() {62lhs.set_validity(Some(rhs.clone()));63} else {64lhs.apply_validity(|bitmap| {65match bitmap.into_mut() {66Either::Left(immutable) => {67// alloc new region68&immutable & rhs69},70Either::Right(mutable) => {71// mutate in place72(mutable & rhs).into()73},74}75});76}77};7879if let Some(values) = lhs.get_mut_values() {80// mutate values in place81values82.iter_mut()83.zip(rhs.values().iter())84.for_each(|(l, r)| *l = op(*l, *r));85} else {86// alloc new region87let values = lhs88.values()89.iter()90.zip(rhs.values().iter())91.map(|(l, r)| op(*l, *r))92.collect::<Vec<_>>();93lhs.set_values(values.into());94}95}969798