11// SPDX-License-Identifier: Apache-2.0
22// SPDX-FileCopyrightText: Copyright the Vortex contributors
33
4+ use vortex_dtype:: NativePType ;
45use vortex_vector:: VectorMutOps ;
6+ use vortex_vector:: VectorOps ;
57use vortex_vector:: bool:: BoolVector ;
68use vortex_vector:: bool:: BoolVectorMut ;
79use vortex_vector:: primitive:: PVector ;
@@ -10,137 +12,75 @@ use vortex_vector::primitive::PrimitiveVector;
1012
1113use crate :: take:: Take ;
1214
13- /// Tests `Take` on `PVector` with mixed validity in both data and indices.
14- ///
15- /// This test covers:
16- /// - Taking from a vector with some null values.
17- /// - Using indices that have some null values.
18- /// - Verifying that nulls in the data propagate correctly.
19- /// - Verifying that nulls in indices result in null outputs.
20- /// - Using non-sequential indices to test the general case.
15+ /// Helper to collect a `PVector` into a `Vec<Option<T>>` for easy comparison.
16+ fn collect_pvector < T : NativePType > ( v : & PVector < T > ) -> Vec < Option < T > > {
17+ ( 0 ..v. len ( ) ) . map ( |i| v. get ( i) . copied ( ) ) . collect ( )
18+ }
19+
20+ /// Helper to collect a `BoolVector` into a `Vec<Option<bool>>` for easy comparison.
21+ fn collect_bool_vector ( v : & BoolVector ) -> Vec < Option < bool > > {
22+ ( 0 ..v. len ( ) ) . map ( |i| v. get ( i) ) . collect ( )
23+ }
24+
2125#[ test]
2226fn test_pvector_take_with_nullable_indices ( ) {
23- // Data: [10, null, 30, 40, null, 60]
24- let data: PVectorMut < i32 > = [ Some ( 10 ) , None , Some ( 30 ) , Some ( 40 ) , None , Some ( 60 ) ]
25- . into_iter ( )
26- . collect ( ) ;
27- let data = data. freeze ( ) ;
28-
29- // Indices: [0, null, 2, 5, null] (u32 indices with nulls)
30- let indices: PVectorMut < u32 > = [ Some ( 0 ) , None , Some ( 2 ) , Some ( 5 ) , None ]
31- . into_iter ( )
32- . collect ( ) ;
33- let indices = indices. freeze ( ) ;
27+ let data: PVector < i32 > =
28+ PVectorMut :: from_iter ( [ Some ( 10 ) , None , Some ( 30 ) , Some ( 40 ) , None , Some ( 60 ) ] ) . freeze ( ) ;
29+ let indices: PVector < u32 > =
30+ PVectorMut :: from_iter ( [ Some ( 0 ) , None , Some ( 2 ) , Some ( 5 ) , None ] ) . freeze ( ) ;
3431
3532 let result = ( & data) . take ( & indices) ;
3633
37- // Expected: [10, null, 30, 60, null]
38- // - Index 0 -> data[0] = 10 (valid)
39- // - Index null -> null (null index produces null)
40- // - Index 2 -> data[2] = 30 (valid)
41- // - Index 5 -> data[5] = 60 (valid)
42- // - Index null -> null (null index produces null)
43- assert_eq ! ( result. get( 0 ) , Some ( & 10 ) ) ;
44- assert_eq ! ( result. get( 1 ) , None ) ; // Null index.
45- assert_eq ! ( result. get( 2 ) , Some ( & 30 ) ) ;
46- assert_eq ! ( result. get( 3 ) , Some ( & 60 ) ) ;
47- assert_eq ! ( result. get( 4 ) , None ) ; // Null index.
34+ assert_eq ! (
35+ collect_pvector( & result) ,
36+ vec![ Some ( 10 ) , None , Some ( 30 ) , Some ( 60 ) , None ]
37+ ) ;
4838}
4939
50- /// Tests `Take` on `PVector` using `PrimitiveVector` indices (type-erased).
51- ///
52- /// This ensures the generic `Take<PrimitiveVector>` impl works correctly by dispatching to the
53- /// typed implementation.
5440#[ test]
5541fn test_pvector_take_with_primitive_vector_indices ( ) {
56- // Data: [100, 200, null, 400, 500]
57- let data: PVectorMut < i64 > = [ Some ( 100 ) , Some ( 200 ) , None , Some ( 400 ) , Some ( 500 ) ]
58- . into_iter ( )
59- . collect ( ) ;
60- let data = data. freeze ( ) ;
61-
62- // Indices as PrimitiveVector (u16): [4, 2, 0, 1]
63- let indices: PVectorMut < u16 > = [ 4u16 , 2 , 0 , 1 ] . into_iter ( ) . collect ( ) ;
64- let indices: PrimitiveVector = indices. freeze ( ) . into ( ) ;
42+ let data: PVector < i64 > =
43+ PVectorMut :: from_iter ( [ Some ( 100 ) , Some ( 200 ) , None , Some ( 400 ) , Some ( 500 ) ] ) . freeze ( ) ;
44+ let indices: PrimitiveVector = PVectorMut :: from_iter ( [ 4u16 , 2 , 0 , 1 ] ) . freeze ( ) . into ( ) ;
6545
6646 let result: PVector < i64 > = ( & data) . take ( & indices) ;
6747
68- // Expected: [500, null, 100, 200]
69- assert_eq ! ( result. get( 0 ) , Some ( & 500 ) ) ;
70- assert_eq ! ( result. get( 1 ) , None ) ; // data[2] is null.
71- assert_eq ! ( result. get( 2 ) , Some ( & 100 ) ) ;
72- assert_eq ! ( result. get( 3 ) , Some ( & 200 ) ) ;
48+ assert_eq ! (
49+ collect_pvector( & result) ,
50+ vec![ Some ( 500 ) , None , Some ( 100 ) , Some ( 200 ) ]
51+ ) ;
7352}
7453
75- /// Tests `Take` on `BoolVector` with mixed validity in both data and indices.
76- ///
77- /// This test covers:
78- /// - Taking from a boolean vector with some null values.
79- /// - Using indices that have some null values.
80- /// - Verifying that nulls in the data propagate correctly.
81- /// - Verifying that nulls in indices result in null outputs.
8254#[ test]
8355fn test_bool_vector_take_with_nullable_indices ( ) {
84- // Data: [true, null, false, true, null, false]
85- let data: BoolVectorMut = [ Some ( true ) , None , Some ( false ) , Some ( true ) , None , Some ( false ) ]
86- . into_iter ( )
87- . collect ( ) ;
88- let data = data. freeze ( ) ;
89-
90- // Indices: [5, null, 0, 3, null, 2] (u32 indices with nulls)
91- let indices: PVectorMut < u32 > = [ Some ( 5 ) , None , Some ( 0 ) , Some ( 3 ) , None , Some ( 2 ) ]
92- . into_iter ( )
93- . collect ( ) ;
94- let indices = indices. freeze ( ) ;
56+ let data: BoolVector =
57+ BoolVectorMut :: from_iter ( [ Some ( true ) , None , Some ( false ) , Some ( true ) , None , Some ( false ) ] )
58+ . freeze ( ) ;
59+ let indices: PVector < u32 > =
60+ PVectorMut :: from_iter ( [ Some ( 5 ) , None , Some ( 0 ) , Some ( 3 ) , None , Some ( 2 ) ] ) . freeze ( ) ;
9561
9662 let result = ( & data) . take ( & indices) ;
9763
98- // Expected: [false, null, true, true, null, false]
99- // - Index 5 -> data[5] = false (valid)
100- // - Index null -> null (null index produces null)
101- // - Index 0 -> data[0] = true (valid)
102- // - Index 3 -> data[3] = true (valid)
103- // - Index null -> null (null index produces null)
104- // - Index 2 -> data[2] = false (valid)
105- assert_eq ! ( result. get( 0 ) , Some ( false ) ) ;
106- assert_eq ! ( result. get( 1 ) , None ) ; // Null index.
107- assert_eq ! ( result. get( 2 ) , Some ( true ) ) ;
108- assert_eq ! ( result. get( 3 ) , Some ( true ) ) ;
109- assert_eq ! ( result. get( 4 ) , None ) ; // Null index.
110- assert_eq ! ( result. get( 5 ) , Some ( false ) ) ;
64+ assert_eq ! (
65+ collect_bool_vector( & result) ,
66+ vec![ Some ( false ) , None , Some ( true ) , Some ( true ) , None , Some ( false ) ]
67+ ) ;
11168}
11269
113- /// Tests `Take` on `BoolVector` using `PrimitiveVector` indices (type-erased).
114- ///
115- /// This ensures the generic `Take<PrimitiveVector>` impl works correctly for `BoolVector`.
11670#[ test]
11771fn test_bool_vector_take_with_primitive_vector_indices ( ) {
118- // Data: [true, false, null, true, false]
119- let data: BoolVectorMut = [ Some ( true ) , Some ( false ) , None , Some ( true ) , Some ( false ) ]
120- . into_iter ( )
121- . collect ( ) ;
122- let data = data. freeze ( ) ;
123-
124- // Indices as PrimitiveVector (u64): [4, 2, 1, 0, 3]
125- let indices: PVectorMut < u64 > = [ 4u64 , 2 , 1 , 0 , 3 ] . into_iter ( ) . collect ( ) ;
126- let indices: PrimitiveVector = indices. freeze ( ) . into ( ) ;
72+ let data: BoolVector =
73+ BoolVectorMut :: from_iter ( [ Some ( true ) , Some ( false ) , None , Some ( true ) , Some ( false ) ] ) . freeze ( ) ;
74+ let indices: PrimitiveVector = PVectorMut :: from_iter ( [ 4u64 , 2 , 1 , 0 , 3 ] ) . freeze ( ) . into ( ) ;
12775
12876 let result: BoolVector = ( & data) . take ( & indices) ;
12977
130- // Expected: [false, null, false, true, true]
131- assert_eq ! ( result. get( 0 ) , Some ( false ) ) ; // data[4]
132- assert_eq ! ( result. get( 1 ) , None ) ; // data[2] is null.
133- assert_eq ! ( result. get( 2 ) , Some ( false ) ) ; // data[1]
134- assert_eq ! ( result. get( 3 ) , Some ( true ) ) ; // data[0]
135- assert_eq ! ( result. get( 4 ) , Some ( true ) ) ; // data[3]
78+ assert_eq ! (
79+ collect_bool_vector( & result) ,
80+ vec![ Some ( false ) , None , Some ( false ) , Some ( true ) , Some ( true ) ]
81+ ) ;
13682}
13783
138- /// Tests `Take` on `BitBuffer` covering both code paths.
139- ///
140- /// This test covers:
141- /// - The `take_byte_bool` path (small buffer, len <= 4096).
142- /// - The `take_bool` path (large buffer, len > 4096).
143- /// - Non-sequential indices to verify correct bit extraction.
14484#[ test]
14585fn test_bit_buffer_take_small_and_large ( ) {
14686 use vortex_buffer:: BitBuffer ;
@@ -149,135 +89,76 @@ fn test_bit_buffer_take_small_and_large() {
14989 let small: BitBuffer = [ true , false , true , true , false , true , false , false ]
15090 . into_iter ( )
15191 . collect ( ) ;
152- let indices = [ 7u32 , 0 , 2 , 5 , 1 ] ;
153- let result = ( & small) . take ( & indices[ ..] ) ;
92+ let result = ( & small) . take ( & [ 7u32 , 0 , 2 , 5 , 1 ] [ ..] ) ;
15493
155- assert_eq ! ( result. len( ) , 5 ) ;
156- assert ! ( !result. value( 0 ) ) ; // small[7] = false
157- assert ! ( result. value( 1 ) ) ; // small[0] = true
158- assert ! ( result. value( 2 ) ) ; // small[2] = true
159- assert ! ( result. value( 3 ) ) ; // small[5] = true
160- assert ! ( !result. value( 4 ) ) ; // small[1] = false
94+ let values: Vec < bool > = ( 0 ..result. len ( ) ) . map ( |i| result. value ( i) ) . collect ( ) ;
95+ assert_eq ! ( values, vec![ false , true , true , true , false ] ) ;
16196
16297 // Large buffer (uses take_bool path, len > 4096).
16398 let large: BitBuffer = ( 0 ..5000 ) . map ( |i| i % 3 == 0 ) . collect ( ) ;
164- let indices = [ 4999u32 , 0 , 1 , 2 , 3 , 4998 ] ;
165- let result = ( & large) . take ( & indices[ ..] ) ;
99+ let result = ( & large) . take ( & [ 4999u32 , 0 , 1 , 2 , 3 , 4998 ] [ ..] ) ;
166100
167- assert_eq ! ( result. len( ) , 6 ) ;
168- assert ! ( !result. value( 0 ) ) ; // 4999 % 3 != 0
169- assert ! ( result. value( 1 ) ) ; // 0 % 3 == 0
170- assert ! ( !result. value( 2 ) ) ; // 1 % 3 != 0
171- assert ! ( !result. value( 3 ) ) ; // 2 % 3 != 0
172- assert ! ( result. value( 4 ) ) ; // 3 % 3 == 0
173- assert ! ( result. value( 5 ) ) ; // 4998 % 3 == 0
101+ let values: Vec < bool > = ( 0 ..result. len ( ) ) . map ( |i| result. value ( i) ) . collect ( ) ;
102+ assert_eq ! ( values, vec![ false , true , false , false , true , true ] ) ;
174103}
175104
176- /// Tests `Take` on `Mask` covering all mask variants and nullable index handling.
177- ///
178- /// This test covers:
179- /// - `Mask::AllTrue` with slice indices.
180- /// - `Mask::AllFalse` with slice indices.
181- /// - `Mask::Values` with slice indices.
182- /// - `Mask::AllTrue` with nullable `PVector` indices (returns cloned validity).
183- /// - `Mask::AllFalse` with nullable `PVector` indices.
184- /// - `Mask::Values` with nullable `PVector` indices (both small and large paths).
185105#[ test]
186106fn test_mask_take_all_variants ( ) {
187107 use vortex_mask:: Mask ;
188108
189- // Test AllTrue with slice indices.
190- let all_true = Mask :: AllTrue ( 10 ) ;
191- let indices = [ 9u32 , 0 , 5 ] ;
192- let result = ( & all_true) . take ( & indices[ ..] ) ;
109+ // AllTrue with slice indices.
110+ let result = ( & Mask :: AllTrue ( 10 ) ) . take ( & [ 9u32 , 0 , 5 ] [ ..] ) ;
193111 assert ! ( result. all_true( ) ) ;
194112 assert_eq ! ( result. len( ) , 3 ) ;
195113
196- // Test AllFalse with slice indices.
197- let all_false = Mask :: AllFalse ( 10 ) ;
198- let result = ( & all_false) . take ( & indices[ ..] ) ;
114+ // AllFalse with slice indices.
115+ let result = ( & Mask :: AllFalse ( 10 ) ) . take ( & [ 9u32 , 0 , 5 ] [ ..] ) ;
199116 assert ! ( result. all_false( ) ) ;
200117 assert_eq ! ( result. len( ) , 3 ) ;
201118
202- // Test Values with slice indices.
119+ // Values with slice indices.
203120 let values = Mask :: from_iter ( [ true , false , true , true , false , true ] ) ;
204- let indices = [ 5u32 , 1 , 0 , 4 ] ;
205- let result = ( & values) . take ( & indices[ ..] ) ;
206- assert_eq ! ( result. len( ) , 4 ) ;
207- assert ! ( result. value( 0 ) ) ; // values[5] = true
208- assert ! ( !result. value( 1 ) ) ; // values[1] = false
209- assert ! ( result. value( 2 ) ) ; // values[0] = true
210- assert ! ( !result. value( 3 ) ) ; // values[4] = false
211-
212- // Test AllTrue with nullable PVector indices (some indices are null).
213- // When self is AllTrue, result validity equals indices validity.
214- let all_true = Mask :: AllTrue ( 10 ) ;
215- let indices: PVectorMut < u32 > = [ Some ( 0 ) , None , Some ( 5 ) , None , Some ( 9 ) ]
216- . into_iter ( )
217- . collect ( ) ;
218- let indices = indices. freeze ( ) ;
219- let result = ( & all_true) . take ( & indices) ;
220- assert_eq ! ( result. len( ) , 5 ) ;
221- assert ! ( result. value( 0 ) ) ; // Valid index.
222- assert ! ( !result. value( 1 ) ) ; // Null index -> false.
223- assert ! ( result. value( 2 ) ) ; // Valid index.
224- assert ! ( !result. value( 3 ) ) ; // Null index -> false.
225- assert ! ( result. value( 4 ) ) ; // Valid index.
226-
227- // Test AllFalse with nullable PVector indices (result is always AllFalse).
228- let all_false = Mask :: AllFalse ( 10 ) ;
229- let result = ( & all_false) . take ( & indices) ;
121+ let result = ( & values) . take ( & [ 5u32 , 1 , 0 , 4 ] [ ..] ) ;
122+ let bools: Vec < bool > = ( 0 ..result. len ( ) ) . map ( |i| result. value ( i) ) . collect ( ) ;
123+ assert_eq ! ( bools, vec![ true , false , true , false ] ) ;
124+
125+ // AllTrue with nullable PVector indices.
126+ let indices: PVector < u32 > =
127+ PVectorMut :: from_iter ( [ Some ( 0 ) , None , Some ( 5 ) , None , Some ( 9 ) ] ) . freeze ( ) ;
128+ let result = ( & Mask :: AllTrue ( 10 ) ) . take ( & indices) ;
129+ let bools: Vec < bool > = ( 0 ..result. len ( ) ) . map ( |i| result. value ( i) ) . collect ( ) ;
130+ assert_eq ! ( bools, vec![ true , false , true , false , true ] ) ;
131+
132+ // AllFalse with nullable PVector indices.
133+ let result = ( & Mask :: AllFalse ( 10 ) ) . take ( & indices) ;
230134 assert ! ( result. all_false( ) ) ;
231135 assert_eq ! ( result. len( ) , 5 ) ;
232136
233- // Test Values with nullable PVector indices.
234- // Combines mask values with index nullability.
137+ // Values with nullable PVector indices.
235138 let values = Mask :: from_iter ( [ true , false , true , false , true , false ] ) ;
236- let indices: PVectorMut < u32 > = [ Some ( 0 ) , None , Some ( 1 ) , Some ( 4 ) , None ]
237- . into_iter ( )
238- . collect ( ) ;
239- let indices = indices. freeze ( ) ;
139+ let indices: PVector < u32 > =
140+ PVectorMut :: from_iter ( [ Some ( 0 ) , None , Some ( 1 ) , Some ( 4 ) , None ] ) . freeze ( ) ;
240141 let result = ( & values) . take ( & indices) ;
241- assert_eq ! ( result. len( ) , 5 ) ;
242- assert ! ( result. value( 0 ) ) ; // values[0] = true, index valid.
243- assert ! ( !result. value( 1 ) ) ; // Null index -> false.
244- assert ! ( !result. value( 2 ) ) ; // values[1] = false.
245- assert ! ( result. value( 3 ) ) ; // values[4] = true, index valid.
246- assert ! ( !result. value( 4 ) ) ; // Null index -> false.
142+ let bools: Vec < bool > = ( 0 ..result. len ( ) ) . map ( |i| result. value ( i) ) . collect ( ) ;
143+ assert_eq ! ( bools, vec![ true , false , false , true , false ] ) ;
247144}
248145
249- /// Tests `Take` on `PrimitiveVector` using `PVector` indices.
250- ///
251- /// This ensures the type-erased `PrimitiveVector` can be taken with typed `PVector` indices,
252- /// covering the `Take<PVector<I>> for &PrimitiveVector` implementation.
253146#[ test]
254147fn test_primitive_vector_take_with_pvector_indices ( ) {
255- // Data as PrimitiveVector (i32): [10, 20, null, 40, 50]
256- let data: PVectorMut < i32 > = [ Some ( 10 ) , Some ( 20 ) , None , Some ( 40 ) , Some ( 50 ) ]
257- . into_iter ( )
258- . collect ( ) ;
259- let data: PrimitiveVector = data. freeze ( ) . into ( ) ;
260-
261- // Indices as PVector<u16> with some nulls: [4, null, 2, 0, null]
262- let indices: PVectorMut < u16 > = [ Some ( 4 ) , None , Some ( 2 ) , Some ( 0 ) , None ]
263- . into_iter ( )
264- . collect ( ) ;
265- let indices = indices. freeze ( ) ;
148+ let data: PrimitiveVector =
149+ PVectorMut :: from_iter ( [ Some ( 10i32 ) , Some ( 20 ) , None , Some ( 40 ) , Some ( 50 ) ] )
150+ . freeze ( )
151+ . into ( ) ;
152+ let indices: PVector < u16 > =
153+ PVectorMut :: from_iter ( [ Some ( 4 ) , None , Some ( 2 ) , Some ( 0 ) , None ] ) . freeze ( ) ;
266154
267155 let result = ( & data) . take ( & indices) ;
268156
269- // Expected: [50, null, null, 10, null]
270- // - Index 4 -> data[4] = 50 (valid)
271- // - Index null -> null (null index produces null)
272- // - Index 2 -> data[2] = null (data is null)
273- // - Index 0 -> data[0] = 10 (valid)
274- // - Index null -> null (null index produces null)
275157 let PrimitiveVector :: I32 ( result) = result else {
276- panic ! ( "Expected I32 variant" ) ;
158+ panic ! ( "Expected I32 variant" )
277159 } ;
278- assert_eq ! ( result. get( 0 ) , Some ( & 50 ) ) ;
279- assert_eq ! ( result. get( 1 ) , None ) ; // Null index.
280- assert_eq ! ( result. get( 2 ) , None ) ; // data[2] is null.
281- assert_eq ! ( result. get( 3 ) , Some ( & 10 ) ) ;
282- assert_eq ! ( result. get( 4 ) , None ) ; // Null index.
160+ assert_eq ! (
161+ collect_pvector( & result) ,
162+ vec![ Some ( 50 ) , None , None , Some ( 10 ) , None ]
163+ ) ;
283164}
0 commit comments