@@ -110,16 +110,20 @@ where
110110 T : NativePType + FastLanesComparable < Bitpacked = U > ,
111111 U : UnsignedPType + BitPacking + BitPackingCompare ,
112112{
113- let mut bits =
114- collect_chunk_masks :: < U > ( array. data ( ) , array. len ( ) , array. offset ( ) , |bit_width, packed_chunk, chunk_matches| unsafe {
113+ let mut bits = collect_chunk_masks :: < U > (
114+ array. data ( ) ,
115+ array. len ( ) ,
116+ array. offset ( ) ,
117+ |bit_width, packed_chunk, chunk_matches| unsafe {
115118 U :: unchecked_unpack_cmp (
116119 bit_width,
117120 packed_chunk,
118121 chunk_matches,
119122 |lhs, rhs| compare_values ( lhs, rhs, operator) ,
120123 value,
121124 ) ;
122- } ) ;
125+ } ,
126+ ) ;
123127
124128 if let Some ( patches) = array. patches ( ) {
125129 apply_patch_predicate :: < T > ( & mut bits, & patches, ctx, |patched| {
@@ -277,9 +281,9 @@ where
277281
278282 for chunk_idx in 0 ..num_chunks {
279283 let packed_chunk = & packed[ chunk_idx * elems_per_chunk..] [ ..elems_per_chunk] ;
280- let mut chunk_matches = [ 0u64 ; 16 ] ;
281- fill_chunk ( bit_width, packed_chunk, & mut chunk_matches) ;
282- output . extend_from_slice ( & chunk_matches ) ;
284+ append_chunk_matches ( & mut output , | chunk_matches| {
285+ fill_chunk ( bit_width, packed_chunk, chunk_matches) ;
286+ } ) ;
283287 }
284288
285289 let total_len = num_chunks * 1024 ;
@@ -316,18 +320,17 @@ where
316320 let num_chunks = ( offset as usize + len) . div_ceil ( 1024 ) ;
317321 let mut output = BufferMut :: < u64 > :: with_capacity ( num_chunks * 16 ) ;
318322 let mut unpacked = [ U :: default ( ) ; 1024 ] ;
319- let mut chunk_matches = [ 0u64 ; 16 ] ;
320323
321324 for chunk_idx in 0 ..num_chunks {
322325 let packed_chunk = & packed[ chunk_idx * elems_per_chunk..] [ ..elems_per_chunk] ;
323- chunk_matches. fill ( 0 ) ;
324326
325327 unsafe {
326328 U :: unchecked_unpack ( bit_width, packed_chunk, & mut unpacked) ;
327329 }
328330
329- fill_chunk ( & unpacked, & mut chunk_matches) ;
330- output. extend_from_slice ( & chunk_matches) ;
331+ append_chunk_matches ( & mut output, |chunk_matches| {
332+ fill_chunk ( & unpacked, chunk_matches) ;
333+ } ) ;
331334 }
332335
333336 let total_len = num_chunks * 1024 ;
@@ -345,6 +348,22 @@ where
345348 )
346349}
347350
351+ #[ inline]
352+ fn append_chunk_matches ( output : & mut BufferMut < u64 > , fill_chunk : impl FnOnce ( & mut [ u64 ; 16 ] ) ) {
353+ let base_len = output. len ( ) ;
354+
355+ let spare = output. spare_capacity_mut ( ) ;
356+ debug_assert ! ( spare. len( ) >= 16 ) ;
357+ let chunk_matches = unsafe { & mut * ( spare. as_mut_ptr ( ) . cast :: < [ u64 ; 16 ] > ( ) ) } ;
358+
359+ fill_chunk ( chunk_matches) ;
360+
361+ // SAFETY: `fill_chunk` initializes all 16 words before we expose them via `set_len`.
362+ unsafe {
363+ output. set_len ( base_len + 16 ) ;
364+ }
365+ }
366+
348367#[ inline]
349368fn fill_between_chunk < U , T , LF , UF > (
350369 unpacked : & [ U ; 1024 ] ,
@@ -448,6 +467,7 @@ mod tests {
448467 use vortex_array:: scalar_fn:: fns:: between:: StrictComparison ;
449468 use vortex_array:: scalar_fn:: fns:: binary:: CompareKernel ;
450469 use vortex_array:: scalar_fn:: fns:: operators:: CompareOperator ;
470+ use vortex_array:: validity:: Validity ;
451471
452472 use crate :: BitPacked ;
453473 use crate :: BitPackedArrayExt ;
@@ -514,11 +534,7 @@ mod tests {
514534
515535 assert_arrays_eq ! (
516536 result,
517- BoolArray :: from_indices(
518- array. len( ) ,
519- [ 256usize ] ,
520- vortex_array:: validity:: Validity :: NonNullable ,
521- )
537+ BoolArray :: from_indices( array. len( ) , [ 256usize ] , Validity :: NonNullable , )
522538 ) ;
523539 }
524540
@@ -584,11 +600,7 @@ mod tests {
584600
585601 assert_arrays_eq ! (
586602 result,
587- BoolArray :: from_indices(
588- len,
589- [ 255usize , 256 ] ,
590- vortex_array:: validity:: Validity :: NonNullable ,
591- )
603+ BoolArray :: from_indices( len, [ 255usize , 256 ] , Validity :: NonNullable , )
592604 ) ;
593605 }
594606
0 commit comments