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