use std::borrow::Borrow;
use std::ops::{BitAnd, BitOr};
use polars_error::{polars_ensure, PolarsResult};
use crate::array::Array;
use crate::bitmap::{and_not, push_bitchunk, ternary, Bitmap};
pub fn combine_validities_and3(
opt1: Option<&Bitmap>,
opt2: Option<&Bitmap>,
opt3: Option<&Bitmap>,
) -> Option<Bitmap> {
match (opt1, opt2, opt3) {
(Some(a), Some(b), Some(c)) => Some(ternary(a, b, c, |x, y, z| x & y & z)),
(Some(a), Some(b), None) => Some(a.bitand(b)),
(Some(a), None, Some(c)) => Some(a.bitand(c)),
(None, Some(b), Some(c)) => Some(b.bitand(c)),
(Some(a), None, None) => Some(a.clone()),
(None, Some(b), None) => Some(b.clone()),
(None, None, Some(c)) => Some(c.clone()),
(None, None, None) => None,
}
}
pub fn combine_validities_and(opt_l: Option<&Bitmap>, opt_r: Option<&Bitmap>) -> Option<Bitmap> {
match (opt_l, opt_r) {
(Some(l), Some(r)) => Some(l.bitand(r)),
(None, Some(r)) => Some(r.clone()),
(Some(l), None) => Some(l.clone()),
(None, None) => None,
}
}
pub fn combine_validities_or(opt_l: Option<&Bitmap>, opt_r: Option<&Bitmap>) -> Option<Bitmap> {
match (opt_l, opt_r) {
(Some(l), Some(r)) => Some(l.bitor(r)),
_ => None,
}
}
pub fn combine_validities_and_not(
opt_l: Option<&Bitmap>,
opt_r: Option<&Bitmap>,
) -> Option<Bitmap> {
match (opt_l, opt_r) {
(Some(l), Some(r)) => Some(and_not(l, r)),
(None, Some(r)) => Some(!r),
(Some(l), None) => Some(l.clone()),
(None, None) => None,
}
}
pub fn combine_validities_and_many<B: Borrow<Bitmap>>(bitmaps: &[Option<B>]) -> Option<Bitmap> {
let mut bitmaps = bitmaps
.iter()
.flatten()
.map(|b| b.borrow())
.collect::<Vec<_>>();
match bitmaps.len() {
0 => None,
1 => bitmaps.pop().cloned(),
2 => combine_validities_and(bitmaps.pop(), bitmaps.pop()),
3 => combine_validities_and3(bitmaps.pop(), bitmaps.pop(), bitmaps.pop()),
_ => {
let mut iterators = bitmaps
.iter()
.map(|v| v.fast_iter_u64())
.collect::<Vec<_>>();
let mut buffer = Vec::with_capacity(iterators.first().unwrap().size_hint().0 + 2);
'rows: loop {
let mut out = u64::MAX;
for iter in iterators.iter_mut() {
if let Some(v) = iter.next() {
out &= v
} else {
break 'rows;
}
}
push_bitchunk(&mut buffer, out);
}
let mut out = [u64::MAX, u64::MAX];
let mut len = 0;
for iter in iterators.into_iter() {
let (rem, rem_len) = iter.remainder();
len = rem_len;
for (out, rem) in out.iter_mut().zip(rem) {
*out &= rem;
}
}
push_bitchunk(&mut buffer, out[0]);
if len > 64 {
push_bitchunk(&mut buffer, out[1]);
}
let bitmap = Bitmap::from_u8_vec(buffer, bitmaps[0].len());
if bitmap.unset_bits() == bitmap.len() {
None
} else {
Some(bitmap)
}
},
}
}
#[inline]
pub fn check_same_len(lhs: &dyn Array, rhs: &dyn Array) -> PolarsResult<()> {
polars_ensure!(lhs.len() == rhs.len(), ComputeError:
"arrays must have the same length"
);
Ok(())
}