11use fastlanes:: BitPacking ;
2- use itertools:: Itertools ;
32use vortex_array:: array:: PrimitiveArray ;
43use vortex_array:: compute:: { take, try_cast, TakeFn } ;
54use vortex_array:: variants:: PrimitiveArrayTrait ;
@@ -12,6 +11,7 @@ use vortex_dtype::{
1211} ;
1312use vortex_error:: { VortexExpect as _, VortexResult } ;
1413
14+ use super :: chunked_indices;
1515use crate :: { unpack_single_primitive, BitPackedArray , BitPackedEncoding } ;
1616
1717// assuming the buffer is already allocated (which will happen at most once) then unpacking
@@ -54,35 +54,30 @@ fn take_primitive<T: NativePType + BitPacking, I: NativePType>(
5454 let packed = array. packed_slice :: < T > ( ) ;
5555
5656 // Group indices by 1024-element chunk, *without* allocating on the heap
57- let chunked_indices = & indices
58- . maybe_null_slice :: < I > ( )
59- . iter ( )
60- . map ( |i| {
61- i. to_usize ( )
62- . vortex_expect ( "index must be expressible as usize" )
63- + offset
64- } )
65- . chunk_by ( |idx| idx / 1024 ) ;
57+ let indices_iter = indices. maybe_null_slice :: < I > ( ) . iter ( ) . map ( |i| {
58+ i. to_usize ( )
59+ . vortex_expect ( "index must be expressible as usize" )
60+ } ) ;
6661
6762 let mut output = Vec :: with_capacity ( indices. len ( ) ) ;
6863 let mut unpacked = [ T :: zero ( ) ; 1024 ] ;
64+ let chunk_len = 128 * bit_width / size_of :: < T > ( ) ;
6965
70- for ( chunk, offsets) in chunked_indices {
71- let chunk_size = 128 * bit_width / size_of :: < T > ( ) ;
72- let packed_chunk = & packed[ chunk * chunk_size..] [ ..chunk_size] ;
66+ chunked_indices ( indices_iter, offset, |chunk_idx, indices_within_chunk| {
67+ let packed = & packed[ chunk_idx * chunk_len..] [ ..chunk_len] ;
7368
7469 // array_chunks produced a fixed size array, doesn't heap allocate
7570 let mut have_unpacked = false ;
76- let mut offset_chunk_iter = offsets
77- // relativize indices to the start of the chunk
78- . map ( |i| i % 1024 )
71+ let mut offset_chunk_iter = indices_within_chunk
72+ . iter ( )
73+ . copied ( )
7974 . array_chunks :: < UNPACK_CHUNK_THRESHOLD > ( ) ;
8075
8176 // this loop only runs if we have at least UNPACK_CHUNK_THRESHOLD offsets
8277 for offset_chunk in & mut offset_chunk_iter {
8378 if !have_unpacked {
8479 unsafe {
85- BitPacking :: unchecked_unpack ( bit_width, packed_chunk , & mut unpacked) ;
80+ BitPacking :: unchecked_unpack ( bit_width, packed , & mut unpacked) ;
8681 }
8782 have_unpacked = true ;
8883 }
@@ -103,13 +98,11 @@ fn take_primitive<T: NativePType + BitPacking, I: NativePType>(
10398 // we had fewer than UNPACK_CHUNK_THRESHOLD offsets in the first place,
10499 // so we need to unpack each one individually
105100 for index in remainder {
106- output. push ( unsafe {
107- unpack_single_primitive :: < T > ( packed_chunk, bit_width, index)
108- } ) ;
101+ output. push ( unsafe { unpack_single_primitive :: < T > ( packed, bit_width, index) } ) ;
109102 }
110103 }
111104 }
112- }
105+ } ) ;
113106
114107 if let Some ( patches) = array
115108 . patches ( )
0 commit comments