vortex_array/expr/stats/
precision.rs1use std::fmt::Debug;
5use std::fmt::Display;
6use std::fmt::Formatter;
7
8use vortex_dtype::DType;
9use vortex_error::VortexResult;
10use vortex_scalar::Scalar;
11use vortex_scalar::ScalarValue;
12
13use crate::expr::stats::precision::Precision::Exact;
14use crate::expr::stats::precision::Precision::Inexact;
15
16#[derive(Debug, PartialEq, Eq)]
24pub enum Precision<T> {
25 Exact(T),
26 Inexact(T),
27}
28
29impl<T> Clone for Precision<T>
30where
31 T: Clone,
32{
33 fn clone(&self) -> Self {
34 match self {
35 Exact(e) => Exact(e.clone()),
36 Inexact(ie) => Inexact(ie.clone()),
37 }
38 }
39}
40
41impl<T> Precision<Option<T>> {
42 pub fn transpose(self) -> Option<Precision<T>> {
44 match self {
45 Exact(Some(x)) => Some(Exact(x)),
46 Inexact(Some(x)) => Some(Inexact(x)),
47 Exact(None) | Inexact(None) => None,
48 }
49 }
50}
51
52impl<T> Precision<T>
53where
54 T: Copy,
55{
56 pub fn to_inexact(&self) -> Self {
57 match self {
58 Exact(v) => Exact(*v),
59 Inexact(v) => Inexact(*v),
60 }
61 }
62}
63
64impl<T> Precision<T> {
65 pub fn exact<S: Into<T>>(s: S) -> Precision<T> {
67 Exact(s.into())
68 }
69
70 pub fn inexact<S: Into<T>>(s: S) -> Precision<T> {
72 Inexact(s.into())
73 }
74
75 pub fn as_ref(&self) -> Precision<&T> {
77 match self {
78 Exact(val) => Exact(val),
79 Inexact(val) => Inexact(val),
80 }
81 }
82
83 pub fn into_inexact(self) -> Self {
85 match self {
86 Exact(val) => Inexact(val),
87 Inexact(_) => self,
88 }
89 }
90
91 pub fn as_exact(self) -> Option<T> {
93 match self {
94 Exact(val) => Some(val),
95 _ => None,
96 }
97 }
98
99 pub fn as_inexact(self) -> Option<T> {
101 match self {
102 Inexact(val) => Some(val),
103 _ => None,
104 }
105 }
106
107 pub fn is_exact(&self) -> bool {
109 matches!(self, Exact(_))
110 }
111
112 pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Precision<U> {
114 match self {
115 Exact(value) => Exact(f(value)),
116 Inexact(value) => Inexact(f(value)),
117 }
118 }
119
120 pub fn zip<U>(self, other: Precision<U>) -> Precision<(T, U)> {
122 match (self, other) {
123 (Exact(lhs), Exact(rhs)) => Exact((lhs, rhs)),
124 (Inexact(lhs), Exact(rhs))
125 | (Exact(lhs), Inexact(rhs))
126 | (Inexact(lhs), Inexact(rhs)) => Inexact((lhs, rhs)),
127 }
128 }
129
130 pub fn try_map<U, F: FnOnce(T) -> VortexResult<U>>(self, f: F) -> VortexResult<Precision<U>> {
132 let precision = match self {
133 Exact(value) => Exact(f(value)?),
134 Inexact(value) => Inexact(f(value)?),
135 };
136 Ok(precision)
137 }
138
139 pub fn into_inner(self) -> T {
141 match self {
142 Exact(val) | Inexact(val) => val,
143 }
144 }
145}
146
147impl<T: Display> Display for Precision<T> {
148 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
149 match self {
150 Exact(v) => {
151 write!(f, "{v}")
152 }
153 Inexact(v) => {
154 write!(f, "~{v}")
155 }
156 }
157 }
158}
159
160impl<T: PartialEq> PartialEq<T> for Precision<T> {
161 fn eq(&self, other: &T) -> bool {
162 match self {
163 Exact(v) => v == other,
164 _ => false,
165 }
166 }
167}
168
169impl Precision<ScalarValue> {
170 pub fn into_scalar(self, dtype: DType) -> Precision<Scalar> {
171 self.map(|v| Scalar::new(dtype, v))
172 }
173}
174
175impl Precision<&ScalarValue> {
176 pub fn into_scalar(self, dtype: DType) -> Precision<Scalar> {
177 self.map(|v| Scalar::new(dtype, v.clone()))
178 }
179}