Skip to content

Commit

Permalink
unchecked namign
Browse files Browse the repository at this point in the history
  • Loading branch information
a10y committed Dec 18, 2024
1 parent 03a568a commit 3616dd9
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 24 deletions.
4 changes: 2 additions & 2 deletions encodings/fastlanes/src/bitpacking/compress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub fn bitpack_encode(array: PrimitiveArray, bit_width: u8) -> VortexResult<BitP

// SAFETY: values already checked to be non-negative.
unsafe {
BitPackedArray::try_new(
BitPackedArray::new_unchecked(
packed,
array.ptype(),
array.validity(),
Expand All @@ -73,7 +73,7 @@ pub unsafe fn bitpack_encode_unchecked(
unsafe {
let packed = bitpack_unchecked(&array, bit_width)?;

BitPackedArray::try_new(
BitPackedArray::new_unchecked(
packed,
array.ptype(),
array.validity(),
Expand Down
2 changes: 1 addition & 1 deletion encodings/fastlanes/src/bitpacking/compute/scalar_at.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ mod test {
fn invalid_patches() {
// SAFETY: using unsigned PType
let packed_array = unsafe {
BitPackedArray::try_new(
BitPackedArray::new_unchecked(
Buffer::from(vec![0u8; 128]),
PType::U32,
Validity::AllInvalid,
Expand Down
30 changes: 17 additions & 13 deletions encodings/fastlanes/src/bitpacking/compute/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,23 @@ impl SliceFn<BitPackedArray> for BitPackedEncoding {
let encoded_start = (block_start / 8) * array.bit_width() as usize;
let encoded_stop = (block_stop / 8) * array.bit_width() as usize;
// slice the buffer using the encoded start/stop values
BitPackedArray::try_new_from_offset(
array.packed().slice(encoded_start..encoded_stop),
array.ptype(),
array.validity().slice(start, stop)?,
array
.patches()
.map(|p| p.slice(start, stop))
.transpose()?
.flatten(),
array.bit_width(),
stop - start,
offset as u16,
)

// SAFETY: the invariants of the original BitPackedArray are preserved when slicing.
unsafe {
BitPackedArray::new_unchecked_with_offset(
array.packed().slice(encoded_start..encoded_stop),
array.ptype(),
array.validity().slice(start, stop)?,
array
.patches()
.map(|p| p.slice(start, stop))
.transpose()?
.flatten(),
array.bit_width(),
stop - start,
offset as u16,
)
}
.map(|a| a.into_array())
}
}
Expand Down
46 changes: 39 additions & 7 deletions encodings/fastlanes/src/bitpacking/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use std::fmt::{Debug, Display};
use std::sync::Arc;

use ::serde::{Deserialize, Serialize};
pub use compress::*;
use fastlanes::BitPacking;
use ::serde::{Deserialize, Serialize};
use vortex_array::array::PrimitiveArray;
use vortex_array::encoding::ids;
use vortex_array::patches::{Patches, PatchesMetadata};
Expand Down Expand Up @@ -43,22 +43,40 @@ impl BitPackedArray {
///
/// The packed data should be interpreted as a sequence of values with size `bit_width`.
///
/// # Errors
///
/// This method returns errors if any of the metadata is inconsistent, for example the packed
/// buffer provided does not have the right size according to the supplied length and target
/// PType.
///
/// # Safety
///
/// If `ptype` is signed, `packed` may **not** contain any values that once unpacked would
/// be interpreted as negative.
pub unsafe fn try_new(
/// For signed arrays, it is the caller's responsibility to ensure that there are no values
/// that can be interpreted once unpacked to the provided PType.
///
/// This invariant is upheld by the compressor, but callers must ensure this if they wish to
/// construct a new `BitPackedArray` from parts.
///
/// See also the [`encode`][Self::encode] method on this type for a safe path to create a new
/// bit-packed array.
pub unsafe fn new_unchecked(
packed: Buffer,
ptype: PType,
validity: Validity,
patches: Option<Patches>,
bit_width: u8,
len: usize,
) -> VortexResult<Self> {
Self::try_new_from_offset(packed, ptype, validity, patches, bit_width, len, 0)
// SAFETY: checked by caller.
unsafe {
Self::new_unchecked_with_offset(packed, ptype, validity, patches, bit_width, len, 0)
}
}

pub(crate) fn try_new_from_offset(
/// An unsafe constructor for a `BitPackedArray` that also specifies a slicing offset.
///
/// See also [`new_unchecked`][Self::new_unchecked].
pub(crate) unsafe fn new_unchecked_with_offset(
packed: Buffer,
ptype: PType,
validity: Validity,
Expand Down Expand Up @@ -187,6 +205,17 @@ impl BitPackedArray {
})
}

/// Bit-pack an array of primitive integers down to the target bit-width using the FastLanes
/// SIMD-accelerated packing kernels.
///
/// # Errors
///
/// If the provided array is not an integer type, an error will be returned.
///
/// If the provided array contains negative values, an error will be returned.
///
/// If the requested bit-width for packing is larger than the array's native width, an
/// error will be returned.
pub fn encode(array: &ArrayData, bit_width: u8) -> VortexResult<Self> {
if let Ok(parray) = PrimitiveArray::try_from(array.clone()) {
bitpack_encode(parray, bit_width)
Expand All @@ -195,8 +224,11 @@ impl BitPackedArray {
}
}

/// Calculate the maximum value that **can** be contained by this array, given its bit-width.
///
/// Note that this value need not actually be present in the array.
#[inline]
pub fn max_packed_value(&self) -> usize {
fn max_packed_value(&self) -> usize {
(1 << self.bit_width()) - 1
}
}
Expand Down
2 changes: 1 addition & 1 deletion vortex-sampling-compressor/src/compressors/bitpacked.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ impl EncodingCompressor for BitPackedCompressor {
Ok(CompressedArray::compressed(
// SAFETY: we ensure the array contains no negative values.
unsafe {
BitPackedArray::try_new(
BitPackedArray::new_unchecked(
packed_buffer,
parray.ptype(),
validity,
Expand Down

0 comments on commit 3616dd9

Please sign in to comment.