use crate::datatypes::DataType;
use crate::error::{ArrowError, Result};
use crate::scalar::BooleanScalar;
use crate::{
array::BooleanArray,
bitmap::{binary, quaternary, ternary, unary, Bitmap, MutableBitmap},
};
pub fn or(lhs: &BooleanArray, rhs: &BooleanArray) -> Result<BooleanArray> {
if lhs.len() != rhs.len() {
return Err(ArrowError::InvalidArgumentError(
"Cannot perform bitwise operation on arrays of different length".to_string(),
));
}
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,
};
Ok(BooleanArray::from_data(
DataType::Boolean,
lhs_values | rhs_values,
validity,
))
}
pub fn and(lhs: &BooleanArray, rhs: &BooleanArray) -> Result<BooleanArray> {
if lhs.len() != rhs.len() {
return Err(ArrowError::InvalidArgumentError(
"Cannot perform bitwise operation on arrays of different length".to_string(),
));
}
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,
};
Ok(BooleanArray::from_data(
DataType::Boolean,
lhs_values & rhs_values,
validity,
))
}
pub fn or_scalar(array: &BooleanArray, scalar: &BooleanScalar) -> BooleanArray {
match scalar.value() {
Some(true) => {
let mut values = MutableBitmap::new();
values.extend_constant(array.len(), true);
BooleanArray::from_data(DataType::Boolean, values.into(), 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::from_data(DataType::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::from_data(DataType::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::from_data(DataType::Boolean, array.values().clone(), Some(validity))
}
}
}