Path: blob/main/crates/polars-core/src/chunked_array/bitwise.rs
6940 views
use std::ops::{BitAnd, BitOr, BitXor, Not};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 {108match (self.len(), rhs.len()) {109// make sure that we fall through if both are equal unit lengths110// otherwise we stackoverflow111(1, 1) => {},112(1, _) => {113return match self.get(0) {114Some(true) => {115let mut rhs = rhs.not();116rhs.rename(self.name().clone());117rhs118},119Some(false) => {120let mut rhs = rhs.clone();121rhs.rename(self.name().clone());122rhs123},124None => &self.new_from_index(0, rhs.len()) | rhs,125};126},127(_, 1) => {128return match rhs.get(0) {129Some(true) => self.not(),130Some(false) => self.clone(),131None => self | &rhs.new_from_index(0, self.len()),132};133},134_ => {},135}136137arity::binary(self, rhs, |l_arr, r_arr| {138let validity = combine_validities_and(l_arr.validity(), r_arr.validity());139let values = l_arr.values() ^ r_arr.values();140BooleanArray::from_data_default(values, validity)141})142}143}144145impl BitXor for BooleanChunked {146type Output = BooleanChunked;147148fn bitxor(self, rhs: Self) -> Self::Output {149(&self).bitxor(&rhs)150}151}152153impl BitAnd for &BooleanChunked {154type Output = BooleanChunked;155156fn bitand(self, rhs: Self) -> Self::Output {157match (self.len(), rhs.len()) {158// make sure that we fall through if both are equal unit lengths159// otherwise we stackoverflow160(1, 1) => {},161(1, _) => {162return match self.get(0) {163Some(true) => rhs.clone().with_name(self.name().clone()),164Some(false) => BooleanChunked::full(self.name().clone(), false, rhs.len()),165None => &self.new_from_index(0, rhs.len()) & rhs,166};167},168(_, 1) => {169return match rhs.get(0) {170Some(true) => self.clone(),171Some(false) => BooleanChunked::full(self.name().clone(), false, self.len()),172None => self & &rhs.new_from_index(0, self.len()),173};174},175_ => {},176}177178arity::binary(self, rhs, compute::boolean_kleene::and)179}180}181182impl BitAnd for BooleanChunked {183type Output = BooleanChunked;184185fn bitand(self, rhs: Self) -> Self::Output {186(&self).bitand(&rhs)187}188}189190#[cfg(test)]191mod test {192use super::*;193194#[test]195fn guard_so_issue_2494() {196// this cause a stack overflow197let a = BooleanChunked::new(PlSmallStr::from_static("a"), [None]);198let b = BooleanChunked::new(PlSmallStr::from_static("b"), [None]);199200assert_eq!((&a).bitand(&b).null_count(), 1);201assert_eq!((&a).bitor(&b).null_count(), 1);202assert_eq!((&a).bitxor(&b).null_count(), 1);203}204}205206207