22// SPDX-FileCopyrightText: Copyright the Vortex contributors
33
44use itertools:: Itertools as _;
5+ use num_traits:: AsPrimitive ;
6+ use vortex_buffer:: Buffer ;
57use vortex_buffer:: BufferMut ;
68use vortex_error:: VortexExpect ;
79use vortex_error:: VortexResult ;
@@ -27,6 +29,7 @@ use crate::arrays::piecewise_sequence::constant_unsigned_usize;
2729use crate :: arrays:: piecewise_sequence:: maybe_contiguous_slices;
2830use crate :: arrays:: primitive:: PrimitiveArrayExt ;
2931use crate :: dtype:: IntegerPType ;
32+ use crate :: dtype:: PType ;
3033use crate :: dtype:: UnsignedPType ;
3134use crate :: executor:: ExecutionCtx ;
3235use crate :: match_each_unsigned_integer_ptype;
@@ -162,152 +165,54 @@ fn take_slices(
162165 let offsets = offsets. reinterpret_cast ( offsets. ptype ( ) . to_unsigned ( ) ) ;
163166 let output_len = indices_ref. len ( ) ;
164167
168+ // The piece starts and lengths are read once per piece, so they are widened to `u64` instead
169+ // of compiling the gather kernels for each of their widths.
170+ let starts = pieces_as_u64 ( & starts) ;
165171 let taken = match lengths {
166172 Columnar :: Constant ( lengths) => {
167173 let length = constant_unsigned_usize ( & lengths) ;
168- take_slices_constant_start_dispatch (
169- array,
170- & starts,
171- length,
172- & offsets,
173- indices_ref,
174- output_len,
175- & data_validity,
176- ) ?
174+ match_each_unsigned_integer_ptype ! ( offsets. ptype( ) , |O | {
175+ take_slices_constant_length:: <u64 , O >(
176+ array,
177+ & starts,
178+ length,
179+ offsets. as_slice:: <O >( ) ,
180+ indices_ref,
181+ output_len,
182+ & data_validity,
183+ )
184+ } ) ?
177185 }
178186 Columnar :: Canonical ( lengths) => {
179- let lengths = lengths. into_primitive ( ) ;
180- take_slices_start_dispatch (
181- array,
182- & starts,
183- & lengths,
184- & offsets,
185- indices_ref,
186- output_len,
187- & data_validity,
188- ) ?
187+ let lengths = pieces_as_u64 ( & lengths. into_primitive ( ) ) ;
188+ match_each_unsigned_integer_ptype ! ( offsets. ptype( ) , |O | {
189+ take_slices_typed:: <u64 , u64 , O >(
190+ array,
191+ & starts,
192+ & lengths,
193+ offsets. as_slice:: <O >( ) ,
194+ indices_ref,
195+ output_len,
196+ & data_validity,
197+ )
198+ } ) ?
189199 }
190200 } ;
191201 Ok ( Some ( taken) )
192202}
193203
194- fn take_slices_constant_start_dispatch (
195- array : ArrayView < ' _ , List > ,
196- starts : & PrimitiveArray ,
197- length : usize ,
198- offsets : & PrimitiveArray ,
199- indices_ref : & ArrayRef ,
200- output_len : usize ,
201- data_validity : & Mask ,
202- ) -> VortexResult < ArrayRef > {
203- match_each_unsigned_integer_ptype ! ( starts. ptype( ) , |S | {
204- take_slices_constant_offset_dispatch:: <S >(
205- array,
206- starts,
207- length,
208- offsets,
209- indices_ref,
210- output_len,
211- data_validity,
212- )
213- } )
214- }
215-
216- fn take_slices_constant_offset_dispatch < S > (
217- array : ArrayView < ' _ , List > ,
218- starts : & PrimitiveArray ,
219- length : usize ,
220- offsets : & PrimitiveArray ,
221- indices_ref : & ArrayRef ,
222- output_len : usize ,
223- data_validity : & Mask ,
224- ) -> VortexResult < ArrayRef >
225- where
226- S : UnsignedPType ,
227- {
228- match_each_unsigned_integer_ptype ! ( offsets. ptype( ) , |O | {
229- take_slices_constant_length:: <S , O >(
230- array,
231- starts. as_slice:: <S >( ) ,
232- length,
233- offsets. as_slice:: <O >( ) ,
234- indices_ref,
235- output_len,
236- data_validity,
237- )
238- } )
239- }
240-
241- fn take_slices_start_dispatch (
242- array : ArrayView < ' _ , List > ,
243- starts : & PrimitiveArray ,
244- lengths : & PrimitiveArray ,
245- offsets : & PrimitiveArray ,
246- indices_ref : & ArrayRef ,
247- output_len : usize ,
248- data_validity : & Mask ,
249- ) -> VortexResult < ArrayRef > {
250- match_each_unsigned_integer_ptype ! ( starts. ptype( ) , |S | {
251- take_slices_length_dispatch:: <S >(
252- array,
253- starts,
254- lengths,
255- offsets,
256- indices_ref,
257- output_len,
258- data_validity,
259- )
260- } )
261- }
262-
263- fn take_slices_length_dispatch < S > (
264- array : ArrayView < ' _ , List > ,
265- starts : & PrimitiveArray ,
266- lengths : & PrimitiveArray ,
267- offsets : & PrimitiveArray ,
268- indices_ref : & ArrayRef ,
269- output_len : usize ,
270- data_validity : & Mask ,
271- ) -> VortexResult < ArrayRef >
272- where
273- S : UnsignedPType ,
274- {
275- match_each_unsigned_integer_ptype ! ( lengths. ptype( ) , |L | {
276- take_slices_offset_dispatch:: <S , L >(
277- array,
278- starts,
279- lengths,
280- offsets,
281- indices_ref,
282- output_len,
283- data_validity,
284- )
285- } )
286- }
204+ /// Returns the unsigned piece values as `u64`. This does not copy when they are already `u64`.
205+ fn pieces_as_u64 ( pieces : & PrimitiveArray ) -> Buffer < u64 > {
206+ if pieces. ptype ( ) == PType :: U64 {
207+ return pieces. to_buffer :: < u64 > ( ) ;
208+ }
287209
288- fn take_slices_offset_dispatch < S , L > (
289- array : ArrayView < ' _ , List > ,
290- starts : & PrimitiveArray ,
291- lengths : & PrimitiveArray ,
292- offsets : & PrimitiveArray ,
293- indices_ref : & ArrayRef ,
294- output_len : usize ,
295- data_validity : & Mask ,
296- ) -> VortexResult < ArrayRef >
297- where
298- S : UnsignedPType ,
299- L : UnsignedPType ,
300- {
301- match_each_unsigned_integer_ptype ! ( offsets. ptype( ) , |O | {
302- take_slices_typed:: <S , L , O >(
303- array,
304- starts. as_slice:: <S >( ) ,
305- lengths. as_slice:: <L >( ) ,
306- offsets. as_slice:: <O >( ) ,
307- indices_ref,
308- output_len,
309- data_validity,
310- )
210+ match_each_unsigned_integer_ptype ! ( pieces. ptype( ) , |P | {
211+ pieces
212+ . as_slice:: <P >( )
213+ . iter( )
214+ . map( |& piece| piece. as_( ) )
215+ . collect( )
311216 } )
312217}
313218
@@ -849,9 +754,11 @@ mod test {
849754 use std:: sync:: Arc ;
850755
851756 use rstest:: rstest;
757+ use vortex_buffer:: Buffer ;
852758 use vortex_buffer:: buffer;
853759 use vortex_error:: VortexResult ;
854760
761+ use crate :: ArrayRef ;
855762 use crate :: IntoArray as _;
856763 use crate :: VortexSessionExecute ;
857764 use crate :: array_session;
@@ -1114,6 +1021,58 @@ mod test {
11141021 ) ;
11151022 }
11161023
1024+ /// The take widens narrow piece starts and lengths to `u64`.
1025+ #[ rstest]
1026+ #[ case:: u8_pieces(
1027+ buffer![ 1u8 , 0 ] . into_array( ) ,
1028+ buffer![ 2u8 , 1 ] . into_array( ) ,
1029+ buffer![ 2i32 , 3 , 4 , 0 , 1 ] ,
1030+ buffer![ 0u32 , 3 , 3 , 5 ]
1031+ ) ]
1032+ #[ case:: mixed_pieces(
1033+ buffer![ 1u16 , 0 ] . into_array( ) ,
1034+ buffer![ 2u32 , 1 ] . into_array( ) ,
1035+ buffer![ 2i32 , 3 , 4 , 0 , 1 ] ,
1036+ buffer![ 0u32 , 3 , 3 , 5 ]
1037+ ) ]
1038+ #[ case:: constant_length(
1039+ buffer![ 3u16 , 0 ] . into_array( ) ,
1040+ ConstantArray :: new( 1u8 , 2 ) . into_array( ) ,
1041+ buffer![ 5i32 , 6 , 0 , 1 ] ,
1042+ buffer![ 0u32 , 2 , 4 ]
1043+ ) ]
1044+ fn piecewise_sequence_take_narrow_pieces (
1045+ #[ case] starts : ArrayRef ,
1046+ #[ case] lengths : ArrayRef ,
1047+ #[ case] expected_elements : Buffer < i32 > ,
1048+ #[ case] expected_offsets : Buffer < u32 > ,
1049+ ) -> VortexResult < ( ) > {
1050+ let mut ctx = array_session ( ) . create_execution_ctx ( ) ;
1051+ let list = ListArray :: try_new (
1052+ buffer ! [ 0i32 , 1 , 2 , 3 , 4 , 5 , 6 ] . into_array ( ) ,
1053+ buffer ! [ 0u32 , 2 , 5 , 5 , 7 ] . into_array ( ) ,
1054+ Validity :: NonNullable ,
1055+ & mut ctx,
1056+ ) ?
1057+ . into_array ( ) ;
1058+ let output_len = expected_offsets. len ( ) - 1 ;
1059+ let indices = PiecewiseSequenceArray :: try_new (
1060+ starts,
1061+ lengths,
1062+ ConstantArray :: new ( 1u64 , 2 ) . into_array ( ) ,
1063+ output_len,
1064+ ) ?;
1065+ let expected = ListArray :: try_new (
1066+ expected_elements. into_array ( ) ,
1067+ expected_offsets. into_array ( ) ,
1068+ Validity :: NonNullable ,
1069+ & mut ctx,
1070+ ) ?;
1071+
1072+ assert_arrays_eq ! ( list. take( indices. into_array( ) ) ?, expected, & mut ctx) ;
1073+ Ok ( ( ) )
1074+ }
1075+
11171076 #[ test]
11181077 fn piecewise_sequence_take ( ) {
11191078 let mut ctx = array_session ( ) . create_execution_ctx ( ) ;
0 commit comments