Path: blob/main/crates/polars-compute/src/bitwise/mod.rs
8420 views
use std::convert::identity;12use arrow::array::{Array, BooleanArray, PrimitiveArray};3use arrow::bitmap::{binary_fold, intersects_with};4use arrow::datatypes::ArrowDataType;5use arrow::legacy::utils::CustomIterTools;6use polars_utils::float16::pf16;78pub trait BitwiseKernel {9type Scalar;1011fn count_ones(&self) -> PrimitiveArray<u32>;12fn count_zeros(&self) -> PrimitiveArray<u32>;1314fn leading_ones(&self) -> PrimitiveArray<u32>;15fn leading_zeros(&self) -> PrimitiveArray<u32>;1617fn trailing_ones(&self) -> PrimitiveArray<u32>;18fn trailing_zeros(&self) -> PrimitiveArray<u32>;1920fn reduce_and(&self) -> Option<Self::Scalar>;21fn reduce_or(&self) -> Option<Self::Scalar>;22fn reduce_xor(&self) -> Option<Self::Scalar>;2324fn bit_and(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar;25fn bit_or(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar;26fn bit_xor(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar;27}2829macro_rules! impl_bitwise_kernel {30($(($T:ty, $to_bits:expr, $from_bits:expr)),+ $(,)?) => {31$(32impl BitwiseKernel for PrimitiveArray<$T> {33type Scalar = $T;3435#[inline(never)]36fn count_ones(&self) -> PrimitiveArray<u32> {37PrimitiveArray::new(38ArrowDataType::UInt32,39self.values_iter()40.map(|&v| $to_bits(v).count_ones())41.collect_trusted::<Vec<_>>()42.into(),43self.validity().cloned(),44)45}4647#[inline(never)]48fn count_zeros(&self) -> PrimitiveArray<u32> {49PrimitiveArray::new(50ArrowDataType::UInt32,51self.values_iter()52.map(|&v| $to_bits(v).count_zeros())53.collect_trusted::<Vec<_>>()54.into(),55self.validity().cloned(),56)57}5859#[inline(never)]60fn leading_ones(&self) -> PrimitiveArray<u32> {61PrimitiveArray::new(62ArrowDataType::UInt32,63self.values_iter()64.map(|&v| $to_bits(v).leading_ones())65.collect_trusted::<Vec<_>>()66.into(),67self.validity().cloned(),68)69}7071#[inline(never)]72fn leading_zeros(&self) -> PrimitiveArray<u32> {73PrimitiveArray::new(74ArrowDataType::UInt32,75self.values_iter()76.map(|&v| $to_bits(v).leading_zeros())77.collect_trusted::<Vec<_>>()78.into(),79self.validity().cloned(),80)81}8283#[inline(never)]84fn trailing_ones(&self) -> PrimitiveArray<u32> {85PrimitiveArray::new(86ArrowDataType::UInt32,87self.values_iter()88.map(|&v| $to_bits(v).trailing_ones())89.collect_trusted::<Vec<_>>()90.into(),91self.validity().cloned(),92)93}9495#[inline(never)]96fn trailing_zeros(&self) -> PrimitiveArray<u32> {97PrimitiveArray::new(98ArrowDataType::UInt32,99self.values().iter()100.map(|&v| $to_bits(v).trailing_zeros())101.collect_trusted::<Vec<_>>()102.into(),103self.validity().cloned(),104)105}106107#[inline(never)]108fn reduce_and(&self) -> Option<Self::Scalar> {109if !self.has_nulls() {110self.values_iter().copied().map($to_bits).reduce(|a, b| a & b).map($from_bits)111} else {112self.non_null_values_iter().map($to_bits).reduce(|a, b| a & b).map($from_bits)113}114}115116#[inline(never)]117fn reduce_or(&self) -> Option<Self::Scalar> {118if !self.has_nulls() {119self.values_iter().copied().map($to_bits).reduce(|a, b| a | b).map($from_bits)120} else {121self.non_null_values_iter().map($to_bits).reduce(|a, b| a | b).map($from_bits)122}123}124125#[inline(never)]126fn reduce_xor(&self) -> Option<Self::Scalar> {127if !self.has_nulls() {128self.values_iter().copied().map($to_bits).reduce(|a, b| a ^ b).map($from_bits)129} else {130self.non_null_values_iter().map($to_bits).reduce(|a, b| a ^ b).map($from_bits)131}132}133134fn bit_and(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar {135$from_bits($to_bits(lhs) & $to_bits(rhs))136}137fn bit_or(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar {138$from_bits($to_bits(lhs) | $to_bits(rhs))139}140fn bit_xor(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar {141$from_bits($to_bits(lhs) ^ $to_bits(rhs))142}143}144)+145};146}147148impl_bitwise_kernel! {149(i8, identity, identity),150(i16, identity, identity),151(i32, identity, identity),152(i64, identity, identity),153(u8, identity, identity),154(u16, identity, identity),155(u32, identity, identity),156(u64, identity, identity),157(pf16, pf16::to_bits, pf16::from_bits),158(f32, f32::to_bits, f32::from_bits),159(f64, f64::to_bits, f64::from_bits),160}161162#[cfg(feature = "dtype-u128")]163impl_bitwise_kernel! {164(u128, identity, identity),165}166167#[cfg(feature = "dtype-i128")]168impl_bitwise_kernel! {169(i128, identity, identity),170}171172impl BitwiseKernel for BooleanArray {173type Scalar = bool;174175#[inline(never)]176fn count_ones(&self) -> PrimitiveArray<u32> {177PrimitiveArray::new(178ArrowDataType::UInt32,179self.values_iter()180.map(u32::from)181.collect_trusted::<Vec<_>>()182.into(),183self.validity().cloned(),184)185}186187#[inline(never)]188fn count_zeros(&self) -> PrimitiveArray<u32> {189PrimitiveArray::new(190ArrowDataType::UInt32,191self.values_iter()192.map(|v| u32::from(!v))193.collect_trusted::<Vec<_>>()194.into(),195self.validity().cloned(),196)197}198199#[inline(always)]200fn leading_ones(&self) -> PrimitiveArray<u32> {201self.count_ones()202}203204#[inline(always)]205fn leading_zeros(&self) -> PrimitiveArray<u32> {206self.count_zeros()207}208209#[inline(always)]210fn trailing_ones(&self) -> PrimitiveArray<u32> {211self.count_ones()212}213214#[inline(always)]215fn trailing_zeros(&self) -> PrimitiveArray<u32> {216self.count_zeros()217}218219fn reduce_and(&self) -> Option<Self::Scalar> {220if self.len() == self.null_count() {221None222} else if !self.has_nulls() {223Some(self.values().unset_bits() == 0)224} else {225let false_found = binary_fold(226self.values(),227self.validity().unwrap(),228|lhs, rhs| (!lhs & rhs) != 0,229false,230|a, b| a || b,231);232Some(!false_found)233}234}235236fn reduce_or(&self) -> Option<Self::Scalar> {237if self.len() == self.null_count() {238None239} else if !self.has_nulls() {240Some(self.values().set_bits() > 0)241} else {242Some(intersects_with(self.values(), self.validity().unwrap()))243}244}245246fn reduce_xor(&self) -> Option<Self::Scalar> {247if self.len() == self.null_count() {248None249} else if !self.has_nulls() {250Some(self.values().set_bits() % 2 == 1)251} else {252let nonnull_parity = binary_fold(253self.values(),254self.validity().unwrap(),255|lhs, rhs| lhs & rhs,2560,257|a, b| a ^ b,258);259Some(nonnull_parity.count_ones() % 2 == 1)260}261}262263fn bit_and(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar {264lhs & rhs265}266fn bit_or(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar {267lhs | rhs268}269fn bit_xor(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar {270lhs ^ rhs271}272}273274275