vortex_array/arrays/chunked/compute/
is_constant.rs
1use vortex_error::{VortexExpect, VortexResult};
2
3use crate::Array;
4use crate::arrays::{ChunkedArray, ChunkedEncoding};
5use crate::compute::{IsConstantFn, IsConstantOpts, is_constant_opts, scalar_at};
6
7impl IsConstantFn<&ChunkedArray> for ChunkedEncoding {
8 fn is_constant(
9 &self,
10 array: &ChunkedArray,
11 opts: &IsConstantOpts,
12 ) -> VortexResult<Option<bool>> {
13 let mut chunks = array.chunks().iter().skip_while(|c| c.is_empty());
14
15 let first_chunk = chunks.next().vortex_expect("Must have at least one value");
16
17 if !is_constant_opts(first_chunk, opts)? {
18 return Ok(Some(false));
19 }
20
21 let first_value = scalar_at(first_chunk, 0)?.into_nullable();
22
23 for chunk in chunks {
24 if chunk.is_empty() {
25 continue;
26 }
27
28 if !is_constant_opts(chunk, opts)? {
29 return Ok(Some(false));
30 }
31
32 if first_value != scalar_at(chunk, 0)?.into_nullable() {
33 return Ok(Some(false));
34 }
35 }
36
37 Ok(Some(true))
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use vortex_buffer::{Buffer, buffer};
44 use vortex_dtype::{DType, Nullability, PType};
45
46 use crate::arrays::ChunkedArray;
47 use crate::{Array, IntoArray};
48
49 #[test]
50 fn empty_chunk_is_constant() {
51 let chunked = ChunkedArray::try_new(
52 vec![
53 Buffer::<u8>::empty().into_array(),
54 Buffer::<u8>::empty().into_array(),
55 buffer![255u8, 255].into_array(),
56 Buffer::<u8>::empty().into_array(),
57 buffer![255u8, 255].into_array(),
58 ],
59 DType::Primitive(PType::U8, Nullability::NonNullable),
60 )
61 .unwrap()
62 .into_array();
63
64 assert!(chunked.statistics().compute_is_constant().unwrap());
65 }
66}