use vortex_array::ArrayId;
use vortex_array::ArrayRef;
use vortex_array::Canonical;
use vortex_array::ExecutionCtx;
use vortex_array::IntoArray;
use vortex_array::VTable;
use vortex_array::arrays::PrimitiveArray;
use vortex_array::arrays::primitive::PrimitiveArrayExt;
use vortex_compressor::scheme::AncestorExclusion;
use vortex_compressor::scheme::CompressionEstimate;
use vortex_compressor::scheme::DeferredEstimate;
use vortex_compressor::scheme::DescendantExclusion;
use vortex_compressor::scheme::EstimateVerdict;
use vortex_error::VortexResult;
use vortex_fastlanes::RLE;
use vortex_fastlanes::RLEArrayExt;
use vortex_fastlanes::RLEArraySlotsExt;
use super::RUN_LENGTH_THRESHOLD;
use crate::ArrayAndStats;
use crate::CascadingCompressor;
use crate::CompressorContext;
use crate::Scheme;
use crate::SchemeExt;
use crate::schemes::rle_ancestor_exclusions;
use crate::schemes::rle_descendant_exclusions;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct IntRLEScheme;
pub(crate) fn rle_compress(
scheme: &dyn Scheme,
compressor: &CascadingCompressor,
data: &ArrayAndStats,
compress_ctx: CompressorContext,
exec_ctx: &mut ExecutionCtx,
) -> VortexResult<ArrayRef> {
let rle_array = RLE::encode(data.array_as_primitive(), exec_ctx)?;
let rle_values_primitive = rle_array
.values()
.clone()
.execute::<PrimitiveArray>(exec_ctx)?;
let compressed_values = compressor.compress_child(
&rle_values_primitive.into_array(),
&compress_ctx,
scheme.id(),
0,
exec_ctx,
)?;
let rle_indices_primitive = rle_array
.indices()
.clone()
.execute::<PrimitiveArray>(exec_ctx)?
.narrow(exec_ctx)?;
let compressed_indices = compressor.compress_child(
&rle_indices_primitive.into_array(),
&compress_ctx,
scheme.id(),
1,
exec_ctx,
)?;
let rle_offsets_primitive = rle_array
.values_idx_offsets()
.clone()
.execute::<PrimitiveArray>(exec_ctx)?
.narrow(exec_ctx)?;
let compressed_offsets = compressor.compress_child(
&rle_offsets_primitive.into_array(),
&compress_ctx,
scheme.id(),
2,
exec_ctx,
)?;
unsafe {
Ok(RLE::new_unchecked(
compressed_values,
compressed_indices,
compressed_offsets,
rle_array.offset(),
rle_array.len(),
)
.into_array())
}
}
impl Scheme for IntRLEScheme {
fn scheme_name(&self) -> &'static str {
"vortex.int.rle"
}
fn matches(&self, canonical: &Canonical) -> bool {
canonical.dtype().is_int()
}
fn produced_encodings(&self) -> Vec<ArrayId> {
vec![RLE.id()]
}
fn num_children(&self) -> usize {
3
}
fn descendant_exclusions(&self) -> Vec<DescendantExclusion> {
rle_descendant_exclusions()
}
fn ancestor_exclusions(&self) -> Vec<AncestorExclusion> {
rle_ancestor_exclusions()
}
fn expected_compression_ratio(
&self,
data: &ArrayAndStats,
compress_ctx: CompressorContext,
exec_ctx: &mut ExecutionCtx,
) -> CompressionEstimate {
if compress_ctx.finished_cascading() {
return CompressionEstimate::Verdict(EstimateVerdict::Skip);
}
if data.integer_stats(exec_ctx).average_run_length() < RUN_LENGTH_THRESHOLD {
return CompressionEstimate::Verdict(EstimateVerdict::Skip);
}
CompressionEstimate::Deferred(DeferredEstimate::Sample)
}
fn compress(
&self,
compressor: &CascadingCompressor,
data: &ArrayAndStats,
compress_ctx: CompressorContext,
exec_ctx: &mut ExecutionCtx,
) -> VortexResult<ArrayRef> {
rle_compress(self, compressor, data, compress_ctx, exec_ctx)
}
}