vortex_fastlanes/bitpacking/vtable/
encode.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use vortex_array::Canonical;
5use vortex_array::vtable::EncodeVTable;
6use vortex_error::VortexResult;
7
8use crate::BitPackedArray;
9use crate::BitPackedVTable;
10use crate::bitpack_compress;
11
12impl EncodeVTable<BitPackedVTable> for BitPackedVTable {
13    fn encode(
14        _vtable: &BitPackedVTable,
15        canonical: &Canonical,
16        like: Option<&BitPackedArray>,
17    ) -> VortexResult<Option<BitPackedArray>> {
18        let parray = canonical.clone().into_primitive();
19
20        let bit_width = like
21            .map(|like_array| like_array.bit_width())
22            // Only reuse the bitwidth if its smaller than the array's original bitwidth.
23            .filter(|bw| (*bw as usize) < parray.ptype().bit_width());
24
25        // In our current benchmark suite this seems to be the faster option,
26        // but it has an unbounded worst-case where some array becomes all patches.
27        let (bit_width, bit_width_histogram) = match bit_width {
28            Some(bw) => (bw, None),
29            None => {
30                let histogram = bitpack_compress::bit_width_histogram(&parray)?;
31                let bit_width = bitpack_compress::find_best_bit_width(parray.ptype(), &histogram)?;
32                (bit_width, Some(histogram))
33            }
34        };
35
36        if bit_width as usize == parray.ptype().bit_width()
37            || parray.ptype().is_signed_int()
38                && parray.statistics().compute_min::<i64>().unwrap_or_default() < 0
39        {
40            // Bit-packed compression not supported.
41            return Ok(None);
42        }
43
44        Ok(Some(bitpack_compress::bitpack_encode(
45            &parray,
46            bit_width,
47            bit_width_histogram.as_deref(),
48        )?))
49    }
50}