• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vortex-data / vortex / 16598973893

29 Jul 2025 02:25PM UTC coverage: 82.692% (-0.01%) from 82.703%
16598973893

push

github

web-flow
Clean up stats propagation for slicing (#3356)

Reduces the amount we copy some stats (by removing into_iter that forces
a full stats copy)

---------

Signed-off-by: Nicholas Gates <nick@nickgates.com>
Signed-off-by: Robert Kruszewski <github@robertk.io>
Signed-off-by: Will Manning <will@willmanning.io>
Co-authored-by: Robert Kruszewski <github@robertk.io>
Co-authored-by: Will Manning <will@willmanning.io>

130 of 157 new or added lines in 15 files covered. (82.8%)

30 existing lines in 13 files now uncovered.

45215 of 54679 relevant lines covered (82.69%)

184610.34 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

62.35
/vortex-array/src/stats/precision.rs
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3

4
use std::fmt::{Debug, Display, Formatter};
5

6
use vortex_dtype::DType;
7
use vortex_error::VortexResult;
8
use vortex_scalar::{Scalar, ScalarValue};
9

10
use crate::stats::precision::Precision::{Exact, Inexact};
11

12
/// A statistic has a precision `Exact` or `Inexact`. This represents uncertainty in that value.
13
/// Exact values are computed, where can inexact values are likely inferred from compute functions.
14
///
15
/// Inexact statistics form a range of possible values that the statistic could be.
16
/// This is statistic specific, for max this will be an upper bound. Meaning that the actual max
17
/// in an array is guaranteed to be less than or equal to the inexact value, but equal to the exact
18
/// value.
19
#[derive(Debug, PartialEq, Eq)]
20
pub enum Precision<T> {
21
    Exact(T),
22
    Inexact(T),
23
}
24

25
impl<T> Clone for Precision<T>
26
where
27
    T: Clone,
28
{
29
    fn clone(&self) -> Self {
756,679✔
30
        match self {
756,679✔
31
            Exact(e) => Exact(e.clone()),
755,314✔
32
            Inexact(ie) => Inexact(ie.clone()),
1,365✔
33
        }
34
    }
756,679✔
35
}
36

37
impl<T> Precision<Option<T>> {
38
    /// Transpose the `Option<Precision<T>>` into `Option<Precision<T>>`.
39
    pub fn transpose(self) -> Option<Precision<T>> {
336✔
40
        match self {
336✔
41
            Exact(Some(x)) => Some(Exact(x)),
292✔
42
            Inexact(Some(x)) => Some(Inexact(x)),
×
43
            _ => None,
44✔
44
        }
45
    }
336✔
46
}
47

48
impl<T> Precision<T>
49
where
50
    T: Copy,
51
{
52
    pub fn to_inexact(&self) -> Self {
×
53
        match self {
×
54
            Exact(v) => Exact(*v),
×
55
            Inexact(v) => Inexact(*v),
×
56
        }
57
    }
×
58
}
59

60
impl<T> Precision<T> {
61
    /// Creates an exact value
62
    pub fn exact<S: Into<T>>(s: S) -> Precision<T> {
144,476✔
63
        Exact(s.into())
144,476✔
64
    }
144,476✔
65

66
    /// Creates an inexact value
67
    pub fn inexact<S: Into<T>>(s: S) -> Precision<T> {
194✔
68
        Inexact(s.into())
194✔
69
    }
194✔
70

71
    /// Pushed the ref into the Precision enum
72
    pub fn as_ref(&self) -> Precision<&T> {
12,188✔
73
        match self {
12,188✔
74
            Exact(val) => Exact(val),
12,188✔
75
            Inexact(val) => Inexact(val),
×
76
        }
77
    }
12,188✔
78

79
    /// Converts `self` into an inexact bound
80
    pub fn into_inexact(self) -> Self {
558✔
81
        match self {
558✔
82
            Exact(val) => Inexact(val),
558✔
83
            Inexact(_) => self,
×
84
        }
85
    }
558✔
86

87
    /// Returns the exact value from the bound, if that value is inexact, otherwise `None`.
88
    pub fn as_exact(self) -> Option<T> {
37,225✔
89
        match self {
37,225✔
90
            Exact(val) => Some(val),
37,225✔
UNCOV
91
            _ => None,
×
92
        }
93
    }
37,225✔
94

95
    /// Returns the exact value from the bound, if that value is inexact, otherwise `None`.
96
    pub fn as_inexact(self) -> Option<T> {
×
97
        match self {
×
98
            Inexact(val) => Some(val),
×
99
            _ => None,
×
100
        }
101
    }
×
102

103
    /// True iff self == Exact(_)
104
    pub fn is_exact(&self) -> bool {
24,908✔
105
        matches!(self, Exact(_))
24,908✔
106
    }
24,908✔
107

108
    /// Map the value of either precision value
109
    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Precision<U> {
224,552✔
110
        match self {
224,552✔
111
            Exact(value) => Exact(f(value)),
223,250✔
112
            Inexact(value) => Inexact(f(value)),
1,302✔
113
        }
114
    }
224,552✔
115

116
    /// Zip two `Precision` values into a tuple, keeping the inexactness if any.
117
    pub fn zip<U>(self, other: Precision<U>) -> Precision<(T, U)> {
467✔
118
        match (self, other) {
467✔
119
            (Exact(lhs), Exact(rhs)) => Exact((lhs, rhs)),
3✔
120
            (Inexact(lhs), Exact(rhs))
×
121
            | (Exact(lhs), Inexact(rhs))
176✔
122
            | (Inexact(lhs), Inexact(rhs)) => Inexact((lhs, rhs)),
464✔
123
        }
124
    }
467✔
125

126
    /// Similar to `map` but handles fucntions that can fail.
127
    pub fn try_map<U, F: FnOnce(T) -> VortexResult<U>>(self, f: F) -> VortexResult<Precision<U>> {
×
128
        let precision = match self {
×
129
            Exact(value) => Exact(f(value)?),
×
130
            Inexact(value) => Inexact(f(value)?),
×
131
        };
132
        Ok(precision)
×
133
    }
×
134

135
    /// Unwrap the underlying value
136
    pub fn into_inner(self) -> T {
24,426✔
137
        match self {
24,426✔
138
            Exact(val) | Inexact(val) => val,
24,426✔
139
        }
140
    }
24,426✔
141
}
142

143
impl<T: Display> Display for Precision<T> {
144
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
×
145
        match self {
×
146
            Exact(v) => {
×
147
                write!(f, "{v}")
×
148
            }
149
            Inexact(v) => {
×
150
                write!(f, "~{v}")
×
151
            }
152
        }
153
    }
×
154
}
155

156
impl<T: PartialEq> PartialEq<T> for Precision<T> {
157
    fn eq(&self, other: &T) -> bool {
1✔
158
        match self {
1✔
159
            Exact(v) => v == other,
1✔
160
            _ => false,
×
161
        }
162
    }
1✔
163
}
164

165
impl Precision<ScalarValue> {
166
    pub fn into_scalar(self, dtype: DType) -> Precision<Scalar> {
4,009✔
167
        self.map(|v| Scalar::new(dtype, v))
4,009✔
168
    }
4,009✔
169
}
170

171
impl Precision<&ScalarValue> {
172
    pub fn into_scalar(self, dtype: DType) -> Precision<Scalar> {
×
173
        self.map(|v| Scalar::new(dtype, v.clone()))
×
174
    }
×
175
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc