vortex_array/aggregate_fn/fns/is_constant/
primitive.rs1use crate::arrays::PrimitiveArray;
5use crate::dtype::NativePType;
6use crate::dtype::half::f16;
7use crate::match_each_native_ptype;
8
9cfg_if::cfg_if! {
10 if #[cfg(target_feature = "avx2")] {
11 pub const IS_CONST_LANE_WIDTH: usize = 32;
12 } else {
13 pub const IS_CONST_LANE_WIDTH: usize = 16;
14 }
15}
16
17pub fn compute_is_constant<T: NativePType, const WIDTH: usize>(values: &[T]) -> bool {
20 let first_value = values[0];
21 let first_vec = &[first_value; WIDTH];
22
23 let (chunks, remainder) = values[1..].as_chunks::<WIDTH>();
24 for chunk in chunks {
25 if first_vec != chunk {
26 return false;
27 }
28 }
29
30 for value in remainder {
31 if !value.is_eq(first_value) {
32 return false;
33 }
34 }
35
36 true
37}
38
39trait EqFloat {
40 type IntType;
41}
42
43impl EqFloat for f16 {
44 type IntType = u16;
45}
46impl EqFloat for f32 {
47 type IntType = u32;
48}
49impl EqFloat for f64 {
50 type IntType = u64;
51}
52
53pub(super) fn check_primitive_constant(array: &PrimitiveArray) -> bool {
54 match_each_native_ptype!(array.ptype(), integral: |P| {
55 compute_is_constant::<_, {IS_CONST_LANE_WIDTH / size_of::<P>()}>(array.as_slice::<P>())
56 }, floating: |P| {
57 compute_is_constant::<_, {IS_CONST_LANE_WIDTH / size_of::<P>()}>(unsafe { std::mem::transmute::<&[P], &[<P as EqFloat>::IntType]>(array.as_slice::<P>()) })
58 })
59}