Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ rstest = "0.26.1"
rstest_reuse = "0.7.0"
rustc-hash = "2.1.1"
rustix = { version = "1.1", features = ["fs"] }
seq-macro = "0.3.6"
serde = "1.0.221"
serde_json = "1.0.138"
serde_test = "1.0.176"
Expand Down
1 change: 1 addition & 0 deletions encodings/fastlanes/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ lending-iterator = { workspace = true }
num-traits = { workspace = true }
prost = { workspace = true }
rand = { workspace = true, optional = true }
seq-macro = { workspace = true }
vortex-array = { workspace = true }
vortex-buffer = { workspace = true }
vortex-error = { workspace = true }
Expand Down
22 changes: 11 additions & 11 deletions encodings/fastlanes/src/bitpacking/array/bitpack_compress.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright the Vortex contributors

use fastlanes::BitPacking;
use itertools::Itertools;
use num_traits::PrimInt;
use vortex_array::ArrayView;
Expand Down Expand Up @@ -30,6 +29,7 @@ use vortex_mask::Mask;
use crate::BitPacked;
use crate::BitPackedArray;
use crate::bitpack_decompress;
use crate::bitpacking::array::kernels::BitPackedPhysical;

pub fn bitpack_to_best_bit_width(
array: &PrimitiveArray,
Expand Down Expand Up @@ -143,10 +143,11 @@ pub unsafe fn bitpack_unchecked(parray: &PrimitiveArray, bit_width: u8) -> ByteB
/// Bitpack a slice of primitives down to the given width.
///
/// See `bitpack` for more caller information.
pub fn bitpack_primitive<T: NativePType + BitPacking>(array: &[T], bit_width: u8) -> Buffer<T> {
pub fn bitpack_primitive<T: BitPackedPhysical>(array: &[T], bit_width: u8) -> Buffer<T> {
if bit_width == 0 {
return Buffer::<T>::empty();
}
let pack = T::resolve_pack(bit_width);
let bit_width = bit_width as usize;

// How many fastlanes vectors we will process.
Expand All @@ -164,14 +165,15 @@ pub fn bitpack_primitive<T: NativePType + BitPacking>(array: &[T], bit_width: u8
(0..num_full_chunks).for_each(|i| {
let start_elem = i * 1024;
let output_len = output.len();
// SAFETY: The capacity holds every block, so the new slots exist; the input is exactly
// 1024 values and the output exactly one block, which `pack` fully initializes.
unsafe {
output.set_len(output_len + packed_len);
BitPacking::unchecked_pack(
bit_width,
pack(
&array[start_elem..][..1024],
&mut output[output_len..][..packed_len],
);
};
}
});

// Pad the last chunk with zeros to a full 1024 elements.
Expand All @@ -181,14 +183,12 @@ pub fn bitpack_primitive<T: NativePType + BitPacking>(array: &[T], bit_width: u8
last_chunk[..last_chunk_size].copy_from_slice(&array[array.len() - last_chunk_size..]);

let output_len = output.len();
// SAFETY: The capacity holds every block, so the new slots exist; the input is exactly
// 1024 values and the output exactly one block, which `pack` fully initializes.
unsafe {
output.set_len(output_len + packed_len);
BitPacking::unchecked_pack(
bit_width,
&last_chunk,
&mut output[output_len..][..packed_len],
);
};
pack(&last_chunk, &mut output[output_len..][..packed_len]);
}
}

output.freeze()
Expand Down
40 changes: 20 additions & 20 deletions encodings/fastlanes/src/bitpacking/array/bitpack_decompress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

use std::mem::MaybeUninit;

use fastlanes::BitPacking;
use itertools::Itertools;
use num_traits::AsPrimitive;
use vortex_array::ArrayView;
Expand All @@ -22,6 +21,8 @@ use vortex_error::VortexResult;

use crate::BitPacked;
use crate::BitPackedArrayExt;
use crate::bitpacking::array::kernels::BitPackedKernels;
use crate::bitpacking::array::kernels::BitPackedPhysical;
use crate::unpack_iter::BitPacked as BitPackedUnpack;
use crate::unpack_iter::BitUnpackedChunks;

Expand Down Expand Up @@ -159,39 +160,38 @@ pub(crate) fn apply_patches_to_uninit_range<S: NativePType, T: NativePType, F: F
}

pub fn unpack_single(array: ArrayView<'_, BitPacked>, index: usize) -> Scalar {
let bit_width = array.bit_width() as usize;
let ptype = array.dtype().as_ptype();
// let packed = array.packed().into_primitive()?;
let index_in_encoded = index + array.offset() as usize;
let scalar: Scalar = match_each_unsigned_integer_ptype!(ptype.to_unsigned(), |P| {
unsafe {
unpack_single_primitive::<P>(array.packed_slice::<P>(), bit_width, index_in_encoded)
.into()
}
unpack_single_primitive::<P>(
array.kernels::<P>(),
array.packed_slice::<P>(),
index_in_encoded,
)
.into()
});
// Cast to fix signedness and nullability
scalar.cast(array.dtype()).vortex_expect("cast failure")
}

/// # Safety
/// Unpacks the value at `index_to_decode` from `packed`, a buffer of whole FastLanes blocks
/// packed at the bit width `kernels` were resolved for.
///
/// The caller must ensure the following invariants hold:
/// * `packed.len() == (length + 1023) / 1024 * 128 * bit_width`
/// * `index_to_decode < length`
/// # Panics
///
/// Where `length` is the length of the array/slice backed by `packed`
/// (but is not provided to this function).
pub unsafe fn unpack_single_primitive<T: NativePType + BitPacking>(
packed: &[T],
bit_width: usize,
/// If `index_to_decode` falls outside the blocks held by `packed`.
pub fn unpack_single_primitive<P: BitPackedPhysical>(
kernels: BitPackedKernels<P>,
packed: &[P],
index_to_decode: usize,
) -> T {
) -> P {
let chunk_index = index_to_decode / 1024;
let index_in_chunk = index_to_decode % 1024;
let elems_per_chunk: usize = 128 * bit_width / size_of::<T>();
let elems_per_chunk = kernels.packed_block_len();

let packed_chunk = &packed[chunk_index * elems_per_chunk..][0..elems_per_chunk];
unsafe { BitPacking::unchecked_unpack_single(bit_width, packed_chunk, index_in_chunk) }
let packed_chunk = &packed[chunk_index * elems_per_chunk..][..elems_per_chunk];
// SAFETY: `packed_chunk` is exactly one block at the width `kernels` were resolved for.
unsafe { (kernels.unpack_single)(packed_chunk, index_in_chunk) }
}

pub fn count_exceptions(bit_width: u8, bit_width_freq: &[usize]) -> usize {
Expand Down
Loading
Loading