1use core::cell;
2#[cfg(feature = "num-complex")]
3use num_complex::Complex;
4
5pub trait AbsDiffEq<Rhs = Self>: PartialEq<Rhs>
7where
8 Rhs: ?Sized,
9{
10 type Epsilon;
12
13 fn default_epsilon() -> Self::Epsilon;
18
19 fn abs_diff_eq(&self, other: &Rhs, epsilon: Self::Epsilon) -> bool;
22
23 fn abs_diff_ne(&self, other: &Rhs, epsilon: Self::Epsilon) -> bool {
25 !Self::abs_diff_eq(self, other, epsilon)
26 }
27}
28
29macro_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
89impl<'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}