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}