approx/
abs_diff_eq.rs

1use core::cell;
2#[cfg(feature = "num-complex")]
3use num_complex::Complex;
4
5/// Equality that is defined using the absolute difference of two numbers.
6pub trait AbsDiffEq<Rhs = Self>: PartialEq<Rhs>
7where
8    Rhs: ?Sized,
9{
10    /// Used for specifying relative comparisons.
11    type Epsilon;
12
13    /// The default tolerance to use when testing values that are close together.
14    ///
15    /// This is used when no `epsilon` value is supplied to the [`abs_diff_eq!`], [`relative_eq!`],
16    /// or [`ulps_eq!`] macros.
17    fn default_epsilon() -> Self::Epsilon;
18
19    /// A test for equality that uses the absolute difference to compute the approximate
20    /// equality of two numbers.
21    fn abs_diff_eq(&self, other: &Rhs, epsilon: Self::Epsilon) -> bool;
22
23    /// The inverse of [`AbsDiffEq::abs_diff_eq`].
24    fn abs_diff_ne(&self, other: &Rhs, epsilon: Self::Epsilon) -> bool {
25        !Self::abs_diff_eq(self, other, epsilon)
26    }
27}
28
29///////////////////////////////////////////////////////////////////////////////////////////////////
30// Base implementations
31///////////////////////////////////////////////////////////////////////////////////////////////////
32
33macro_rules! impl_unsigned_abs_diff_eq {
34    ($T:ident, $default_epsilon:expr) => {
35        impl AbsDiffEq for $T {
36            type Epsilon = $T;
37
38            #[inline]
39            fn default_epsilon() -> $T {
40                $default_epsilon
41            }
42
43            #[inline]
44            fn abs_diff_eq(&self, other: &$T, epsilon: $T) -> bool {
45                (if self > other {
46                    self - other
47                } else {
48                    other - self
49                }) <= epsilon
50            }
51        }
52    };
53}
54
55impl_unsigned_abs_diff_eq!(u8, 0);
56impl_unsigned_abs_diff_eq!(u16, 0);
57impl_unsigned_abs_diff_eq!(u32, 0);
58impl_unsigned_abs_diff_eq!(u64, 0);
59impl_unsigned_abs_diff_eq!(usize, 0);
60
61macro_rules! impl_signed_abs_diff_eq {
62    ($T:ident, $default_epsilon:expr) => {
63        impl AbsDiffEq for $T {
64            type Epsilon = $T;
65
66            #[inline]
67            fn default_epsilon() -> $T {
68                $default_epsilon
69            }
70
71            #[inline]
72            #[allow(unused_imports)]
73            fn abs_diff_eq(&self, other: &$T, epsilon: $T) -> bool {
74                use num_traits::float::FloatCore;
75                $T::abs(self - other) <= epsilon
76            }
77        }
78    };
79}
80
81impl_signed_abs_diff_eq!(i8, 0);
82impl_signed_abs_diff_eq!(i16, 0);
83impl_signed_abs_diff_eq!(i32, 0);
84impl_signed_abs_diff_eq!(i64, 0);
85impl_signed_abs_diff_eq!(isize, 0);
86impl_signed_abs_diff_eq!(f32, core::f32::EPSILON);
87impl_signed_abs_diff_eq!(f64, core::f64::EPSILON);
88
89///////////////////////////////////////////////////////////////////////////////////////////////////
90// Derived implementations
91///////////////////////////////////////////////////////////////////////////////////////////////////
92
93impl<'a, T: AbsDiffEq + ?Sized> AbsDiffEq for &'a T {
94    type Epsilon = T::Epsilon;
95
96    #[inline]
97    fn default_epsilon() -> T::Epsilon {
98        T::default_epsilon()
99    }
100
101    #[inline]
102    fn abs_diff_eq(&self, other: &&'a T, epsilon: T::Epsilon) -> bool {
103        T::abs_diff_eq(*self, *other, epsilon)
104    }
105}
106
107impl<'a, T: AbsDiffEq + ?Sized> AbsDiffEq for &'a mut T {
108    type Epsilon = T::Epsilon;
109
110    #[inline]
111    fn default_epsilon() -> T::Epsilon {
112        T::default_epsilon()
113    }
114
115    #[inline]
116    fn abs_diff_eq(&self, other: &&'a mut T, epsilon: T::Epsilon) -> bool {
117        T::abs_diff_eq(*self, *other, epsilon)
118    }
119}
120
121impl<T: AbsDiffEq + Copy> AbsDiffEq for cell::Cell<T> {
122    type Epsilon = T::Epsilon;
123
124    #[inline]
125    fn default_epsilon() -> T::Epsilon {
126        T::default_epsilon()
127    }
128
129    #[inline]
130    fn abs_diff_eq(&self, other: &cell::Cell<T>, epsilon: T::Epsilon) -> bool {
131        T::abs_diff_eq(&self.get(), &other.get(), epsilon)
132    }
133}
134
135impl<T: AbsDiffEq + ?Sized> AbsDiffEq for cell::RefCell<T> {
136    type Epsilon = T::Epsilon;
137
138    #[inline]
139    fn default_epsilon() -> T::Epsilon {
140        T::default_epsilon()
141    }
142
143    #[inline]
144    fn abs_diff_eq(&self, other: &cell::RefCell<T>, epsilon: T::Epsilon) -> bool {
145        T::abs_diff_eq(&self.borrow(), &other.borrow(), epsilon)
146    }
147}
148
149impl<A, B> AbsDiffEq<[B]> for [A]
150where
151    A: AbsDiffEq<B>,
152    A::Epsilon: Clone,
153{
154    type Epsilon = A::Epsilon;
155
156    #[inline]
157    fn default_epsilon() -> A::Epsilon {
158        A::default_epsilon()
159    }
160
161    #[inline]
162    fn abs_diff_eq(&self, other: &[B], epsilon: A::Epsilon) -> bool {
163        self.len() == other.len()
164            && Iterator::zip(self.iter(), other).all(|(x, y)| A::abs_diff_eq(x, y, epsilon.clone()))
165    }
166}
167
168#[cfg(feature = "num-complex")]
169impl<T: AbsDiffEq> AbsDiffEq for Complex<T>
170where
171    T::Epsilon: Clone,
172{
173    type Epsilon = T::Epsilon;
174
175    #[inline]
176    fn default_epsilon() -> T::Epsilon {
177        T::default_epsilon()
178    }
179
180    #[inline]
181    fn abs_diff_eq(&self, other: &Complex<T>, epsilon: T::Epsilon) -> bool {
182        T::abs_diff_eq(&self.re, &other.re, epsilon.clone())
183            && T::abs_diff_eq(&self.im, &other.im, epsilon)
184    }
185}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy