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