Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-core/src/chunked_array/bitwise.rs
6940 views
1
use std::ops::{BitAnd, BitOr, BitXor, Not};
2
3
use arrow::compute;
4
use arrow::compute::bitwise;
5
use arrow::compute::utils::combine_validities_and;
6
7
use super::*;
8
use crate::chunked_array::arity::apply_binary_kernel_broadcast;
9
10
impl<T> BitAnd for &ChunkedArray<T>
11
where
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
28
impl<T> BitOr for &ChunkedArray<T>
29
where
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
46
impl<T> BitXor for &ChunkedArray<T>
47
where
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
64
impl BitOr for &BooleanChunked {
65
type Output = BooleanChunked;
66
67
fn bitor(self, rhs: Self) -> Self::Output {
68
match (self.len(), rhs.len()) {
69
// make sure that we fall through if both are equal unit lengths
70
// otherwise we stackoverflow
71
(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
97
impl BitOr for BooleanChunked {
98
type Output = BooleanChunked;
99
100
fn bitor(self, rhs: Self) -> Self::Output {
101
(&self).bitor(&rhs)
102
}
103
}
104
105
impl BitXor for &BooleanChunked {
106
type Output = BooleanChunked;
107
108
fn bitxor(self, rhs: Self) -> Self::Output {
109
match (self.len(), rhs.len()) {
110
// make sure that we fall through if both are equal unit lengths
111
// otherwise we stackoverflow
112
(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
146
impl BitXor for BooleanChunked {
147
type Output = BooleanChunked;
148
149
fn bitxor(self, rhs: Self) -> Self::Output {
150
(&self).bitxor(&rhs)
151
}
152
}
153
154
impl BitAnd for &BooleanChunked {
155
type Output = BooleanChunked;
156
157
fn bitand(self, rhs: Self) -> Self::Output {
158
match (self.len(), rhs.len()) {
159
// make sure that we fall through if both are equal unit lengths
160
// otherwise we stackoverflow
161
(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
183
impl 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)]
192
mod test {
193
use super::*;
194
195
#[test]
196
fn guard_so_issue_2494() {
197
// this cause a stack overflow
198
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
}
206
207