Skip to content

Commit e25e26d

Browse files
authored
Cleanup fastlanes encodings crate (#7118)
* Remove dead code only used in tests * Simplify signatures that needlessly return Results * Add test coverage for bit_transpose functions * Propagate patch offsets when compressing patches --------- Signed-off-by: Robert Kruszewski <github@robertk.io>
1 parent 5a11eee commit e25e26d

11 files changed

Lines changed: 164 additions & 265 deletions

File tree

encodings/fastlanes/public-api.lock

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub fn vortex_fastlanes::bitpack_compress::bitpack_primitive<T: vortex_array::dt
2626

2727
pub fn vortex_fastlanes::bitpack_compress::bitpack_to_best_bit_width(array: &vortex_array::arrays::primitive::array::PrimitiveArray) -> vortex_error::VortexResult<vortex_fastlanes::BitPackedArray>
2828

29-
pub unsafe fn vortex_fastlanes::bitpack_compress::bitpack_unchecked(parray: &vortex_array::arrays::primitive::array::PrimitiveArray, bit_width: u8) -> vortex_error::VortexResult<vortex_buffer::ByteBuffer>
29+
pub unsafe fn vortex_fastlanes::bitpack_compress::bitpack_unchecked(parray: &vortex_array::arrays::primitive::array::PrimitiveArray, bit_width: u8) -> vortex_buffer::ByteBuffer
3030

3131
pub fn vortex_fastlanes::bitpack_compress::find_best_bit_width(ptype: vortex_array::dtype::ptype::PType, bit_width_freq: &[usize]) -> vortex_error::VortexResult<u8>
3232

@@ -48,10 +48,6 @@ pub fn vortex_fastlanes::bitpack_decompress::unpack_single(array: &vortex_fastla
4848

4949
pub unsafe fn vortex_fastlanes::bitpack_decompress::unpack_single_primitive<T: vortex_array::dtype::ptype::NativePType + fastlanes::bitpacking::BitPacking>(packed: &[T], bit_width: usize, index_to_decode: usize) -> T
5050

51-
pub fn vortex_fastlanes::bitpack_decompress::unpack_to_primitive(array: &vortex_fastlanes::BitPackedArray) -> vortex_array::arrays::primitive::array::PrimitiveArray
52-
53-
pub fn vortex_fastlanes::bitpack_decompress::unpack_to_primitive_typed<P: vortex_fastlanes::unpack_iter::BitPacked>(array: &vortex_fastlanes::BitPackedArray) -> vortex_array::arrays::primitive::array::PrimitiveArray
54-
5551
pub mod vortex_fastlanes::unpack_iter
5652

5753
pub struct vortex_fastlanes::unpack_iter::BitPackingStrategy
@@ -380,11 +376,9 @@ pub fn vortex_fastlanes::DeltaArray::len(&self) -> usize
380376

381377
pub fn vortex_fastlanes::DeltaArray::offset(&self) -> usize
382378

383-
pub fn vortex_fastlanes::DeltaArray::try_from_delta_compress_parts(bases: vortex_array::array::ArrayRef, deltas: vortex_array::array::ArrayRef) -> vortex_error::VortexResult<Self>
384-
385379
pub fn vortex_fastlanes::DeltaArray::try_from_primitive_array(array: &vortex_array::arrays::primitive::array::PrimitiveArray, ctx: &mut vortex_array::executor::ExecutionCtx) -> vortex_error::VortexResult<Self>
386380

387-
pub fn vortex_fastlanes::DeltaArray::try_new(bases: vortex_array::array::ArrayRef, deltas: vortex_array::array::ArrayRef, offset: usize, logical_len: usize) -> vortex_error::VortexResult<Self>
381+
pub fn vortex_fastlanes::DeltaArray::try_new(bases: vortex_array::array::ArrayRef, deltas: vortex_array::array::ArrayRef, offset: usize, len: usize) -> vortex_error::VortexResult<Self>
388382

389383
impl vortex_fastlanes::DeltaArray
390384

encodings/fastlanes/src/bit_transpose/validity.rs

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ pub fn transpose_validity(validity: &Validity, ctx: &mut ExecutionCtx) -> Vortex
3737
}
3838
}
3939

40-
#[inline]
4140
pub fn transpose_bitbuffer(bits: BitBuffer) -> BitBuffer {
4241
let (offset, len, bytes) = bits.into_inner();
4342

@@ -79,11 +78,10 @@ pub fn untranspose_validity(validity: &Validity, ctx: &mut ExecutionCtx) -> Vort
7978
}
8079
}
8180

82-
#[inline]
8381
pub fn untranspose_bitbuffer(bits: BitBuffer) -> BitBuffer {
8482
assert!(
8583
bits.inner().len().is_multiple_of(128),
86-
"Transpose BitBuffer must be 128-byte aligned"
84+
"Transpose BitBuffer byte length must be a multiple of 128"
8785
);
8886
let (offset, len, bytes) = bits.into_inner();
8987
match bytes.try_into_mut() {
@@ -137,3 +135,58 @@ fn bits_op_with_copy<F: Fn(&[u8; 128], &mut [u8; 128])>(
137135
offset,
138136
)
139137
}
138+
139+
#[cfg(test)]
140+
mod tests {
141+
use vortex_buffer::BitBuffer;
142+
use vortex_buffer::BitBufferMut;
143+
use vortex_buffer::ByteBuffer;
144+
145+
use super::*;
146+
147+
fn make_validity_bits(num_bits: usize) -> BitBuffer {
148+
let mut builder = BitBufferMut::with_capacity(num_bits);
149+
for i in 0..num_bits {
150+
builder.append(i % 3 != 0);
151+
}
152+
builder.freeze()
153+
}
154+
155+
fn force_copy_path(bits: BitBuffer) -> (BitBuffer, ByteBuffer) {
156+
let (offset, len, bytes) = bits.into_inner();
157+
let extra_ref = bytes.clone();
158+
(BitBuffer::new_with_offset(bytes, len, offset), extra_ref)
159+
}
160+
161+
#[test]
162+
fn transpose_padding_copy_produces_same_bits() {
163+
let bits = make_validity_bits(500);
164+
let transposed = transpose_bitbuffer(bits.clone());
165+
assert_eq!(transposed.len(), 1024);
166+
let untransposed = untranspose_bitbuffer(transposed);
167+
assert_eq!(untransposed.slice(0..500), bits)
168+
}
169+
170+
#[test]
171+
fn transpose_inplace_and_copy_produce_same_bits() {
172+
let bits = make_validity_bits(2048);
173+
174+
let inplace_result = transpose_bitbuffer(bits.clone());
175+
176+
let (bits_shared, _hold) = force_copy_path(bits);
177+
let copy_result = transpose_bitbuffer(bits_shared);
178+
179+
assert_eq!(inplace_result.len(), copy_result.len());
180+
assert_eq!(inplace_result, copy_result);
181+
}
182+
183+
#[test]
184+
fn transpose_validity_roundtrip_non_aligned() {
185+
let original_len = 1500;
186+
let bits = make_validity_bits(original_len);
187+
188+
let transposed = transpose_bitbuffer(bits.clone());
189+
let roundtripped = untranspose_bitbuffer(transposed);
190+
assert_eq!(bits, roundtripped.slice(0..original_len));
191+
}
192+
}

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

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ pub fn bitpack_encode(
6565
}
6666

6767
// SAFETY: we check that array only contains non-negative values.
68-
let packed = unsafe { bitpack_unchecked(array, bit_width)? };
68+
let packed = unsafe { bitpack_unchecked(array, bit_width) };
6969
let patches = (num_exceptions > 0)
7070
.then(|| gather_patches(array, bit_width, num_exceptions))
7171
.transpose()?
@@ -103,7 +103,7 @@ pub unsafe fn bitpack_encode_unchecked(
103103
bit_width: u8,
104104
) -> VortexResult<BitPackedArray> {
105105
// SAFETY: non-negativity of input checked by caller.
106-
let packed = unsafe { bitpack_unchecked(&array, bit_width)? };
106+
let packed = unsafe { bitpack_unchecked(&array, bit_width) };
107107

108108
// SAFETY: checked by bitpack_unchecked
109109
let bitpacked = unsafe {
@@ -135,15 +135,11 @@ pub unsafe fn bitpack_encode_unchecked(
135135
///
136136
/// It is the caller's responsibility to ensure that `parray` is non-negative before calling
137137
/// this function.
138-
pub unsafe fn bitpack_unchecked(
139-
parray: &PrimitiveArray,
140-
bit_width: u8,
141-
) -> VortexResult<ByteBuffer> {
138+
pub unsafe fn bitpack_unchecked(parray: &PrimitiveArray, bit_width: u8) -> ByteBuffer {
142139
let parray = parray.reinterpret_cast(parray.ptype().to_unsigned());
143-
let packed = match_each_unsigned_integer_ptype!(parray.ptype(), |P| {
140+
match_each_unsigned_integer_ptype!(parray.ptype(), |P| {
144141
bitpack_primitive(parray.as_slice::<P>(), bit_width).into_byte_buffer()
145-
});
146-
Ok(packed)
142+
})
147143
}
148144

149145
/// Bitpack a slice of primitives down to the given width.

0 commit comments

Comments
 (0)