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