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