use crate::array::{Array, BooleanArray};
use crate::bitmap::{Bitmap, binary, quaternary, ternary, unary};
use crate::datatypes::ArrowDataType;
use crate::scalar::BooleanScalar;
pub fn or(lhs: &BooleanArray, rhs: &BooleanArray) -> BooleanArray {
assert_eq!(
lhs.len(),
rhs.len(),
"lhs and rhs must have the same length"
);
let lhs_values = lhs.values();
let rhs_values = rhs.values();
let lhs_validity = lhs.validity();
let rhs_validity = rhs.validity();
let validity = match (lhs_validity, rhs_validity) {
(Some(lhs_validity), Some(rhs_validity)) => {
Some(quaternary(
lhs_values,
rhs_values,
lhs_validity,
rhs_validity,
|lhs, rhs, lhs_v, rhs_v| {
(lhs & lhs_v) |
(rhs & rhs_v) |
(!lhs & lhs_v) & (!rhs & rhs_v)
},
))
},
(Some(lhs_validity), None) => {
Some(ternary(
lhs_values,
rhs_values,
lhs_validity,
|lhs, rhs, lhs_v| {
(lhs & lhs_v) |
rhs |
(!lhs & lhs_v) & !rhs
},
))
},
(None, Some(rhs_validity)) => {
Some(ternary(
lhs_values,
rhs_values,
rhs_validity,
|lhs, rhs, rhs_v| {
lhs |
(rhs & rhs_v) |
!lhs & (!rhs & rhs_v)
},
))
},
(None, None) => None,
};
BooleanArray::new(ArrowDataType::Boolean, lhs_values | rhs_values, validity)
}
pub fn and(lhs: &BooleanArray, rhs: &BooleanArray) -> BooleanArray {
assert_eq!(
lhs.len(),
rhs.len(),
"lhs and rhs must have the same length"
);
let lhs_values = lhs.values();
let rhs_values = rhs.values();
let lhs_validity = lhs.validity();
let rhs_validity = rhs.validity();
let validity = match (lhs_validity, rhs_validity) {
(Some(lhs_validity), Some(rhs_validity)) => {
Some(quaternary(
lhs_values,
rhs_values,
lhs_validity,
rhs_validity,
|lhs, rhs, lhs_v, rhs_v| {
(!rhs & rhs_v) |
(!lhs & lhs_v) |
(lhs & lhs_v) & (rhs & rhs_v)
},
))
},
(Some(lhs_validity), None) => {
Some(ternary(
lhs_values,
rhs_values,
lhs_validity,
|lhs, rhs, lhs_v| {
!rhs |
(!lhs & lhs_v) |
(lhs & lhs_v) & rhs
},
))
},
(None, Some(rhs_validity)) => {
Some(ternary(
lhs_values,
rhs_values,
rhs_validity,
|lhs, rhs, rhs_v| {
(!rhs & rhs_v) |
!lhs |
lhs & (rhs & rhs_v)
},
))
},
(None, None) => None,
};
BooleanArray::new(ArrowDataType::Boolean, lhs_values & rhs_values, validity)
}
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()),
None,
),
Some(false) => array.clone(),
None => {
let values = array.values();
let validity = match array.validity() {
Some(validity) => binary(values, validity, |value, validity| validity & value),
None => unary(values, |value| value),
};
BooleanArray::new(ArrowDataType::Boolean, values.clone(), Some(validity))
},
}
}
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, None)
},
None => {
let values = array.values();
let validity = match array.validity() {
Some(validity) => binary(values, validity, |value, validity| validity & !value),
None => unary(values, |value| !value),
};
BooleanArray::new(
ArrowDataType::Boolean,
array.values().clone(),
Some(validity),
)
},
}
}
pub fn any(array: &BooleanArray) -> Option<bool> {
if array.is_empty() {
Some(false)
} else if let Some(validity) = array.validity()
&& validity.unset_bits() > 0
{
if array.values().intersects_with(validity) {
Some(true)
} else {
None
}
} else {
let vals = array.values();
Some(vals.unset_bits() != vals.len())
}
}
pub fn all(array: &BooleanArray) -> Option<bool> {
if array.is_empty() {
Some(true)
} else if array.null_count() > 0 {
if array.into_iter().any(|v| v == Some(false)) {
Some(false)
} else {
None
}
} else {
let vals = array.values();
Some(vals.unset_bits() == 0)
}
}