use super::utils::combine_validities_and;
use crate::array::{Array, BooleanArray};
use crate::bitmap::Bitmap;
use crate::datatypes::ArrowDataType;
use crate::scalar::BooleanScalar;
fn assert_lengths(lhs: &BooleanArray, rhs: &BooleanArray) {
assert_eq!(
lhs.len(),
rhs.len(),
"lhs and rhs must have the same length"
);
}
pub(crate) fn binary_boolean_kernel<F>(
lhs: &BooleanArray,
rhs: &BooleanArray,
op: F,
) -> BooleanArray
where
F: Fn(&Bitmap, &Bitmap) -> Bitmap,
{
assert_lengths(lhs, rhs);
let validity = combine_validities_and(lhs.validity(), rhs.validity());
let left_buffer = lhs.values();
let right_buffer = rhs.values();
let values = op(left_buffer, right_buffer);
BooleanArray::new(ArrowDataType::Boolean, values, validity)
}
pub fn and(lhs: &BooleanArray, rhs: &BooleanArray) -> BooleanArray {
if lhs.null_count() == 0 && rhs.null_count() == 0 {
let left_buffer = lhs.values();
let right_buffer = rhs.values();
match (left_buffer.unset_bits(), right_buffer.unset_bits()) {
(0, 0) => {
assert_lengths(lhs, rhs);
return lhs.clone();
},
(l, _) if l == lhs.len() => {
assert_lengths(lhs, rhs);
return lhs.clone();
},
(_, r) if r == rhs.len() => {
assert_lengths(lhs, rhs);
return rhs.clone();
},
_ => {},
}
}
binary_boolean_kernel(lhs, rhs, |lhs, rhs| lhs & rhs)
}
pub fn or(lhs: &BooleanArray, rhs: &BooleanArray) -> BooleanArray {
if lhs.null_count() == 0 && rhs.null_count() == 0 {
let left_buffer = lhs.values();
let right_buffer = rhs.values();
match (left_buffer.unset_bits(), right_buffer.unset_bits()) {
(0, _) => {
assert_lengths(lhs, rhs);
return lhs.clone();
},
(_, 0) => {
assert_lengths(lhs, rhs);
return rhs.clone();
},
(l, r) if l == lhs.len() && r == rhs.len() => {
assert_lengths(lhs, rhs);
return rhs.clone();
},
_ => {},
}
}
binary_boolean_kernel(lhs, rhs, |lhs, rhs| lhs | rhs)
}
pub fn not(array: &BooleanArray) -> BooleanArray {
let values = !array.values();
let validity = array.validity().cloned();
BooleanArray::new(ArrowDataType::Boolean, values, validity)
}
pub fn is_null(input: &dyn Array) -> BooleanArray {
let len = input.len();
let values = match input.validity() {
None => Bitmap::new_zeroed(len),
Some(buffer) => !buffer,
};
BooleanArray::new(ArrowDataType::Boolean, values, None)
}
pub fn is_not_null(input: &dyn Array) -> BooleanArray {
let values = match input.validity() {
None => Bitmap::new_with_value(true, input.len()),
Some(buffer) => buffer.clone(),
};
BooleanArray::new(ArrowDataType::Boolean, values, None)
}
pub fn and_scalar(array: &BooleanArray, scalar: &BooleanScalar) -> BooleanArray {
match scalar.value() {
Some(true) => array.clone(),
Some(false) => {
let values = Bitmap::new_zeroed(array.len());
BooleanArray::new(ArrowDataType::Boolean, values, array.validity().cloned())
},
None => BooleanArray::new_null(ArrowDataType::Boolean, array.len()),
}
}
pub fn or_scalar(array: &BooleanArray, scalar: &BooleanScalar) -> BooleanArray {
match scalar.value() {
Some(true) => BooleanArray::new(
ArrowDataType::Boolean,
Bitmap::new_with_value(true, array.len()),
array.validity().cloned(),
),
Some(false) => array.clone(),
None => BooleanArray::new_null(ArrowDataType::Boolean, array.len()),
}
}
pub fn any(array: &BooleanArray) -> bool {
if array.is_empty() {
false
} else if array.null_count() > 0 {
array.into_iter().any(|v| v == Some(true))
} else {
let vals = array.values();
vals.unset_bits() != vals.len()
}
}
pub fn all(array: &BooleanArray) -> bool {
if array.is_empty() {
true
} else if array.null_count() > 0 {
!array.into_iter().any(|v| v == Some(false))
} else {
let vals = array.values();
vals.unset_bits() == 0
}
}