Path: blob/main/crates/polars-compute/src/bitwise/mod.rs
6939 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;67pub trait BitwiseKernel {8type Scalar;910fn count_ones(&self) -> PrimitiveArray<u32>;11fn count_zeros(&self) -> PrimitiveArray<u32>;1213fn leading_ones(&self) -> PrimitiveArray<u32>;14fn leading_zeros(&self) -> PrimitiveArray<u32>;1516fn trailing_ones(&self) -> PrimitiveArray<u32>;17fn trailing_zeros(&self) -> PrimitiveArray<u32>;1819fn reduce_and(&self) -> Option<Self::Scalar>;20fn reduce_or(&self) -> Option<Self::Scalar>;21fn reduce_xor(&self) -> Option<Self::Scalar>;2223fn bit_and(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar;24fn bit_or(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar;25fn bit_xor(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar;26}2728macro_rules! impl_bitwise_kernel {29($(($T:ty, $to_bits:expr, $from_bits:expr)),+ $(,)?) => {30$(31impl BitwiseKernel for PrimitiveArray<$T> {32type Scalar = $T;3334#[inline(never)]35fn count_ones(&self) -> PrimitiveArray<u32> {36PrimitiveArray::new(37ArrowDataType::UInt32,38self.values_iter()39.map(|&v| $to_bits(v).count_ones())40.collect_trusted::<Vec<_>>()41.into(),42self.validity().cloned(),43)44}4546#[inline(never)]47fn count_zeros(&self) -> PrimitiveArray<u32> {48PrimitiveArray::new(49ArrowDataType::UInt32,50self.values_iter()51.map(|&v| $to_bits(v).count_zeros())52.collect_trusted::<Vec<_>>()53.into(),54self.validity().cloned(),55)56}5758#[inline(never)]59fn leading_ones(&self) -> PrimitiveArray<u32> {60PrimitiveArray::new(61ArrowDataType::UInt32,62self.values_iter()63.map(|&v| $to_bits(v).leading_ones())64.collect_trusted::<Vec<_>>()65.into(),66self.validity().cloned(),67)68}6970#[inline(never)]71fn leading_zeros(&self) -> PrimitiveArray<u32> {72PrimitiveArray::new(73ArrowDataType::UInt32,74self.values_iter()75.map(|&v| $to_bits(v).leading_zeros())76.collect_trusted::<Vec<_>>()77.into(),78self.validity().cloned(),79)80}8182#[inline(never)]83fn trailing_ones(&self) -> PrimitiveArray<u32> {84PrimitiveArray::new(85ArrowDataType::UInt32,86self.values_iter()87.map(|&v| $to_bits(v).trailing_ones())88.collect_trusted::<Vec<_>>()89.into(),90self.validity().cloned(),91)92}9394#[inline(never)]95fn trailing_zeros(&self) -> PrimitiveArray<u32> {96PrimitiveArray::new(97ArrowDataType::UInt32,98self.values().iter()99.map(|&v| $to_bits(v).trailing_zeros())100.collect_trusted::<Vec<_>>()101.into(),102self.validity().cloned(),103)104}105106#[inline(never)]107fn reduce_and(&self) -> Option<Self::Scalar> {108if !self.has_nulls() {109self.values_iter().copied().map($to_bits).reduce(|a, b| a & b).map($from_bits)110} else {111self.non_null_values_iter().map($to_bits).reduce(|a, b| a & b).map($from_bits)112}113}114115#[inline(never)]116fn reduce_or(&self) -> Option<Self::Scalar> {117if !self.has_nulls() {118self.values_iter().copied().map($to_bits).reduce(|a, b| a | b).map($from_bits)119} else {120self.non_null_values_iter().map($to_bits).reduce(|a, b| a | b).map($from_bits)121}122}123124#[inline(never)]125fn reduce_xor(&self) -> Option<Self::Scalar> {126if !self.has_nulls() {127self.values_iter().copied().map($to_bits).reduce(|a, b| a ^ b).map($from_bits)128} else {129self.non_null_values_iter().map($to_bits).reduce(|a, b| a ^ b).map($from_bits)130}131}132133fn bit_and(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar {134$from_bits($to_bits(lhs) & $to_bits(rhs))135}136fn bit_or(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar {137$from_bits($to_bits(lhs) | $to_bits(rhs))138}139fn bit_xor(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar {140$from_bits($to_bits(lhs) ^ $to_bits(rhs))141}142}143)+144};145}146147impl_bitwise_kernel! {148(i8, identity, identity),149(i16, identity, identity),150(i32, identity, identity),151(i64, identity, identity),152(u8, identity, identity),153(u16, identity, identity),154(u32, identity, identity),155(u64, identity, identity),156(f32, f32::to_bits, f32::from_bits),157(f64, f64::to_bits, f64::from_bits),158}159160#[cfg(feature = "dtype-i128")]161impl_bitwise_kernel! {162(i128, identity, identity),163}164165impl BitwiseKernel for BooleanArray {166type Scalar = bool;167168#[inline(never)]169fn count_ones(&self) -> PrimitiveArray<u32> {170PrimitiveArray::new(171ArrowDataType::UInt32,172self.values_iter()173.map(u32::from)174.collect_trusted::<Vec<_>>()175.into(),176self.validity().cloned(),177)178}179180#[inline(never)]181fn count_zeros(&self) -> PrimitiveArray<u32> {182PrimitiveArray::new(183ArrowDataType::UInt32,184self.values_iter()185.map(|v| u32::from(!v))186.collect_trusted::<Vec<_>>()187.into(),188self.validity().cloned(),189)190}191192#[inline(always)]193fn leading_ones(&self) -> PrimitiveArray<u32> {194self.count_ones()195}196197#[inline(always)]198fn leading_zeros(&self) -> PrimitiveArray<u32> {199self.count_zeros()200}201202#[inline(always)]203fn trailing_ones(&self) -> PrimitiveArray<u32> {204self.count_ones()205}206207#[inline(always)]208fn trailing_zeros(&self) -> PrimitiveArray<u32> {209self.count_zeros()210}211212fn reduce_and(&self) -> Option<Self::Scalar> {213if self.len() == self.null_count() {214None215} else if !self.has_nulls() {216Some(self.values().unset_bits() == 0)217} else {218let false_found = binary_fold(219self.values(),220self.validity().unwrap(),221|lhs, rhs| (!lhs & rhs) != 0,222false,223|a, b| a || b,224);225Some(!false_found)226}227}228229fn reduce_or(&self) -> Option<Self::Scalar> {230if self.len() == self.null_count() {231None232} else if !self.has_nulls() {233Some(self.values().set_bits() > 0)234} else {235Some(intersects_with(self.values(), self.validity().unwrap()))236}237}238239fn reduce_xor(&self) -> Option<Self::Scalar> {240if self.len() == self.null_count() {241None242} else if !self.has_nulls() {243Some(self.values().set_bits() % 2 == 1)244} else {245let nonnull_parity = binary_fold(246self.values(),247self.validity().unwrap(),248|lhs, rhs| lhs & rhs,2490,250|a, b| a ^ b,251);252Some(nonnull_parity.count_ones() % 2 == 1)253}254}255256fn bit_and(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar {257lhs & rhs258}259fn bit_or(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar {260lhs | rhs261}262fn bit_xor(lhs: Self::Scalar, rhs: Self::Scalar) -> Self::Scalar {263lhs ^ rhs264}265}266267268