polars_core/chunked_array/
bitwise.rs1use std::ops::{BitAnd, BitOr, BitXor, Not};
2
3use arrow::compute;
4use arrow::compute::bitwise;
5use arrow::compute::utils::combine_validities_and;
6
7use super::*;
8use crate::chunked_array::arity::apply_binary_kernel_broadcast;
9
10impl<T> BitAnd for &ChunkedArray<T>
11where
12 T: PolarsIntegerType,
13 T::Native: BitAnd<Output = T::Native>,
14{
15 type Output = ChunkedArray<T>;
16
17 fn bitand(self, rhs: Self) -> Self::Output {
18 apply_binary_kernel_broadcast(
19 self,
20 rhs,
21 bitwise::and,
22 |l, r| bitwise::and_scalar(r, &l),
23 |l, r| bitwise::and_scalar(l, &r),
24 )
25 }
26}
27
28impl<T> BitOr for &ChunkedArray<T>
29where
30 T: PolarsIntegerType,
31 T::Native: BitOr<Output = T::Native>,
32{
33 type Output = ChunkedArray<T>;
34
35 fn bitor(self, rhs: Self) -> Self::Output {
36 apply_binary_kernel_broadcast(
37 self,
38 rhs,
39 bitwise::or,
40 |l, r| bitwise::or_scalar(r, &l),
41 |l, r| bitwise::or_scalar(l, &r),
42 )
43 }
44}
45
46impl<T> BitXor for &ChunkedArray<T>
47where
48 T: PolarsIntegerType,
49 T::Native: BitXor<Output = T::Native>,
50{
51 type Output = ChunkedArray<T>;
52
53 fn bitxor(self, rhs: Self) -> Self::Output {
54 apply_binary_kernel_broadcast(
55 self,
56 rhs,
57 bitwise::xor,
58 |l, r| bitwise::xor_scalar(r, &l),
59 |l, r| bitwise::xor_scalar(l, &r),
60 )
61 }
62}
63
64impl BitOr for &BooleanChunked {
65 type Output = BooleanChunked;
66
67 fn bitor(self, rhs: Self) -> Self::Output {
68 match (self.len(), rhs.len()) {
69 (1, 1) => {},
72 (1, _) => {
73 return match self.get(0) {
74 Some(true) => BooleanChunked::full(self.name().clone(), true, rhs.len()),
75 Some(false) => {
76 let mut rhs = rhs.clone();
77 rhs.rename(self.name().clone());
78 rhs
79 },
80 None => &self.new_from_index(0, rhs.len()) | rhs,
81 };
82 },
83 (_, 1) => {
84 return match rhs.get(0) {
85 Some(true) => BooleanChunked::full(self.name().clone(), true, self.len()),
86 Some(false) => self.clone(),
87 None => self | &rhs.new_from_index(0, self.len()),
88 };
89 },
90 _ => {},
91 }
92
93 arity::binary(self, rhs, compute::boolean_kleene::or)
94 }
95}
96
97impl BitOr for BooleanChunked {
98 type Output = BooleanChunked;
99
100 fn bitor(self, rhs: Self) -> Self::Output {
101 (&self).bitor(&rhs)
102 }
103}
104
105impl BitXor for &BooleanChunked {
106 type Output = BooleanChunked;
107
108 fn bitxor(self, rhs: Self) -> Self::Output {
109 match (self.len(), rhs.len()) {
110 (1, 1) => {},
113 (1, _) => {
114 return match self.get(0) {
115 Some(true) => {
116 let mut rhs = rhs.not();
117 rhs.rename(self.name().clone());
118 rhs
119 },
120 Some(false) => {
121 let mut rhs = rhs.clone();
122 rhs.rename(self.name().clone());
123 rhs
124 },
125 None => &self.new_from_index(0, rhs.len()) | rhs,
126 };
127 },
128 (_, 1) => {
129 return match rhs.get(0) {
130 Some(true) => self.not(),
131 Some(false) => self.clone(),
132 None => self | &rhs.new_from_index(0, self.len()),
133 };
134 },
135 _ => {},
136 }
137
138 arity::binary(self, rhs, |l_arr, r_arr| {
139 let validity = combine_validities_and(l_arr.validity(), r_arr.validity());
140 let values = l_arr.values() ^ r_arr.values();
141 BooleanArray::from_data_default(values, validity)
142 })
143 }
144}
145
146impl BitXor for BooleanChunked {
147 type Output = BooleanChunked;
148
149 fn bitxor(self, rhs: Self) -> Self::Output {
150 (&self).bitxor(&rhs)
151 }
152}
153
154impl BitAnd for &BooleanChunked {
155 type Output = BooleanChunked;
156
157 fn bitand(self, rhs: Self) -> Self::Output {
158 match (self.len(), rhs.len()) {
159 (1, 1) => {},
162 (1, _) => {
163 return match self.get(0) {
164 Some(true) => rhs.clone().with_name(self.name().clone()),
165 Some(false) => BooleanChunked::full(self.name().clone(), false, rhs.len()),
166 None => &self.new_from_index(0, rhs.len()) & rhs,
167 };
168 },
169 (_, 1) => {
170 return match rhs.get(0) {
171 Some(true) => self.clone(),
172 Some(false) => BooleanChunked::full(self.name().clone(), false, self.len()),
173 None => self & &rhs.new_from_index(0, self.len()),
174 };
175 },
176 _ => {},
177 }
178
179 arity::binary(self, rhs, compute::boolean_kleene::and)
180 }
181}
182
183impl BitAnd for BooleanChunked {
184 type Output = BooleanChunked;
185
186 fn bitand(self, rhs: Self) -> Self::Output {
187 (&self).bitand(&rhs)
188 }
189}
190
191#[cfg(test)]
192mod test {
193 use super::*;
194
195 #[test]
196 fn guard_so_issue_2494() {
197 let a = BooleanChunked::new(PlSmallStr::from_static("a"), [None]);
199 let b = BooleanChunked::new(PlSmallStr::from_static("b"), [None]);
200
201 assert_eq!((&a).bitand(&b).null_count(), 1);
202 assert_eq!((&a).bitor(&b).null_count(), 1);
203 assert_eq!((&a).bitxor(&b).null_count(), 1);
204 }
205}