vortex_array/arrays/chunked/compute/
is_constant.rs1use vortex_error::{VortexExpect, VortexResult};
2
3use crate::arrays::{ChunkedArray, ChunkedVTable};
4use crate::compute::{IsConstantKernel, IsConstantKernelAdapter, IsConstantOpts, is_constant_opts};
5use crate::{Array, register_kernel};
6
7impl IsConstantKernel for ChunkedVTable {
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 match is_constant_opts(first_chunk, opts)? {
18 None => return Ok(None),
20 Some(false) => return Ok(Some(false)),
21 Some(true) => {}
22 }
23
24 let first_value = first_chunk.scalar_at(0)?.into_nullable();
25
26 for chunk in chunks {
27 if chunk.is_empty() {
28 continue;
29 }
30
31 match is_constant_opts(chunk, opts)? {
32 None => return Ok(None),
34 Some(false) => return Ok(Some(false)),
35 Some(true) => {}
36 }
37
38 if first_value != chunk.scalar_at(0)?.into_nullable() {
39 return Ok(Some(false));
40 }
41 }
42
43 Ok(Some(true))
44 }
45}
46
47register_kernel!(IsConstantKernelAdapter(ChunkedVTable).lift());
48
49#[cfg(test)]
50mod tests {
51 use vortex_buffer::{Buffer, buffer};
52 use vortex_dtype::{DType, Nullability, PType};
53
54 use crate::arrays::ChunkedArray;
55 use crate::{Array, IntoArray};
56
57 #[test]
58 fn empty_chunk_is_constant() {
59 let chunked = ChunkedArray::try_new(
60 vec![
61 Buffer::<u8>::empty().into_array(),
62 Buffer::<u8>::empty().into_array(),
63 buffer![255u8, 255].into_array(),
64 Buffer::<u8>::empty().into_array(),
65 buffer![255u8, 255].into_array(),
66 ],
67 DType::Primitive(PType::U8, Nullability::NonNullable),
68 )
69 .unwrap()
70 .into_array();
71
72 assert!(chunked.statistics().compute_is_constant().unwrap());
73 }
74}