Skip to content

Commit 56d3c9e

Browse files
committed
fix
Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
1 parent 6c248bb commit 56d3c9e

4 files changed

Lines changed: 29 additions & 77 deletions

File tree

encodings/fastlanes/src/bitpacking/array/bitpack_decompress.rs

Lines changed: 22 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -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<()>
9861
where
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();

encodings/fastlanes/src/bitpacking/compute/cast.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// SPDX-License-Identifier: Apache-2.0
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

4+
use num_traits::AsPrimitive;
45
use vortex_array::ArrayRef;
56
use vortex_array::ArrayView;
67
use vortex_array::ExecutionCtx;
@@ -17,7 +18,7 @@ use vortex_error::VortexResult;
1718

1819
use crate::bitpacking::BitPacked;
1920
use crate::bitpacking::array::BitPackedArrayExt;
20-
use crate::bitpacking::array::bitpack_decompress::unpack_and_cast_into_builder;
21+
use crate::bitpacking::array::bitpack_decompress::unpack_map_into_builder;
2122

2223
/// Returns `true` if casting `src` to `tgt` is a widening integer cast for which every value a
2324
/// bit-packed array can hold is guaranteed to be representable in `tgt` (so no per-value bounds
@@ -101,7 +102,7 @@ impl CastKernel for BitPacked {
101102
let result = match_each_integer_ptype!(tgt, |T| {
102103
let mut builder = PrimitiveBuilder::<T>::with_capacity(tgt_nullability, array.len());
103104
match_each_integer_ptype!(src, |F| {
104-
unpack_and_cast_into_builder::<F, T>(array, &mut builder, ctx)?;
105+
unpack_map_into_builder::<F, T, _>(array, &mut builder, ctx, |v: F| v.as_())?;
105106
});
106107
builder.finish_into_primitive().into_array()
107108
});

encodings/fastlanes/src/bitpacking/vtable/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use crate::BitPackedArrayExt;
4444
use crate::BitPackedData;
4545
use crate::BitPackedDataParts;
4646
use crate::bitpack_decompress::unpack_array;
47-
use crate::bitpack_decompress::unpack_into_primitive_builder;
47+
use crate::bitpack_decompress::unpack_map_into_builder;
4848
use crate::bitpacking::array::BitPackedSlots;
4949
use crate::bitpacking::array::BitPackedSlotsView;
5050
use crate::bitpacking::array::PATCH_SLOTS;
@@ -239,13 +239,14 @@ impl VTable for BitPacked {
239239
ctx: &mut ExecutionCtx,
240240
) -> VortexResult<()> {
241241
match_each_integer_ptype!(array.dtype().as_ptype(), |T| {
242-
unpack_into_primitive_builder::<T>(
242+
unpack_map_into_builder::<T, T, _>(
243243
array,
244244
builder
245245
.as_any_mut()
246246
.downcast_mut()
247247
.vortex_expect("bit packed array must canonicalize into a primitive array"),
248248
ctx,
249+
|v| v,
249250
)
250251
})
251252
}

encodings/fastlanes/src/for/array/for_decompress.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ pub(crate) fn fused_decompress<
119119
unpacked.decode_into(uninit_slice);
120120

121121
if let Some(patches) = bp.patches() {
122-
bitpack_decompress::apply_patches_to_uninit_range_fn(
122+
bitpack_decompress::apply_patches_to_uninit_range(
123123
&mut uninit_range,
124124
&patches,
125125
ctx,

0 commit comments

Comments
 (0)