vortex_array/arrays/bool/compute/
is_constant.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use vortex_error::VortexResult;
5
6use crate::arrays::{BoolArray, BoolVTable};
7use crate::compute::{IsConstantKernel, IsConstantKernelAdapter, IsConstantOpts};
8use crate::register_kernel;
9
10impl IsConstantKernel for BoolVTable {
11    fn is_constant(&self, array: &BoolArray, opts: &IsConstantOpts) -> VortexResult<Option<bool>> {
12        // If the array is small, then it is a constant time operation.
13        if opts.is_negligible_cost() && array.len() > 64 {
14            return Ok(None);
15        }
16
17        let buffer = array.boolean_buffer();
18
19        // Safety:
20        // We must have at least one value at this point
21        let first_value = unsafe { buffer.value_unchecked(0) };
22        let value_block = if first_value { u64::MAX } else { 0_u64 };
23
24        let bit_chunks = buffer.bit_chunks();
25        let packed = bit_chunks.iter().all(|chunk| chunk == value_block);
26        let reminder = bit_chunks.remainder_bits().count_ones() as usize
27            == bit_chunks.remainder_len() * (first_value as usize);
28
29        // We iterate on blocks of u64
30        Ok(Some(packed & reminder))
31    }
32}
33
34register_kernel!(IsConstantKernelAdapter(BoolVTable).lift());
35
36#[cfg(test)]
37mod tests {
38    use rstest::rstest;
39
40    use super::*;
41
42    #[rstest]
43    #[case(vec![true], true)]
44    #[case(vec![false; 65], true)]
45    #[case({
46        let mut v = vec![true; 64];
47        v.push(false);
48        v
49    }, false)]
50    fn test_is_constant(#[case] input: Vec<bool>, #[case] expected: bool) {
51        let array = BoolArray::from_iter(input);
52        assert_eq!(array.is_constant(), expected);
53    }
54}