Skip to content

Commit 7e47fa6

Browse files
authored
support bitwise op: or,xor,not (#2716)
1 parent f56b573 commit 7e47fa6

File tree

1 file changed

+162
-5
lines changed

1 file changed

+162
-5
lines changed

arrow/src/compute/kernels/bitwise.rs

Lines changed: 162 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::array::PrimitiveArray;
1919
use crate::compute::{binary, unary};
2020
use crate::datatypes::ArrowNumericType;
2121
use crate::error::{ArrowError, Result};
22-
use std::ops::BitAnd;
22+
use std::ops::{BitAnd, BitOr, BitXor, Not};
2323

2424
// The helper function for bitwise operation with two array
2525
fn bitwise_op<T, F>(
@@ -52,7 +52,43 @@ where
5252
bitwise_op(left, right, |a, b| a & b)
5353
}
5454

55-
/// Perform bitwise and every value in an array with the scalar. If any value in the array is null then the
55+
/// Perform `left | right` operation on two arrays. If either left or right value is null
56+
/// then the result is also null.
57+
pub fn bitwise_or<T>(
58+
left: &PrimitiveArray<T>,
59+
right: &PrimitiveArray<T>,
60+
) -> Result<PrimitiveArray<T>>
61+
where
62+
T: ArrowNumericType,
63+
T::Native: BitOr<Output = T::Native>,
64+
{
65+
bitwise_op(left, right, |a, b| a | b)
66+
}
67+
68+
/// Perform `left ^ right` operation on two arrays. If either left or right value is null
69+
/// then the result is also null.
70+
pub fn bitwise_xor<T>(
71+
left: &PrimitiveArray<T>,
72+
right: &PrimitiveArray<T>,
73+
) -> Result<PrimitiveArray<T>>
74+
where
75+
T: ArrowNumericType,
76+
T::Native: BitXor<Output = T::Native>,
77+
{
78+
bitwise_op(left, right, |a, b| a ^ b)
79+
}
80+
81+
/// Perform `!array` operation on array. If array value is null
82+
/// then the result is also null.
83+
pub fn bitwise_not<T>(array: &PrimitiveArray<T>) -> Result<PrimitiveArray<T>>
84+
where
85+
T: ArrowNumericType,
86+
T::Native: Not<Output = T::Native>,
87+
{
88+
Ok(unary(array, |value| !value))
89+
}
90+
91+
/// Perform bitwise `and` every value in an array with the scalar. If any value in the array is null then the
5692
/// result is also null.
5793
pub fn bitwise_and_scalar<T>(
5894
array: &PrimitiveArray<T>,
@@ -65,10 +101,39 @@ where
65101
Ok(unary(array, |value| value & scalar))
66102
}
67103

104+
/// Perform bitwise `or` every value in an array with the scalar. If any value in the array is null then the
105+
/// result is also null.
106+
pub fn bitwise_or_scalar<T>(
107+
array: &PrimitiveArray<T>,
108+
scalar: T::Native,
109+
) -> Result<PrimitiveArray<T>>
110+
where
111+
T: ArrowNumericType,
112+
T::Native: BitOr<Output = T::Native>,
113+
{
114+
Ok(unary(array, |value| value | scalar))
115+
}
116+
117+
/// Perform bitwise `xor` every value in an array with the scalar. If any value in the array is null then the
118+
/// result is also null.
119+
pub fn bitwise_xor_scalar<T>(
120+
array: &PrimitiveArray<T>,
121+
scalar: T::Native,
122+
) -> Result<PrimitiveArray<T>>
123+
where
124+
T: ArrowNumericType,
125+
T::Native: BitXor<Output = T::Native>,
126+
{
127+
Ok(unary(array, |value| value ^ scalar))
128+
}
129+
68130
#[cfg(test)]
69131
mod tests {
70132
use crate::array::{Int32Array, UInt64Array};
71-
use crate::compute::kernels::bitwise::{bitwise_and, bitwise_and_scalar};
133+
use crate::compute::kernels::bitwise::{
134+
bitwise_and, bitwise_and_scalar, bitwise_not, bitwise_or, bitwise_or_scalar,
135+
bitwise_xor, bitwise_xor_scalar,
136+
};
72137
use crate::error::Result;
73138

74139
#[test]
@@ -82,7 +147,7 @@ mod tests {
82147

83148
// signed value
84149
let left = Int32Array::from(vec![Some(1), Some(2), None, Some(4)]);
85-
let right = Int32Array::from(vec![Some(5), Some(10), Some(8), Some(12)]);
150+
let right = Int32Array::from(vec![Some(5), Some(-10), Some(8), Some(12)]);
86151
let expected = Int32Array::from(vec![Some(1), Some(2), None, Some(4)]);
87152
let result = bitwise_and(&left, &right)?;
88153
assert_eq!(expected, result);
@@ -100,10 +165,102 @@ mod tests {
100165

101166
// signed value
102167
let left = Int32Array::from(vec![Some(1), Some(2), None, Some(4)]);
103-
let scalar = 20;
168+
let scalar = -20;
104169
let expected = Int32Array::from(vec![Some(0), Some(0), None, Some(4)]);
105170
let result = bitwise_and_scalar(&left, scalar)?;
106171
assert_eq!(expected, result);
107172
Ok(())
108173
}
174+
175+
#[test]
176+
fn test_bitwise_or_array() -> Result<()> {
177+
// unsigned value
178+
let left = UInt64Array::from(vec![Some(1), Some(2), None, Some(4)]);
179+
let right = UInt64Array::from(vec![Some(7), Some(5), Some(8), Some(13)]);
180+
let expected = UInt64Array::from(vec![Some(7), Some(7), None, Some(13)]);
181+
let result = bitwise_or(&left, &right)?;
182+
assert_eq!(expected, result);
183+
184+
// signed value
185+
let left = Int32Array::from(vec![Some(1), Some(2), None, Some(4)]);
186+
let right = Int32Array::from(vec![Some(-7), Some(-5), Some(8), Some(13)]);
187+
let expected = Int32Array::from(vec![Some(-7), Some(-5), None, Some(13)]);
188+
let result = bitwise_or(&left, &right)?;
189+
assert_eq!(expected, result);
190+
Ok(())
191+
}
192+
193+
#[test]
194+
fn test_bitwise_not_array() -> Result<()> {
195+
// unsigned value
196+
let array = UInt64Array::from(vec![Some(1), Some(2), None, Some(4)]);
197+
let expected = UInt64Array::from(vec![
198+
Some(18446744073709551614),
199+
Some(18446744073709551613),
200+
None,
201+
Some(18446744073709551611),
202+
]);
203+
let result = bitwise_not(&array)?;
204+
assert_eq!(expected, result);
205+
// signed value
206+
let array = Int32Array::from(vec![Some(1), Some(2), None, Some(4)]);
207+
let expected = Int32Array::from(vec![Some(-2), Some(-3), None, Some(-5)]);
208+
let result = bitwise_not(&array)?;
209+
assert_eq!(expected, result);
210+
Ok(())
211+
}
212+
213+
#[test]
214+
fn test_bitwise_or_array_scalar() -> Result<()> {
215+
// unsigned value
216+
let left = UInt64Array::from(vec![Some(15), Some(2), None, Some(4)]);
217+
let scalar = 7;
218+
let expected = UInt64Array::from(vec![Some(15), Some(7), None, Some(7)]);
219+
let result = bitwise_or_scalar(&left, scalar)?;
220+
assert_eq!(expected, result);
221+
222+
// signed value
223+
let left = Int32Array::from(vec![Some(1), Some(2), None, Some(4)]);
224+
let scalar = 20;
225+
let expected = Int32Array::from(vec![Some(21), Some(22), None, Some(20)]);
226+
let result = bitwise_or_scalar(&left, scalar)?;
227+
assert_eq!(expected, result);
228+
Ok(())
229+
}
230+
231+
#[test]
232+
fn test_bitwise_xor_array() -> Result<()> {
233+
// unsigned value
234+
let left = UInt64Array::from(vec![Some(1), Some(2), None, Some(4)]);
235+
let right = UInt64Array::from(vec![Some(7), Some(5), Some(8), Some(13)]);
236+
let expected = UInt64Array::from(vec![Some(6), Some(7), None, Some(9)]);
237+
let result = bitwise_xor(&left, &right)?;
238+
assert_eq!(expected, result);
239+
240+
// signed value
241+
let left = Int32Array::from(vec![Some(1), Some(2), None, Some(4)]);
242+
let right = Int32Array::from(vec![Some(-7), Some(5), Some(8), Some(-13)]);
243+
let expected = Int32Array::from(vec![Some(-8), Some(7), None, Some(-9)]);
244+
let result = bitwise_xor(&left, &right)?;
245+
assert_eq!(expected, result);
246+
Ok(())
247+
}
248+
249+
#[test]
250+
fn test_bitwise_xor_array_scalar() -> Result<()> {
251+
// unsigned value
252+
let left = UInt64Array::from(vec![Some(15), Some(2), None, Some(4)]);
253+
let scalar = 7;
254+
let expected = UInt64Array::from(vec![Some(8), Some(5), None, Some(3)]);
255+
let result = bitwise_xor_scalar(&left, scalar)?;
256+
assert_eq!(expected, result);
257+
258+
// signed value
259+
let left = Int32Array::from(vec![Some(1), Some(2), None, Some(4)]);
260+
let scalar = -20;
261+
let expected = Int32Array::from(vec![Some(-19), Some(-18), None, Some(-24)]);
262+
let result = bitwise_xor_scalar(&left, scalar)?;
263+
assert_eq!(expected, result);
264+
Ok(())
265+
}
109266
}

0 commit comments

Comments
 (0)