33
44use fastlanes:: { BitPacking , FastLanes } ;
55use static_assertions:: const_assert_eq;
6+ use vortex_array:: pipeline:: validity:: ValidityKernel ;
67use vortex_array:: pipeline:: {
78 BindContext , BitView , Kernel , KernelCtx , N , PipelineInputs , PipelinedNode ,
89} ;
10+ use vortex_array:: validity:: Validity ;
911use vortex_buffer:: Buffer ;
1012use vortex_dtype:: { PTypeDowncastExt , PhysicalPType , match_each_integer_ptype} ;
1113use vortex_error:: VortexResult ;
12- use vortex_mask:: Mask ;
1314use vortex_vector:: primitive:: PVectorMut ;
1415use vortex_vector:: { VectorMut , VectorMutOps } ;
1516
@@ -53,11 +54,21 @@ impl PipelinedNode for BitPackedArray {
5354 )
5455 }
5556
56- Ok ( Box :: new( AlignedBitPackedKernel :: <T >:: new(
57- packed_bit_width,
58- packed_buffer,
59- self . validity. to_mask( self . len( ) ) ,
60- ) ) as Box <dyn Kernel >)
57+ match self . validity {
58+ Validity :: NonNullable | Validity :: AllValid => Ok ( Box :: new(
59+ AlignedBitPackedKernel :: <T >:: new( packed_bit_width, packed_buffer) ,
60+ )
61+ as Box <dyn Kernel >) ,
62+ Validity :: AllInvalid => {
63+ todo!( "make a kernel that returns constant null" ) ;
64+ }
65+ Validity :: Array ( _) => {
66+ let inner = AlignedBitPackedKernel :: <T >:: new( packed_bit_width, packed_buffer) ;
67+ let mask = self . validity_mask( ) ;
68+
69+ Ok ( Box :: new( ValidityKernel :: new( inner, mask) ) as Box <dyn Kernel >)
70+ }
71+ }
6172 } )
6273 }
6374}
@@ -84,19 +95,12 @@ pub struct AlignedBitPackedKernel<BP: PhysicalPType<Physical: BitPacking>> {
8495 /// The buffer containing the bitpacked values.
8596 packed_buffer : Buffer < BP :: Physical > ,
8697
87- /// The validity mask for the bitpacked array.
88- validity : Mask ,
89-
9098 /// The total number of bitpacked chunks we have unpacked.
9199 num_chunks_unpacked : usize ,
92100}
93101
94102impl < BP : PhysicalPType < Physical : BitPacking > > AlignedBitPackedKernel < BP > {
95- pub fn new (
96- packed_bit_width : usize ,
97- packed_buffer : Buffer < BP :: Physical > ,
98- validity : Mask ,
99- ) -> Self {
103+ pub fn new ( packed_bit_width : usize , packed_buffer : Buffer < BP :: Physical > ) -> Self {
100104 let packed_stride =
101105 packed_bit_width * <<BP as PhysicalPType >:: Physical as FastLanes >:: LANES ;
102106
@@ -110,7 +114,6 @@ impl<BP: PhysicalPType<Physical: BitPacking>> AlignedBitPackedKernel<BP> {
110114 packed_bit_width,
111115 packed_stride,
112116 packed_buffer,
113- validity,
114117 num_chunks_unpacked : 0 ,
115118 }
116119 }
@@ -130,9 +133,6 @@ impl<BP: PhysicalPType<Physical: BitPacking>> Kernel for AlignedBitPackedKernel<
130133 let not_yet_unpacked_values = & self . packed_buffer . as_slice ( ) [ packed_offset..] ;
131134
132135 let true_count = selection. true_count ( ) ;
133- let chunk_offset = self . num_chunks_unpacked * N ;
134- let array_len = self . validity . len ( ) ;
135- debug_assert ! ( chunk_offset < array_len) ;
136136
137137 // If the true count is very small (the selection is sparse), we can unpack individual
138138 // elements directly into the output vector.
@@ -141,26 +141,21 @@ impl<BP: PhysicalPType<Physical: BitPacking>> Kernel for AlignedBitPackedKernel<
141141 debug_assert ! ( true_count <= output_vector. capacity( ) ) ;
142142
143143 selection. iter_ones ( |idx| {
144- let absolute_idx = chunk_offset + idx;
145- if self . validity . value ( absolute_idx) {
146- // SAFETY:
147- // - The documentation for `packed_bit_width` explains that the size is valid.
148- // - We know that the size of the `next_packed_chunk` we provide is equal to
149- // `self.packed_stride`, and we explain why this is correct in its
150- // documentation.
151- let unpacked_value = unsafe {
152- BitPacking :: unchecked_unpack_single (
153- self . packed_bit_width ,
154- not_yet_unpacked_values,
155- idx,
156- )
157- } ;
158-
159- // SAFETY: We just reserved enough capacity to push these values.
160- unsafe { output_vector. push_unchecked ( unpacked_value) } ;
161- } else {
162- output_vector. append_nulls ( 1 ) ;
163- }
144+ // SAFETY:
145+ // - The documentation for `packed_bit_width` explains that the size is valid.
146+ // - We know that the size of the `next_packed_chunk` we provide is equal to
147+ // `self.packed_stride`, and we explain why this is correct in its
148+ // documentation.
149+ let unpacked_value = unsafe {
150+ BitPacking :: unchecked_unpack_single (
151+ self . packed_bit_width ,
152+ not_yet_unpacked_values,
153+ idx,
154+ )
155+ } ;
156+
157+ // SAFETY: We just reserved enough capacity to push these values.
158+ unsafe { output_vector. elements_mut ( ) . push_unchecked ( unpacked_value) } ;
164159 } ) ;
165160 } else {
166161 // Otherwise if the mask is dense, it is faster to fully unpack the entire 1024
@@ -192,26 +187,6 @@ impl<BP: PhysicalPType<Physical: BitPacking>> Kernel for AlignedBitPackedKernel<
192187 output_vector. as_mut ( ) ,
193188 ) ;
194189 }
195-
196- if array_len < chunk_offset + N {
197- let vector_len = array_len - chunk_offset;
198- debug_assert ! ( vector_len < N , "math is broken" ) ;
199-
200- // SAFETY: This must be less than `N` so this is just a truncate.
201- unsafe { output_vector. elements_mut ( ) . set_len ( vector_len) } ;
202-
203- let chunk_mask = self . validity . slice ( chunk_offset..array_len) ;
204-
205- // SAFETY: We have just set the elements length to N, and the validity buffer has
206- // capacity for N elements.
207- unsafe { output_vector. validity_mut ( ) } . append_mask ( & chunk_mask) ;
208- } else {
209- let chunk_mask = self . validity . slice ( chunk_offset..chunk_offset + N ) ;
210-
211- // SAFETY: We have just set the elements length to N, and the validity buffer has
212- // capacity for N elements.
213- unsafe { output_vector. validity_mut ( ) } . append_mask ( & chunk_mask) ;
214- }
215190 }
216191
217192 self . num_chunks_unpacked += 1 ;
0 commit comments