Path: blob/main/crates/polars-core/src/chunked_array/bitwise.rs
8406 views
use std::ops::{BitAnd, BitOr, BitXor};12use arrow::compute;3use arrow::compute::bitwise;4use arrow::compute::utils::combine_validities_and;56use super::*;7use crate::chunked_array::arity::apply_binary_kernel_broadcast;89impl<T> BitAnd for &ChunkedArray<T>10where11T: PolarsIntegerType,12T::Native: BitAnd<Output = T::Native>,13{14type Output = ChunkedArray<T>;1516fn bitand(self, rhs: Self) -> Self::Output {17apply_binary_kernel_broadcast(18self,19rhs,20bitwise::and,21|l, r| bitwise::and_scalar(r, &l),22|l, r| bitwise::and_scalar(l, &r),23)24}25}2627impl<T> BitOr for &ChunkedArray<T>28where29T: PolarsIntegerType,30T::Native: BitOr<Output = T::Native>,31{32type Output = ChunkedArray<T>;3334fn bitor(self, rhs: Self) -> Self::Output {35apply_binary_kernel_broadcast(36self,37rhs,38bitwise::or,39|l, r| bitwise::or_scalar(r, &l),40|l, r| bitwise::or_scalar(l, &r),41)42}43}4445impl<T> BitXor for &ChunkedArray<T>46where47T: PolarsIntegerType,48T::Native: BitXor<Output = T::Native>,49{50type Output = ChunkedArray<T>;5152fn bitxor(self, rhs: Self) -> Self::Output {53apply_binary_kernel_broadcast(54self,55rhs,56bitwise::xor,57|l, r| bitwise::xor_scalar(r, &l),58|l, r| bitwise::xor_scalar(l, &r),59)60}61}6263impl BitOr for &BooleanChunked {64type Output = BooleanChunked;6566fn bitor(self, rhs: Self) -> Self::Output {67match (self.len(), rhs.len()) {68// make sure that we fall through if both are equal unit lengths69// otherwise we stackoverflow70(1, 1) => {},71(1, _) => {72return match self.get(0) {73Some(true) => BooleanChunked::full(self.name().clone(), true, rhs.len()),74Some(false) => {75let mut rhs = rhs.clone();76rhs.rename(self.name().clone());77rhs78},79None => &self.new_from_index(0, rhs.len()) | rhs,80};81},82(_, 1) => {83return match rhs.get(0) {84Some(true) => BooleanChunked::full(self.name().clone(), true, self.len()),85Some(false) => self.clone(),86None => self | &rhs.new_from_index(0, self.len()),87};88},89_ => {},90}9192arity::binary(self, rhs, compute::boolean_kleene::or)93}94}9596impl BitOr for BooleanChunked {97type Output = BooleanChunked;9899fn bitor(self, rhs: Self) -> Self::Output {100(&self).bitor(&rhs)101}102}103104impl BitXor for &BooleanChunked {105type Output = BooleanChunked;106107fn bitxor(self, rhs: Self) -> Self::Output {108if let Some((scalar, other_ca)) = match (self.len(), rhs.len()) {109// make sure that we fall through if both are equal unit lengths110// otherwise we stackoverflow111(1, 1) => None,112(1, _) => Some((self.get(0), rhs)),113(_, 1) => Some((rhs.get(0), self)),114_ => None,115} {116match scalar {117Some(false) => other_ca.clone(),118None => BooleanChunked::full_null(self.name().clone(), other_ca.len()),119Some(true) => !other_ca,120}121} else {122arity::binary(self, rhs, |l_arr, r_arr| {123let validity = combine_validities_and(l_arr.validity(), r_arr.validity());124let values = l_arr.values() ^ r_arr.values();125BooleanArray::from_data_default(values, validity)126})127}128}129}130131impl BitXor for BooleanChunked {132type Output = BooleanChunked;133134fn bitxor(self, rhs: Self) -> Self::Output {135(&self).bitxor(&rhs)136}137}138139impl BitAnd for &BooleanChunked {140type Output = BooleanChunked;141142fn bitand(self, rhs: Self) -> Self::Output {143match (self.len(), rhs.len()) {144// make sure that we fall through if both are equal unit lengths145// otherwise we stackoverflow146(1, 1) => {},147(1, _) => {148return match self.get(0) {149Some(true) => rhs.clone().with_name(self.name().clone()),150Some(false) => BooleanChunked::full(self.name().clone(), false, rhs.len()),151None => &self.new_from_index(0, rhs.len()) & rhs,152};153},154(_, 1) => {155return match rhs.get(0) {156Some(true) => self.clone(),157Some(false) => BooleanChunked::full(self.name().clone(), false, self.len()),158None => self & &rhs.new_from_index(0, self.len()),159};160},161_ => {},162}163164arity::binary(self, rhs, compute::boolean_kleene::and)165}166}167168impl BitAnd for BooleanChunked {169type Output = BooleanChunked;170171fn bitand(self, rhs: Self) -> Self::Output {172(&self).bitand(&rhs)173}174}175176#[cfg(test)]177mod test {178use super::*;179180#[test]181fn guard_so_issue_2494() {182// this cause a stack overflow183let a = BooleanChunked::new(PlSmallStr::from_static("a"), [None]);184let b = BooleanChunked::new(PlSmallStr::from_static("b"), [None]);185186assert_eq!((&a).bitand(&b).null_count(), 1);187assert_eq!((&a).bitor(&b).null_count(), 1);188assert_eq!((&a).bitxor(&b).null_count(), 1);189}190}191192193