dashu_base/
approx.rs

1//! Trait definitions for approximated values
2
3/// Represent an calculation result with a possible error.
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum Approximation<T, E> {
6    /// The result is exact, contains the result value
7    Exact(T),
8
9    /// The result is inexact, contains the result value and error
10    Inexact(T, E),
11}
12
13impl<T, E> Approximation<T, E> {
14    /// Get the value of the calculation regardless of error
15    #[inline]
16    pub fn value(self) -> T {
17        match self {
18            Self::Exact(v) => v,
19            Self::Inexact(v, _) => v,
20        }
21    }
22
23    /// Get a reference to the calculation result
24    #[inline]
25    pub const fn value_ref(&self) -> &T {
26        match self {
27            Self::Exact(v) => v,
28            Self::Inexact(v, _) => v,
29        }
30    }
31
32    #[inline]
33    pub fn unwrap(self) -> T {
34        match self {
35            Self::Exact(val) => val,
36            Self::Inexact(_, _) => panic!("called `Approximation::unwrap()` on a `Inexact` value"),
37        }
38    }
39
40    #[inline]
41    pub fn error(self) -> Option<E> {
42        match self {
43            Self::Exact(_) => None,
44            Self::Inexact(_, e) => Some(e),
45        }
46    }
47
48    #[inline]
49    pub const fn error_ref(&self) -> Option<&E> {
50        match self {
51            Self::Exact(_) => None,
52            Self::Inexact(_, e) => Some(e),
53        }
54    }
55
56    #[inline]
57    pub fn map<U, F>(self, f: F) -> Approximation<U, E>
58    where
59        F: FnOnce(T) -> U,
60    {
61        match self {
62            Self::Exact(v) => Approximation::Exact(f(v)),
63            Self::Inexact(v, e) => Approximation::Inexact(f(v), e),
64        }
65    }
66
67    #[inline]
68    pub fn and_then<U, F>(self, f: F) -> Approximation<U, E>
69    where
70        F: FnOnce(T) -> Approximation<U, E>,
71    {
72        match self {
73            Self::Exact(v) => match f(v) {
74                Approximation::Exact(v2) => Approximation::Exact(v2),
75                Approximation::Inexact(v2, e) => Approximation::Inexact(v2, e),
76            },
77            Self::Inexact(v, e) => match f(v) {
78                Approximation::Exact(v2) => Approximation::Inexact(v2, e),
79                Approximation::Inexact(v2, e2) => Approximation::Inexact(v2, e2),
80            },
81        }
82    }
83}