Skip to main content

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    /// Return the value if the result is exact, panic otherwise.
33    #[inline]
34    pub fn unwrap(self) -> T {
35        match self {
36            Self::Exact(val) => val,
37            Self::Inexact(_, _) => panic!("called `Approximation::unwrap()` on a `Inexact` value"),
38        }
39    }
40
41    /// Return the error if the result is inexact, [`None`] if it is exact.
42    #[inline]
43    pub fn error(self) -> Option<E> {
44        match self {
45            Self::Exact(_) => None,
46            Self::Inexact(_, e) => Some(e),
47        }
48    }
49
50    /// Borrow the error if the result is inexact, [`None`] if it is exact.
51    #[inline]
52    pub const fn error_ref(&self) -> Option<&E> {
53        match self {
54            Self::Exact(_) => None,
55            Self::Inexact(_, e) => Some(e),
56        }
57    }
58
59    /// Map the result value to a new type, preserving the error (if any).
60    #[inline]
61    pub fn map<U, F>(self, f: F) -> Approximation<U, E>
62    where
63        F: FnOnce(T) -> U,
64    {
65        match self {
66            Self::Exact(v) => Approximation::Exact(f(v)),
67            Self::Inexact(v, e) => Approximation::Inexact(f(v), e),
68        }
69    }
70
71    /// Chain a fallible mapping that itself returns an [`Approximation`], combining the
72    /// errors: an inexact input or an inexact result both yield an inexact result.
73    #[inline]
74    pub fn and_then<U, F>(self, f: F) -> Approximation<U, E>
75    where
76        F: FnOnce(T) -> Approximation<U, E>,
77    {
78        match self {
79            Self::Exact(v) => match f(v) {
80                Approximation::Exact(v2) => Approximation::Exact(v2),
81                Approximation::Inexact(v2, e) => Approximation::Inexact(v2, e),
82            },
83            Self::Inexact(v, e) => match f(v) {
84                Approximation::Exact(v2) => Approximation::Inexact(v2, e),
85                Approximation::Inexact(v2, e2) => Approximation::Inexact(v2, e2),
86            },
87        }
88    }
89}