Skip to main content

vortex_array/arrays/primitive/array/
top_value.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use std::hash::Hash;
5
6use rustc_hash::FxBuildHasher;
7use vortex_error::VortexExpect;
8use vortex_error::VortexResult;
9use vortex_mask::AllOr;
10use vortex_mask::Mask;
11use vortex_utils::aliases::hash_map::HashMap;
12
13use crate::arrays::PrimitiveArray;
14use crate::arrays::primitive::NativeValue;
15use crate::dtype::NativePType;
16use crate::match_each_native_ptype;
17use crate::scalar::PValue;
18use crate::validity::Validity;
19
20impl PrimitiveArray {
21    /// Compute most common present value of this array
22    pub fn top_value(&self) -> VortexResult<Option<(PValue, usize)>> {
23        if self.is_empty() {
24            return Ok(None);
25        }
26
27        if matches!(self.validity()?, Validity::AllInvalid) {
28            return Ok(None);
29        }
30
31        match_each_native_ptype!(self.ptype(), |P| {
32            let (top, count) = typed_top_value(self.as_slice::<P>(), self.validity_mask()?);
33            Ok(Some((top.into(), count)))
34        })
35    }
36}
37
38fn typed_top_value<T>(values: &[T], mask: Mask) -> (T, usize)
39where
40    T: NativePType,
41    NativeValue<T>: Eq + Hash,
42{
43    let mut distinct_values: HashMap<NativeValue<T>, usize, FxBuildHasher> =
44        HashMap::with_hasher(FxBuildHasher);
45    match mask.indices() {
46        AllOr::All => {
47            for value in values.iter().copied() {
48                *distinct_values.entry(NativeValue(value)).or_insert(0) += 1;
49            }
50        }
51        AllOr::None => unreachable!("All invalid arrays should be handled earlier"),
52        AllOr::Some(idxs) => {
53            for &i in idxs {
54                *distinct_values
55                    .entry(NativeValue(unsafe { *values.get_unchecked(i) }))
56                    .or_insert(0) += 1
57            }
58        }
59    }
60
61    let (&top_value, &top_count) = distinct_values
62        .iter()
63        .max_by_key(|&(_, &count)| count)
64        .vortex_expect("non-empty");
65    (top_value.0, top_count)
66}