@@ -13,13 +13,21 @@ use crate::{BitPackedArray, BitPackedEncoding};
1313
1414impl FilterFn < BitPackedArray > for BitPackedEncoding {
1515 fn filter ( & self , array : & BitPackedArray , mask : FilterMask ) -> VortexResult < ArrayData > {
16- let primitive = match_each_unsigned_integer_ptype ! ( array. ptype( ) , |$I | {
16+ let primitive = match_each_unsigned_integer_ptype ! ( array. ptype( ) . to_unsigned ( ) , |$I | {
1717 filter_primitive:: <$I >( array, mask)
1818 } ) ;
1919 Ok ( primitive?. into_array ( ) )
2020 }
2121}
2222
23+ /// Specialized filter kernel for primitive bit-packed arrays.
24+ ///
25+ /// Because the FastLanes bit-packing kernels are only implemented for unsigned types, the provided
26+ /// `T` should be promoted to the unsigned variant for any target bit width.
27+ /// For example, if the array is bit-packed `i16`, this function called be called with `T = u16`.
28+ ///
29+ /// All bit-packing operations will use the unsigned kernels, but the logical type of `array`
30+ /// dictates the final `PType` of the result.
2331fn filter_primitive < T : NativePType + BitPacking + ArrowNativeType > (
2432 array : & BitPackedArray ,
2533 mask : FilterMask ,
@@ -49,7 +57,7 @@ fn filter_primitive<T: NativePType + BitPacking + ArrowNativeType>(
4957 FilterIter :: SlicesIter ( iter) => filter_slices ( array, mask. true_count ( ) , iter) ,
5058 } ;
5159
52- let mut values = PrimitiveArray :: from_vec ( values, validity) ;
60+ let mut values = PrimitiveArray :: from_vec ( values, validity) . reinterpret_cast ( array . ptype ( ) ) ;
5361 if let Some ( patches) = patches {
5462 values = values. patch ( patches) ?;
5563 }
@@ -120,6 +128,7 @@ fn filter_slices<T: NativePType + BitPacking + ArrowNativeType>(
120128
121129#[ cfg( test) ]
122130mod test {
131+ use itertools:: Itertools ;
123132 use vortex_array:: array:: PrimitiveArray ;
124133 use vortex_array:: compute:: { filter, slice, FilterMask } ;
125134 use vortex_array:: { ArrayLen , IntoArrayVariant } ;
@@ -166,4 +175,24 @@ mod test {
166175 ( 0 ..1024 ) . map( |i| ( i % 63 ) as u8 ) . collect:: <Vec <_>>( )
167176 ) ;
168177 }
178+
179+ #[ test]
180+ fn filter_bitpacked_signed ( ) {
181+ // Elements 0..=499 are negative integers (patches)
182+ // Element 500 = 0 (packed)
183+ // Elements 501..999 are positive integers (packed)
184+ let values: Vec < i64 > = ( -500 ..500 ) . collect_vec ( ) ;
185+ let unpacked = PrimitiveArray :: from ( values. clone ( ) ) ;
186+ let bitpacked = BitPackedArray :: encode ( unpacked. as_ref ( ) , 9 ) . unwrap ( ) ;
187+ let filtered = filter (
188+ bitpacked. as_ref ( ) ,
189+ FilterMask :: from_indices ( values. len ( ) , 250 ..750 ) ,
190+ )
191+ . unwrap ( )
192+ . into_primitive ( )
193+ . unwrap ( )
194+ . into_maybe_null_slice :: < i64 > ( ) ;
195+
196+ assert_eq ! ( filtered. as_slice( ) , & values[ 250 ..750 ] ) ;
197+ }
169198}
0 commit comments