@@ -37,67 +37,31 @@ pub fn unpack_primitive_array<T: BitPackedUnpack>(
3737 ctx : & mut ExecutionCtx ,
3838) -> VortexResult < PrimitiveArray > {
3939 let mut builder = PrimitiveBuilder :: with_capacity ( array. dtype ( ) . nullability ( ) , array. len ( ) ) ;
40- unpack_into_primitive_builder :: < T > ( array, & mut builder, ctx) ?;
40+ unpack_map_into_builder :: < T , T , _ > ( array, & mut builder, ctx, |v| v ) ?;
4141 assert_eq ! ( builder. len( ) , array. len( ) ) ;
4242 Ok ( builder. finish_into_primitive ( ) )
4343}
4444
45- pub ( crate ) fn unpack_into_primitive_builder < T : BitPackedUnpack > (
46- array : ArrayView < ' _ , BitPacked > ,
47- // TODO(ngates): do we want to use fastlanes alignment for this buffer?
48- builder : & mut PrimitiveBuilder < T > ,
49- ctx : & mut ExecutionCtx ,
50- ) -> VortexResult < ( ) > {
51- // If the array is empty, then we don't need to add anything to the builder.
52- if array. is_empty ( ) {
53- return Ok ( ( ) ) ;
54- }
55-
56- let mut uninit_range = builder. uninit_range ( array. len ( ) ) ;
57-
58- // SAFETY: We later initialize the the uninitialized range of values with `copy_from_slice`.
59- unsafe {
60- // Append a dense null Mask.
61- uninit_range. append_mask ( array. validity ( ) ?. execute_mask ( array. as_ref ( ) . len ( ) , ctx) ?) ;
62- }
63-
64- // SAFETY: `decode_into` will initialize all values in this range.
65- let uninit_slice = unsafe { uninit_range. slice_uninit_mut ( 0 , array. len ( ) ) } ;
66-
67- let mut bit_packed_iter = array. unpacked_chunks ( ) ?;
68- bit_packed_iter. decode_into ( uninit_slice) ;
69-
70- if let Some ( patches) = array. patches ( ) {
71- apply_patches_to_uninit_range ( & mut uninit_range, & patches, ctx) ?;
72- } ;
73-
74- // SAFETY: We have set a correct validity mask via `append_mask` with `array.len()` values and
75- // initialized the same number of values needed via `decode_into`.
76- unsafe {
77- uninit_range. finish ( ) ;
78- }
79- Ok ( ( ) )
80- }
81-
82- /// Unpack a bit-packed array of physical type `F` directly into a wider primitive type `T`,
83- /// casting each value during decompression.
45+ /// Unpack a bit-packed array of physical type `F` into a `PrimitiveBuilder<T>`, applying `map`
46+ /// to each value during decompression.
8447///
85- /// This is the "cast pushdown" path: rather than canonicalizing to a full-length `F`-typed
86- /// `PrimitiveArray` and then casting it to `T` (two full-length buffers, with the `F` intermediate
87- /// written out to RAM), we unpack each 1024-element FastLanes chunk into a small cache-resident
88- /// scratch buffer and cast-copy straight into the `T` output. Only the `T` output buffer is
89- /// allocated and touched in RAM.
48+ /// Pass `|v| v` (with `F = T`) for plain decompression, `|v: F| v.as_()` for a widening cast,
49+ /// or any other element-wise transform. Each 1024-element FastLanes chunk is unpacked into a
50+ /// cache-resident scratch buffer and written through `map` directly into the `T` output, so when
51+ /// `F != T` no full-length `F`-typed intermediate is materialized.
9052///
91- /// The caller must ensure all valid values are representable in `T` (it is intended for widening
92- /// casts such as `u16 -> u32`); narrowing or sign-changing casts are not validated here .
93- pub ( crate ) fn unpack_and_cast_into_builder < F , T > (
53+ /// The caller must ensure that every valid source value is representable in `T` under `map`; no
54+ /// per-value bounds check is performed .
55+ pub ( crate ) fn unpack_map_into_builder < F , T , M > (
9456 array : ArrayView < ' _ , BitPacked > ,
9557 builder : & mut PrimitiveBuilder < T > ,
9658 ctx : & mut ExecutionCtx ,
59+ map : M ,
9760) -> VortexResult < ( ) >
9861where
99- F : BitPackedUnpack + AsPrimitive < T > ,
62+ F : BitPackedUnpack ,
10063 T : NativePType ,
64+ M : Fn ( F ) -> T ,
10165{
10266 if array. is_empty ( ) {
10367 return Ok ( ( ) ) ;
@@ -115,10 +79,10 @@ where
11579 let uninit_slice = unsafe { uninit_range. slice_uninit_mut ( 0 , len) } ;
11680
11781 let mut chunks = array. unpacked_chunks :: < F > ( ) ?;
118- chunks. decode_map_into ( uninit_slice, | v : F | v . as_ ( ) ) ;
82+ chunks. decode_map_into ( uninit_slice, & map ) ;
11983
12084 if let Some ( patches) = array. patches ( ) {
121- apply_patches_to_uninit_range_map ( & mut uninit_range, & patches, ctx, | v : F | v . as_ ( ) ) ?;
85+ apply_patches_to_uninit_range ( & mut uninit_range, & patches, ctx, & map ) ?;
12286 }
12387
12488 // SAFETY: A correct validity mask of `len` values was set via `append_mask`, and the same
@@ -129,24 +93,7 @@ where
12993 Ok ( ( ) )
13094}
13195
132- pub fn apply_patches_to_uninit_range < T : NativePType > (
133- dst : & mut UninitRange < T > ,
134- patches : & Patches ,
135- ctx : & mut ExecutionCtx ,
136- ) -> VortexResult < ( ) > {
137- apply_patches_to_uninit_range_fn ( dst, patches, ctx, |v : T | v)
138- }
139-
140- pub fn apply_patches_to_uninit_range_fn < T : NativePType , F : Fn ( T ) -> T > (
141- dst : & mut UninitRange < T > ,
142- patches : & Patches ,
143- ctx : & mut ExecutionCtx ,
144- f : F ,
145- ) -> VortexResult < ( ) > {
146- apply_patches_to_uninit_range_map ( dst, patches, ctx, f)
147- }
148-
149- pub ( crate ) fn apply_patches_to_uninit_range_map < S : NativePType , T : NativePType , F : Fn ( S ) -> T > (
96+ pub fn apply_patches_to_uninit_range < S : NativePType , T : NativePType , F : Fn ( S ) -> T > (
15097 dst : & mut UninitRange < T > ,
15198 patches : & Patches ,
15299 ctx : & mut ExecutionCtx ,
@@ -394,10 +341,11 @@ mod tests {
394341 let bitpacked = encode ( & empty, 0 ) ;
395342
396343 let mut builder = PrimitiveBuilder :: < u32 > :: new ( Nullability :: NonNullable ) ;
397- unpack_into_primitive_builder (
344+ unpack_map_into_builder :: < _ , _ , _ > (
398345 bitpacked. as_view ( ) ,
399346 & mut builder,
400347 & mut SESSION . create_execution_ctx ( ) ,
348+ |v| v,
401349 ) ?;
402350
403351 let result = builder. finish_into_primitive ( ) ;
@@ -422,10 +370,11 @@ mod tests {
422370
423371 // Unpack into a new builder.
424372 let mut builder = PrimitiveBuilder :: < u32 > :: with_capacity ( Nullability :: Nullable , 5 ) ;
425- unpack_into_primitive_builder (
373+ unpack_map_into_builder :: < _ , _ , _ > (
426374 bitpacked. as_view ( ) ,
427375 & mut builder,
428376 & mut SESSION . create_execution_ctx ( ) ,
377+ |v| v,
429378 ) ?;
430379
431380 let result = builder. finish_into_primitive ( ) ;
@@ -459,10 +408,11 @@ mod tests {
459408
460409 // Unpack into a new builder.
461410 let mut builder = PrimitiveBuilder :: < u32 > :: with_capacity ( Nullability :: NonNullable , 100 ) ;
462- unpack_into_primitive_builder (
411+ unpack_map_into_builder :: < _ , _ , _ > (
463412 bitpacked. as_view ( ) ,
464413 & mut builder,
465414 & mut SESSION . create_execution_ctx ( ) ,
415+ |v| v,
466416 ) ?;
467417
468418 let result = builder. finish_into_primitive ( ) ;
0 commit comments