use arrow::array::*;
use arrow::compute::kernels::bitwise::{
bitwise_and, bitwise_and_scalar, bitwise_or, bitwise_or_scalar, bitwise_shift_left,
bitwise_shift_left_scalar, bitwise_shift_right, bitwise_shift_right_scalar,
bitwise_xor, bitwise_xor_scalar,
};
use arrow::datatypes::DataType;
use datafusion_common::internal_err;
use datafusion_common::{DataFusionError, Result, ScalarValue};
use std::sync::Arc;
macro_rules! call_bitwise_kernel {
($LEFT:expr, $RIGHT:expr, $KERNEL:expr, $ARRAY_TYPE:ident) => {{
let left = $LEFT.as_any().downcast_ref::<$ARRAY_TYPE>().unwrap();
let right = $RIGHT.as_any().downcast_ref::<$ARRAY_TYPE>().unwrap();
let result: $ARRAY_TYPE = $KERNEL(left, right)?;
Ok(Arc::new(result))
}};
}
macro_rules! create_dyn_kernel {
($FUNC:ident, $KERNEL:ident) => {
pub(crate) fn $FUNC(left: ArrayRef, right: ArrayRef) -> Result<ArrayRef> {
match &left.data_type() {
DataType::Int8 => {
call_bitwise_kernel!(left, right, $KERNEL, Int8Array)
}
DataType::Int16 => {
call_bitwise_kernel!(left, right, $KERNEL, Int16Array)
}
DataType::Int32 => {
call_bitwise_kernel!(left, right, $KERNEL, Int32Array)
}
DataType::Int64 => {
call_bitwise_kernel!(left, right, $KERNEL, Int64Array)
}
DataType::UInt8 => {
call_bitwise_kernel!(left, right, $KERNEL, UInt8Array)
}
DataType::UInt16 => {
call_bitwise_kernel!(left, right, $KERNEL, UInt16Array)
}
DataType::UInt32 => {
call_bitwise_kernel!(left, right, $KERNEL, UInt32Array)
}
DataType::UInt64 => {
call_bitwise_kernel!(left, right, $KERNEL, UInt64Array)
}
other => internal_err!(
"Data type {:?} not supported for binary operation '{}' on dyn arrays",
other,
stringify!($KERNEL)
),
}
}
};
}
create_dyn_kernel!(bitwise_or_dyn, bitwise_or);
create_dyn_kernel!(bitwise_xor_dyn, bitwise_xor);
create_dyn_kernel!(bitwise_and_dyn, bitwise_and);
create_dyn_kernel!(bitwise_shift_right_dyn, bitwise_shift_right);
create_dyn_kernel!(bitwise_shift_left_dyn, bitwise_shift_left);
macro_rules! call_bitwise_scalar_kernel {
($LEFT:expr, $RIGHT:expr, $KERNEL:ident, $ARRAY_TYPE:ident, $TYPE:ty) => {{
let len = $LEFT.len();
let array = $LEFT.as_any().downcast_ref::<$ARRAY_TYPE>().unwrap();
let scalar = $RIGHT;
if scalar.is_null() {
Ok(new_null_array(array.data_type(), len))
} else {
let scalar: $TYPE = scalar.try_into().unwrap();
let result: $ARRAY_TYPE = $KERNEL(array, scalar).unwrap();
Ok(Arc::new(result) as ArrayRef)
}
}};
}
macro_rules! create_dyn_scalar_kernel {
($FUNC:ident, $KERNEL:ident) => {
pub(crate) fn $FUNC(array: &dyn Array, scalar: ScalarValue) -> Option<Result<ArrayRef>> {
let result = match array.data_type() {
DataType::Int8 => call_bitwise_scalar_kernel!(array, scalar, $KERNEL, Int8Array, i8),
DataType::Int16 => call_bitwise_scalar_kernel!(array, scalar, $KERNEL, Int16Array, i16),
DataType::Int32 => call_bitwise_scalar_kernel!(array, scalar, $KERNEL, Int32Array, i32),
DataType::Int64 => call_bitwise_scalar_kernel!(array, scalar, $KERNEL, Int64Array, i64),
DataType::UInt8 => call_bitwise_scalar_kernel!(array, scalar, $KERNEL, UInt8Array, u8),
DataType::UInt16 => call_bitwise_scalar_kernel!(array, scalar, $KERNEL, UInt16Array, u16),
DataType::UInt32 => call_bitwise_scalar_kernel!(array, scalar, $KERNEL, UInt32Array, u32),
DataType::UInt64 => call_bitwise_scalar_kernel!(array, scalar, $KERNEL, UInt64Array, u64),
other => internal_err!(
"Data type {:?} not supported for binary operation '{}' on dyn arrays",
other,
stringify!($KERNEL)
),
};
Some(result)
}
};
}
create_dyn_scalar_kernel!(bitwise_and_dyn_scalar, bitwise_and_scalar);
create_dyn_scalar_kernel!(bitwise_or_dyn_scalar, bitwise_or_scalar);
create_dyn_scalar_kernel!(bitwise_xor_dyn_scalar, bitwise_xor_scalar);
create_dyn_scalar_kernel!(bitwise_shift_right_dyn_scalar, bitwise_shift_right_scalar);
create_dyn_scalar_kernel!(bitwise_shift_left_dyn_scalar, bitwise_shift_left_scalar);