Skip to content

Commit c4ac758

Browse files
authored
feat: support bitwise shift left/right with scalars (#4159)
1 parent 547cb80 commit c4ac758

File tree

1 file changed

+72
-19
lines changed

1 file changed

+72
-19
lines changed

arrow-arith/src/bitwise.rs

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use arrow_schema::ArrowError;
2222
use num::traits::{WrappingShl, WrappingShr};
2323
use std::ops::{BitAnd, BitOr, BitXor, Not};
2424

25-
// The helper function for bitwise operation with two array
25+
/// The helper function for bitwise operation with two array
2626
fn bitwise_op<T, F>(
2727
left: &PrimitiveArray<T>,
2828
right: &PrimitiveArray<T>,
@@ -74,6 +74,38 @@ where
7474
bitwise_op(left, right, |a, b| a ^ b)
7575
}
7676

77+
/// Perform bitwise `left << right` operation on two arrays. If either left or right value is null
78+
/// then the result is also null.
79+
pub fn bitwise_shift_left<T>(
80+
left: &PrimitiveArray<T>,
81+
right: &PrimitiveArray<T>,
82+
) -> Result<PrimitiveArray<T>, ArrowError>
83+
where
84+
T: ArrowNumericType,
85+
T::Native: WrappingShl<Output = T::Native>,
86+
{
87+
bitwise_op(left, right, |a, b| {
88+
let b = b.as_usize();
89+
a.wrapping_shl(b as u32)
90+
})
91+
}
92+
93+
/// Perform bitwise `left >> right` operation on two arrays. If either left or right value is null
94+
/// then the result is also null.
95+
pub fn bitwise_shift_right<T>(
96+
left: &PrimitiveArray<T>,
97+
right: &PrimitiveArray<T>,
98+
) -> Result<PrimitiveArray<T>, ArrowError>
99+
where
100+
T: ArrowNumericType,
101+
T::Native: WrappingShr<Output = T::Native>,
102+
{
103+
bitwise_op(left, right, |a, b| {
104+
let b = b.as_usize();
105+
a.wrapping_shr(b as u32)
106+
})
107+
}
108+
77109
/// Perform `!array` operation on array. If array value is null
78110
/// then the result is also null.
79111
pub fn bitwise_not<T>(array: &PrimitiveArray<T>) -> Result<PrimitiveArray<T>, ArrowError>
@@ -123,36 +155,36 @@ where
123155
Ok(unary(array, |value| value ^ scalar))
124156
}
125157

126-
/// Perform bitwise 'left << right' operation on two arrays. If either left or right value is null
127-
/// then the result is also null.
128-
pub fn bitwise_shift_left<T>(
129-
left: &PrimitiveArray<T>,
130-
right: &PrimitiveArray<T>,
158+
/// Perform bitwise `left << right` every value in an array with the scalar. If any value in the array is null then the
159+
/// result is also null.
160+
pub fn bitwise_shift_left_scalar<T>(
161+
array: &PrimitiveArray<T>,
162+
scalar: T::Native,
131163
) -> Result<PrimitiveArray<T>, ArrowError>
132164
where
133165
T: ArrowNumericType,
134166
T::Native: WrappingShl<Output = T::Native>,
135167
{
136-
bitwise_op(left, right, |a, b| {
137-
let b = b.as_usize();
138-
a.wrapping_shl(b as u32)
139-
})
168+
Ok(unary(array, |value| {
169+
let scalar = scalar.as_usize();
170+
value.wrapping_shl(scalar as u32)
171+
}))
140172
}
141173

142-
/// Perform bitwise 'left >> right' operation on two arrays. If either left or right value is null
143-
/// then the result is also null.
144-
pub fn bitwise_shift_right<T>(
145-
left: &PrimitiveArray<T>,
146-
right: &PrimitiveArray<T>,
174+
/// Perform bitwise `left >> right` every value in an array with the scalar. If any value in the array is null then the
175+
/// result is also null.
176+
pub fn bitwise_shift_right_scalar<T>(
177+
array: &PrimitiveArray<T>,
178+
scalar: T::Native,
147179
) -> Result<PrimitiveArray<T>, ArrowError>
148180
where
149181
T: ArrowNumericType,
150182
T::Native: WrappingShr<Output = T::Native>,
151183
{
152-
bitwise_op(left, right, |a, b| {
153-
let b = b.as_usize();
154-
a.wrapping_shr(b as u32)
155-
})
184+
Ok(unary(array, |value| {
185+
let scalar = scalar.as_usize();
186+
value.wrapping_shr(scalar as u32)
187+
}))
156188
}
157189

158190
#[cfg(test)]
@@ -188,6 +220,16 @@ mod tests {
188220
assert_eq!(expected, result);
189221
}
190222

223+
#[test]
224+
fn test_bitwise_shift_left_scalar() {
225+
let left = UInt64Array::from(vec![Some(1), Some(2), None, Some(4), Some(8)]);
226+
let scalar = 2;
227+
let expected =
228+
UInt64Array::from(vec![Some(4), Some(8), None, Some(16), Some(32)]);
229+
let result = bitwise_shift_left_scalar(&left, scalar).unwrap();
230+
assert_eq!(expected, result);
231+
}
232+
191233
#[test]
192234
fn test_bitwise_shift_right() {
193235
let left =
@@ -199,6 +241,17 @@ mod tests {
199241
assert_eq!(expected, result);
200242
}
201243

244+
#[test]
245+
fn test_bitwise_shift_right_scalar() {
246+
let left =
247+
UInt64Array::from(vec![Some(32), Some(2048), None, Some(16384), Some(3)]);
248+
let scalar = 2;
249+
let expected =
250+
UInt64Array::from(vec![Some(8), Some(512), None, Some(4096), Some(0)]);
251+
let result = bitwise_shift_right_scalar(&left, scalar).unwrap();
252+
assert_eq!(expected, result);
253+
}
254+
202255
#[test]
203256
fn test_bitwise_and_array_scalar() {
204257
// unsigned value

0 commit comments

Comments
 (0)