@@ -10,37 +10,92 @@ use num_traits::WrappingAdd;
1010use vortex_array:: Array ;
1111use vortex_array:: ToCanonical ;
1212use vortex_array:: arrays:: PrimitiveArray ;
13+ use vortex_array:: execution:: ExecutionCtx ;
1314use vortex_array:: validity:: Validity ;
1415use vortex_buffer:: Buffer ;
1516use vortex_buffer:: BufferMut ;
1617use vortex_dtype:: NativePType ;
18+ use vortex_dtype:: PTypeDowncastExt ;
1719use vortex_dtype:: match_each_unsigned_integer_ptype;
20+ use vortex_error:: VortexResult ;
21+ use vortex_error:: vortex_panic;
22+ use vortex_vector:: Vector ;
23+ use vortex_vector:: primitive:: PVector ;
24+ use vortex_vector:: primitive:: PrimitiveVector ;
1825
1926use crate :: DeltaArray ;
2027
28+ /// Decompresses the [`DeltaArray`] into a vector.
29+ pub fn delta_decompress_into_primitive_vector (
30+ array : & DeltaArray ,
31+ ctx : & mut ExecutionCtx ,
32+ ) -> VortexResult < Vector > {
33+ let bases = array. bases ( ) . batch_execute ( ctx) ?. into_primitive ( ) ;
34+ let deltas = array. deltas ( ) . batch_execute ( ctx) ?. into_primitive ( ) ;
35+
36+ let start = array. offset ( ) ;
37+ let end = start + array. len ( ) ;
38+
39+ let validity = array. deltas ( ) . validity_mask ( ) . slice ( start..end) ;
40+
41+ macro_rules! decompress_case {
42+ ( $pv: expr, $type: ty, $deltas: expr, $start: expr, $end: expr, $validity: expr) => { {
43+ const LANES : usize = <$type>:: LANES ;
44+ let buffer = decompress_primitive:: <$type, LANES >(
45+ $pv. as_ref( ) ,
46+ $deltas. downcast:: <$type>( ) . as_ref( ) ,
47+ ) ;
48+ let buffer = buffer. slice( $start..$end) ;
49+
50+ // SAFETY: We slice the buffer and the validity by the same range.
51+ unsafe { PVector :: <$type>:: new_unchecked( buffer, $validity) } . into( )
52+ } } ;
53+ }
54+
55+ Ok ( match bases {
56+ PrimitiveVector :: U8 ( pv) => decompress_case ! ( pv, u8 , deltas, start, end, validity) ,
57+ PrimitiveVector :: U16 ( pv) => decompress_case ! ( pv, u16 , deltas, start, end, validity) ,
58+ PrimitiveVector :: U32 ( pv) => decompress_case ! ( pv, u32 , deltas, start, end, validity) ,
59+ PrimitiveVector :: U64 ( pv) => decompress_case ! ( pv, u64 , deltas, start, end, validity) ,
60+ PrimitiveVector :: I8 ( _)
61+ | PrimitiveVector :: I16 ( _)
62+ | PrimitiveVector :: I32 ( _)
63+ | PrimitiveVector :: I64 ( _)
64+ | PrimitiveVector :: F16 ( _)
65+ | PrimitiveVector :: F32 ( _)
66+ | PrimitiveVector :: F64 ( _) => {
67+ vortex_panic ! ( "Tried to match a non-unsigned vector in an unsigned match statement" )
68+ }
69+ } )
70+ }
71+
2172pub fn delta_decompress ( array : & DeltaArray ) -> PrimitiveArray {
2273 let bases = array. bases ( ) . to_primitive ( ) ;
2374 let deltas = array. deltas ( ) . to_primitive ( ) ;
24- let decoded = match_each_unsigned_integer_ptype ! ( deltas. ptype( ) , |T | {
75+
76+ let start = array. offset ( ) ;
77+ let end = start + array. len ( ) ;
78+
79+ let validity = Validity :: from_mask ( array. deltas ( ) . validity_mask ( ) , array. dtype ( ) . nullability ( ) ) ;
80+ let validity = validity. slice ( start..end) ;
81+
82+ match_each_unsigned_integer_ptype ! ( deltas. ptype( ) , |T | {
2583 const LANES : usize = T :: LANES ;
2684
27- PrimitiveArray :: new(
28- decompress_primitive:: <T , LANES >( bases. as_slice( ) , deltas. as_slice( ) ) ,
29- Validity :: from_mask( array. deltas( ) . validity_mask( ) , array. dtype( ) . nullability( ) ) ,
30- )
31- } ) ;
85+ let buffer = decompress_primitive:: <T , LANES >( bases. as_slice( ) , deltas. as_slice( ) ) ;
86+ let buffer = buffer. slice( start..end) ;
3287
33- decoded
34- . slice ( array. offset ( ) ..array. offset ( ) + array. len ( ) )
35- . to_primitive ( )
88+ PrimitiveArray :: new( buffer, validity)
89+ } )
3690}
3791
3892// TODO(ngates): can we re-use the deltas buffer for the result? Might be tricky given the
3993// traversal ordering, but possibly doable.
40- fn decompress_primitive < T : NativePType + Delta + Transpose + WrappingAdd , const LANES : usize > (
41- bases : & [ T ] ,
42- deltas : & [ T ] ,
43- ) -> Buffer < T > {
94+ /// Performs the low-level delta decompression on primitive values.
95+ pub ( super ) fn decompress_primitive < T , const LANES : usize > ( bases : & [ T ] , deltas : & [ T ] ) -> Buffer < T >
96+ where
97+ T : NativePType + Delta + Transpose + WrappingAdd ,
98+ {
4499 // How many fastlanes vectors we will process.
45100 let num_chunks = deltas. len ( ) / 1024 ;
46101
0 commit comments