use std::cmp::max;
use std::ops::Range;
use vortex_array::ArrayRef;
use vortex_array::ExecutionCtx;
use vortex_array::IntoArray;
use vortex_array::arrays::SliceKernel;
use vortex_error::VortexResult;
use crate::BitPackedArray;
use crate::BitPackedVTable;
impl SliceKernel for BitPackedVTable {
fn slice(
array: &BitPackedArray,
range: Range<usize>,
_ctx: &mut ExecutionCtx,
) -> VortexResult<Option<ArrayRef>> {
let offset_start = range.start + array.offset() as usize;
let offset_stop = range.end + array.offset() as usize;
let offset = offset_start % 1024;
let block_start = max(0, offset_start - offset);
let block_stop = offset_stop.div_ceil(1024) * 1024;
let encoded_start = (block_start / 8) * array.bit_width() as usize;
let encoded_stop = (block_stop / 8) * array.bit_width() as usize;
Ok(Some(unsafe {
BitPackedArray::new_unchecked(
array.packed().slice(encoded_start..encoded_stop),
array.dtype().clone(),
array.validity()?.slice(range.clone())?,
array
.patches()
.map(|p| p.slice(range.clone()))
.transpose()?
.flatten(),
array.bit_width(),
range.len(),
offset as u16,
)
.into_array()
}))
}
}
#[cfg(test)]
mod tests {
use std::sync::LazyLock;
use vortex_array::Array;
use vortex_array::IntoArray;
use vortex_array::VortexSessionExecute;
use vortex_array::arrays::SliceArray;
use vortex_array::session::ArraySession;
use vortex_array::vtable::VTable;
use vortex_error::VortexResult;
use vortex_session::VortexSession;
use crate::BitPackedVTable;
use crate::bitpack_compress::bitpack_encode;
static SESSION: LazyLock<VortexSession> =
LazyLock::new(|| VortexSession::empty().with::<ArraySession>());
#[test]
fn test_execute_parent_returns_bitpacked_slice() -> VortexResult<()> {
let values = vortex_array::arrays::PrimitiveArray::from_iter(0u32..2048);
let bitpacked = bitpack_encode(&values, 11, None)?;
let slice_array = SliceArray::new(bitpacked.clone().into_array(), 500..1500);
let mut ctx = SESSION.create_execution_ctx();
let reduced = <BitPackedVTable as VTable>::execute_parent(
&bitpacked,
&slice_array.into_array(),
0,
&mut ctx,
)?
.expect("expected slice kernel to execute");
assert!(reduced.is::<BitPackedVTable>());
let reduced_bp = reduced.as_::<BitPackedVTable>();
assert_eq!(reduced_bp.offset(), 500);
assert_eq!(reduced.len(), 1000);
Ok(())
}
}