use num_traits::AsPrimitive;
use vortex_buffer::BitBuffer;
use vortex_buffer::BitBufferMut;
use vortex_error::VortexResult;
use vortex_error::vortex_ensure;
use super::super::Interleave;
use super::super::InterleaveArrayExt;
use crate::array::Array;
use crate::arrays::Bool;
use crate::arrays::BoolArray;
use crate::arrays::Primitive;
use crate::arrays::bool::BoolArrayExt;
use crate::executor::ExecutionCtx;
use crate::executor::ExecutionResult;
use crate::match_each_unsigned_integer_ptype;
use crate::require_child;
pub(super) fn execute(
array: Array<Interleave>,
_ctx: &mut ExecutionCtx,
) -> VortexResult<ExecutionResult> {
let num_values = array.num_values();
let mut array = array;
array = require_child!(array, array.array_indices(), 0 => Primitive);
array = require_child!(array, array.row_indices(), 1 => Primitive);
for i in 0..num_values {
array = require_child!(array, array.value(i), i + 2 => Bool);
}
let mut value_bits = Vec::with_capacity(num_values);
for i in 0..num_values {
value_bits.push(array.value(i).as_::<Bool>().to_bit_buffer());
}
let validity = array.as_ref().validity()?;
let array_indices = array.array_indices().as_::<Primitive>();
let row_indices = array.row_indices().as_::<Primitive>();
let values = match_each_unsigned_integer_ptype!(array_indices.ptype(), |A| {
match_each_unsigned_integer_ptype!(row_indices.ptype(), |R| {
gather(
&value_bits,
array_indices.as_slice::<A>(),
row_indices.as_slice::<R>(),
)?
})
});
Ok(ExecutionResult::done(BoolArray::try_new(
values.freeze(),
validity,
)?))
}
fn gather<A: AsPrimitive<usize>, R: AsPrimitive<usize>>(
value_bits: &[BitBuffer],
branches: &[A],
rows: &[R],
) -> VortexResult<BitBufferMut> {
let len = validate_selectors(value_bits, branches, rows)?;
Ok(unsafe { gather_bits(len, value_bits, branches, rows) })
}
fn validate_selectors<A: AsPrimitive<usize>, R: AsPrimitive<usize>>(
value_bits: &[BitBuffer],
branches: &[A],
rows: &[R],
) -> VortexResult<usize> {
let len = branches.len();
vortex_ensure!(
rows.len() == len,
"interleave selectors differ in length: array_indices {len}, row_indices {}",
rows.len()
);
for i in 0..len {
let branch = branches[i].as_();
vortex_ensure!(
branch < value_bits.len(),
"interleave array index out of bounds"
);
vortex_ensure!(
rows[i].as_() < value_bits[branch].len(),
"interleave row index out of bounds"
);
}
Ok(len)
}
unsafe fn gather_bits<A: AsPrimitive<usize>, R: AsPrimitive<usize>>(
len: usize,
bits: &[BitBuffer],
branches: &[A],
rows: &[R],
) -> BitBufferMut {
BitBufferMut::collect_bool(len, |i| unsafe {
bits.get_unchecked(branches.get_unchecked(i).as_())
.value_unchecked(rows.get_unchecked(i).as_())
})
}