vortex_array/stats/
precision.rs1use std::fmt::{Debug, Display, Formatter};
5
6use vortex_dtype::DType;
7use vortex_error::VortexResult;
8use vortex_scalar::{Scalar, ScalarValue};
9
10use crate::stats::precision::Precision::{Exact, Inexact};
11
12#[derive(Debug, PartialEq, Eq)]
20pub enum Precision<T> {
21 Exact(T),
22 Inexact(T),
23}
24
25impl<T> Clone for Precision<T>
26where
27 T: Clone,
28{
29 fn clone(&self) -> Self {
30 match self {
31 Exact(e) => Exact(e.clone()),
32 Inexact(ie) => Inexact(ie.clone()),
33 }
34 }
35}
36
37impl<T> Precision<Option<T>> {
38 pub fn transpose(self) -> Option<Precision<T>> {
40 match self {
41 Exact(Some(x)) => Some(Exact(x)),
42 Inexact(Some(x)) => Some(Inexact(x)),
43 _ => None,
44 }
45 }
46}
47
48impl<T> Precision<T>
49where
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
60impl<T> Precision<T> {
61 pub fn exact<S: Into<T>>(s: S) -> Precision<T> {
63 Exact(s.into())
64 }
65
66 pub fn inexact<S: Into<T>>(s: S) -> Precision<T> {
68 Inexact(s.into())
69 }
70
71 pub fn as_ref(&self) -> Precision<&T> {
73 match self {
74 Exact(val) => Exact(val),
75 Inexact(val) => Inexact(val),
76 }
77 }
78
79 pub fn into_inexact(self) -> Self {
81 match self {
82 Exact(val) => Inexact(val),
83 Inexact(_) => self,
84 }
85 }
86
87 pub fn as_exact(self) -> Option<T> {
89 match self {
90 Exact(val) => Some(val),
91 _ => None,
92 }
93 }
94
95 pub fn as_inexact(self) -> Option<T> {
97 match self {
98 Inexact(val) => Some(val),
99 _ => None,
100 }
101 }
102
103 pub fn is_exact(&self) -> bool {
105 matches!(self, Exact(_))
106 }
107
108 pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Precision<U> {
110 match self {
111 Exact(value) => Exact(f(value)),
112 Inexact(value) => Inexact(f(value)),
113 }
114 }
115
116 pub fn zip<U>(self, other: Precision<U>) -> Precision<(T, U)> {
118 match (self, other) {
119 (Exact(lhs), Exact(rhs)) => Exact((lhs, rhs)),
120 (Inexact(lhs), Exact(rhs))
121 | (Exact(lhs), Inexact(rhs))
122 | (Inexact(lhs), Inexact(rhs)) => Inexact((lhs, rhs)),
123 }
124 }
125
126 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 pub fn into_inner(self) -> T {
137 match self {
138 Exact(val) | Inexact(val) => val,
139 }
140 }
141}
142
143impl<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
156impl<T: PartialEq> PartialEq<T> for Precision<T> {
157 fn eq(&self, other: &T) -> bool {
158 match self {
159 Exact(v) => v == other,
160 _ => false,
161 }
162 }
163}
164
165impl Precision<ScalarValue> {
166 pub fn into_scalar(self, dtype: DType) -> Precision<Scalar> {
167 self.map(|v| Scalar::new(dtype, v))
168 }
169}
170
171impl Precision<&ScalarValue> {
172 pub fn into_scalar(self, dtype: DType) -> Precision<Scalar> {
173 self.map(|v| Scalar::new(dtype, v.clone()))
174 }
175}