-
Notifications
You must be signed in to change notification settings - Fork 149
Expand file tree
/
Copy pathnan_count.rs
More file actions
65 lines (56 loc) · 1.96 KB
/
nan_count.rs
File metadata and controls
65 lines (56 loc) · 1.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use vortex_error::{VortexExpect, VortexResult, vortex_bail};
use vortex_scalar::ScalarValue;
use crate::stats::{Precision, Stat};
use crate::{Array, Encoding};
/// Computes the min and max of an array, returning the (min, max) values
/// If the array is empty or has only nulls, the result is `None`.
pub trait NaNCountFn<A> {
fn nan_count(&self, array: A) -> VortexResult<Option<usize>>;
}
impl<E: Encoding> NaNCountFn<&dyn Array> for E
where
E: for<'a> NaNCountFn<&'a E::Array>,
{
fn nan_count(&self, array: &dyn Array) -> VortexResult<Option<usize>> {
let array_ref = array
.as_any()
.downcast_ref::<E::Array>()
.vortex_expect("Failed to downcast array");
NaNCountFn::nan_count(self, array_ref)
}
}
/// Computes the nunmber of NaN values in the array
/// This will update the stats set of this array (as a side effect).
pub fn nan_count(array: &dyn Array) -> VortexResult<Option<usize>> {
if array.is_empty() || array.valid_count()? == 0 {
return Ok(Some(0));
}
let nan_count = array
.statistics()
.get_as::<usize>(Stat::NaNCount)
.and_then(Precision::as_exact);
if let Some(nan_count) = nan_count {
return Ok(Some(nan_count));
}
// Only float arrays can have NaNs
let nan_count = if !array.dtype().is_float() {
Some(0)
} else if let Some(fn_) = array.vtable().nan_count_fn() {
fn_.nan_count(array)?
} else {
let canonical = array.to_canonical()?;
if let Some(fn_) = canonical.as_ref().vtable().nan_count_fn() {
fn_.nan_count(canonical.as_ref())?
} else {
vortex_bail!(NotImplemented: "nan_count", array.encoding());
}
};
if let Some(nan_count) = nan_count {
// Update the stats set with the computed min/max
array.statistics().set(
Stat::NaNCount,
Precision::Exact(ScalarValue::from(nan_count)),
);
}
Ok(nan_count)
}