use fastlanes::FastLanes;
use vortex_array::ArrayRef;
use vortex_array::DynArray;
use vortex_array::ExecutionCtx;
use vortex_array::IntoArray;
use vortex_array::arrays::PrimitiveArray;
use vortex_array::dtype::DType;
use vortex_array::dtype::PType;
use vortex_array::match_each_unsigned_integer_ptype;
use vortex_array::stats::ArrayStats;
use vortex_error::VortexResult;
use vortex_error::vortex_ensure;
pub mod delta_compress;
pub mod delta_decompress;
#[derive(Clone, Debug)]
pub struct DeltaArray {
pub(super) offset: usize,
pub(super) len: usize,
pub(super) dtype: DType,
pub(super) bases: ArrayRef,
pub(super) deltas: ArrayRef,
pub(super) stats_set: ArrayStats,
}
impl DeltaArray {
pub fn try_from_primitive_array(
array: &PrimitiveArray,
ctx: &mut ExecutionCtx,
) -> VortexResult<Self> {
let logical_len = array.len();
let (bases, deltas) = delta_compress::delta_compress(array, ctx)?;
Self::try_new(bases.into_array(), deltas.into_array(), 0, logical_len)
}
pub fn try_new(
bases: ArrayRef,
deltas: ArrayRef,
offset: usize,
len: usize,
) -> VortexResult<Self> {
vortex_ensure!(offset < 1024, "offset must be less than 1024: {offset}");
vortex_ensure!(
offset + len <= deltas.len(),
"offset + len, {offset} + {len}, must be less than or equal to the size of deltas: {}",
deltas.len()
);
vortex_ensure!(
bases.dtype().eq_ignore_nullability(deltas.dtype()),
"DeltaArray: bases and deltas must have the same dtype, got {} and {}",
bases.dtype(),
deltas.dtype()
);
vortex_ensure!(
bases.dtype().is_int(),
"DeltaArray: dtype must be an integer, got {}",
bases.dtype()
);
let lanes = lane_count(bases.dtype().as_ptype());
vortex_ensure!(
deltas.len().is_multiple_of(1024),
"deltas length ({}) must be a multiple of 1024",
deltas.len(),
);
vortex_ensure!(
bases.len().is_multiple_of(lanes),
"bases length ({}) must be a multiple of LANES ({lanes})",
bases.len(),
);
Ok(unsafe { Self::new_unchecked(bases, deltas, offset, len) })
}
pub(crate) unsafe fn new_unchecked(
bases: ArrayRef,
deltas: ArrayRef,
offset: usize,
logical_len: usize,
) -> Self {
Self {
offset,
len: logical_len,
dtype: bases.dtype().with_nullability(deltas.dtype().nullability()),
bases,
deltas,
stats_set: Default::default(),
}
}
#[inline]
pub fn bases(&self) -> &ArrayRef {
&self.bases
}
#[inline]
pub fn deltas(&self) -> &ArrayRef {
&self.deltas
}
pub(crate) fn lanes(&self) -> usize {
lane_count(self.dtype().as_ptype())
}
#[inline]
pub fn len(&self) -> usize {
self.len
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn dtype(&self) -> &DType {
&self.dtype
}
#[inline]
pub fn offset(&self) -> usize {
self.offset
}
pub(crate) fn bases_len(&self) -> usize {
self.bases.len()
}
pub(crate) fn deltas_len(&self) -> usize {
self.deltas.len()
}
pub(crate) fn stats_set(&self) -> &ArrayStats {
&self.stats_set
}
}
pub(crate) fn lane_count(ptype: PType) -> usize {
match_each_unsigned_integer_ptype!(ptype, |T| { T::LANES })
}