1#[cfg(feature = "approx")]
2mod approx_methods
3{
4 use crate::imp_prelude::*;
5
6 impl<A, S, D> ArrayBase<S, D>
7 where
8 S: Data<Elem = A>,
9 D: Dimension,
10 {
11 pub fn abs_diff_eq<S2>(&self, other: &ArrayBase<S2, D>, epsilon: A::Epsilon) -> bool
16 where
17 A: ::approx::AbsDiffEq<S2::Elem>,
18 A::Epsilon: Clone,
19 S2: Data,
20 {
21 <Self as ::approx::AbsDiffEq<_>>::abs_diff_eq(self, other, epsilon)
22 }
23
24 pub fn relative_eq<S2>(&self, other: &ArrayBase<S2, D>, epsilon: A::Epsilon, max_relative: A::Epsilon) -> bool
29 where
30 A: ::approx::RelativeEq<S2::Elem>,
31 A::Epsilon: Clone,
32 S2: Data,
33 {
34 <Self as ::approx::RelativeEq<_>>::relative_eq(self, other, epsilon, max_relative)
35 }
36 }
37}
38
39macro_rules! impl_approx_traits {
40 ($approx:ident, $doc:expr) => {
41 mod $approx {
42 use crate::imp_prelude::*;
43 use crate::Zip;
44 use $approx::{AbsDiffEq, RelativeEq, UlpsEq};
45
46 #[doc = $doc]
47 impl<A, B, S, S2, D> AbsDiffEq<ArrayBase<S2, D>> for ArrayBase<S, D>
48 where
49 A: AbsDiffEq<B>,
50 A::Epsilon: Clone,
51 S: Data<Elem = A>,
52 S2: Data<Elem = B>,
53 D: Dimension,
54 {
55 type Epsilon = A::Epsilon;
56
57 fn default_epsilon() -> A::Epsilon {
58 A::default_epsilon()
59 }
60
61 fn abs_diff_eq(&self, other: &ArrayBase<S2, D>, epsilon: A::Epsilon) -> bool {
62 if self.shape() != other.shape() {
63 return false;
64 }
65
66 Zip::from(self)
67 .and(other)
68 .all(move |a, b| A::abs_diff_eq(a, b, epsilon.clone()))
69 }
70 }
71
72 #[doc = $doc]
73 impl<A, B, S, S2, D> RelativeEq<ArrayBase<S2, D>> for ArrayBase<S, D>
74 where
75 A: RelativeEq<B>,
76 A::Epsilon: Clone,
77 S: Data<Elem = A>,
78 S2: Data<Elem = B>,
79 D: Dimension,
80 {
81 fn default_max_relative() -> A::Epsilon {
82 A::default_max_relative()
83 }
84
85 fn relative_eq(
86 &self,
87 other: &ArrayBase<S2, D>,
88 epsilon: A::Epsilon,
89 max_relative: A::Epsilon,
90 ) -> bool {
91 if self.shape() != other.shape() {
92 return false;
93 }
94
95 Zip::from(self).and(other).all(move |a, b| {
96 A::relative_eq(a, b, epsilon.clone(), max_relative.clone())
97 })
98 }
99 }
100
101 #[doc = $doc]
102 impl<A, B, S, S2, D> UlpsEq<ArrayBase<S2, D>> for ArrayBase<S, D>
103 where
104 A: UlpsEq<B>,
105 A::Epsilon: Clone,
106 S: Data<Elem = A>,
107 S2: Data<Elem = B>,
108 D: Dimension,
109 {
110 fn default_max_ulps() -> u32 {
111 A::default_max_ulps()
112 }
113
114 fn ulps_eq(
115 &self,
116 other: &ArrayBase<S2, D>,
117 epsilon: A::Epsilon,
118 max_ulps: u32,
119 ) -> bool {
120 if self.shape() != other.shape() {
121 return false;
122 }
123
124 Zip::from(self)
125 .and(other)
126 .all(move |a, b| A::ulps_eq(a, b, epsilon.clone(), max_ulps))
127 }
128 }
129
130 #[cfg(test)]
131 mod tests {
132 use crate::prelude::*;
133 use alloc::vec;
134 use $approx::{
135 assert_abs_diff_eq, assert_abs_diff_ne, assert_relative_eq, assert_relative_ne,
136 assert_ulps_eq, assert_ulps_ne,
137 };
138
139 #[test]
140 fn abs_diff_eq() {
141 let a: Array2<f32> = array![[0., 2.], [-0.000010001, 100000000.]];
142 let mut b: Array2<f32> = array![[0., 1.], [-0.000010002, 100000001.]];
143 assert_abs_diff_ne!(a, b);
144 b[(0, 1)] = 2.;
145 assert_abs_diff_eq!(a, b);
146
147 assert_abs_diff_eq!(array![0.0f32], array![1e-40f32], epsilon = 1e-40f32);
149 assert_abs_diff_ne!(array![0.0f32], array![1e-40f32], epsilon = 1e-41f32);
150
151 let c = array![[1., 2.]];
153 assert_abs_diff_ne!(a, c);
154 }
155
156 #[test]
157 fn relative_eq() {
158 let a: Array2<f32> = array![[1., 2.], [-0.000010001, 100000000.]];
159 let mut b: Array2<f32> = array![[1., 1.], [-0.000010002, 100000001.]];
160 assert_relative_ne!(a, b);
161 b[(0, 1)] = 2.;
162 assert_relative_eq!(a, b);
163
164 assert_relative_eq!(array![0.0f32], array![1e-40f32], epsilon = 1e-40f32);
166 assert_relative_ne!(array![0.0f32], array![1e-40f32], epsilon = 1e-41f32);
167
168 let c = array![[1., 2.]];
170 assert_relative_ne!(a, c);
171 }
172
173 #[test]
174 fn ulps_eq() {
175 let a: Array2<f32> = array![[1., 2.], [-0.000010001, 100000000.]];
176 let mut b: Array2<f32> = array![[1., 1.], [-0.000010002, 100000001.]];
177 assert_ulps_ne!(a, b);
178 b[(0, 1)] = 2.;
179 assert_ulps_eq!(a, b);
180
181 assert_ulps_eq!(array![0.0f32], array![1e-40f32], epsilon = 1e-40f32);
183 assert_ulps_ne!(array![0.0f32], array![1e-40f32], epsilon = 1e-41f32);
184
185 let c = array![[1., 2.]];
187 assert_ulps_ne!(a, c);
188 }
189 }
190 }
191 };
192}
193
194#[cfg(feature = "approx")]
195impl_approx_traits!(approx, "**Requires crate feature `\"approx\"`.**");