Thanks to visit codestin.com
Credit goes to docs.rs

ndarray/
array_approx.rs

1#[cfg(feature = "approx")]
2#[cfg_attr(docsrs, doc(cfg(feature = "approx")))]
3mod approx_methods
4{
5    use crate::imp_prelude::*;
6
7    impl<A, D: Dimension> ArrayRef<A, D>
8    {
9        /// A test for equality that uses the elementwise absolute difference to compute the
10        /// approximate equality of two arrays.
11        pub fn abs_diff_eq<B>(&self, other: &ArrayRef<B, D>, epsilon: A::Epsilon) -> bool
12        where
13            A: ::approx::AbsDiffEq<B>,
14            A::Epsilon: Clone,
15        {
16            <Self as ::approx::AbsDiffEq<_>>::abs_diff_eq(self, other, epsilon)
17        }
18
19        /// A test for equality that uses an elementwise relative comparison if the values are far
20        /// apart; and the absolute difference otherwise.
21        pub fn relative_eq<B>(&self, other: &ArrayRef<B, D>, epsilon: A::Epsilon, max_relative: A::Epsilon) -> bool
22        where
23            A: ::approx::RelativeEq<B>,
24            A::Epsilon: Clone,
25        {
26            <Self as ::approx::RelativeEq<_>>::relative_eq(self, other, epsilon, max_relative)
27        }
28    }
29}
30
31macro_rules! impl_approx_traits {
32    ($approx:ident, $doc:expr) => {
33        mod $approx {
34            use crate::imp_prelude::*;
35            use crate::Zip;
36            use $approx::{AbsDiffEq, RelativeEq, UlpsEq};
37
38            #[doc = $doc]
39            impl<A, B, D> AbsDiffEq<ArrayRef<B, D>> for ArrayRef<A, D>
40            where
41                A: AbsDiffEq<B>,
42                A::Epsilon: Clone,
43                D: Dimension,
44            {
45                type Epsilon = A::Epsilon;
46
47                fn default_epsilon() -> A::Epsilon {
48                    A::default_epsilon()
49                }
50
51                fn abs_diff_eq(&self, other: &ArrayRef<B, D>, epsilon: A::Epsilon) -> bool {
52                    if self.shape() != other.shape() {
53                        return false;
54                    }
55
56                    Zip::from(self)
57                        .and(other)
58                        .all(move |a, b| A::abs_diff_eq(a, b, epsilon.clone()))
59                }
60            }
61
62            #[doc = $doc]
63            impl<A, B, S, S2, D> AbsDiffEq<ArrayBase<S2, D>> for ArrayBase<S, D>
64            where
65                A: AbsDiffEq<B>,
66                A::Epsilon: Clone,
67                S: Data<Elem = A>,
68                S2: Data<Elem = B>,
69                D: Dimension,
70            {
71                type Epsilon = A::Epsilon;
72
73                fn default_epsilon() -> A::Epsilon {
74                    A::default_epsilon()
75                }
76
77                fn abs_diff_eq(&self, other: &ArrayBase<S2, D>, epsilon: A::Epsilon) -> bool {
78                    (**self).abs_diff_eq(other, epsilon)
79                }
80            }
81
82            #[doc = $doc]
83            impl<A, B, D> RelativeEq<ArrayRef<B, D>> for ArrayRef<A, D>
84            where
85                A: RelativeEq<B>,
86                A::Epsilon: Clone,
87                D: Dimension,
88            {
89                fn default_max_relative() -> A::Epsilon {
90                    A::default_max_relative()
91                }
92
93                fn relative_eq(
94                    &self,
95                    other: &ArrayRef<B, D>,
96                    epsilon: A::Epsilon,
97                    max_relative: A::Epsilon,
98                ) -> bool {
99                    if self.shape() != other.shape() {
100                        return false;
101                    }
102
103                    Zip::from(self).and(other).all(move |a, b| {
104                        A::relative_eq(a, b, epsilon.clone(), max_relative.clone())
105                    })
106                }
107            }
108
109            #[doc = $doc]
110            impl<A, B, S, S2, D> RelativeEq<ArrayBase<S2, D>> for ArrayBase<S, D>
111            where
112                A: RelativeEq<B>,
113                A::Epsilon: Clone,
114                S: Data<Elem = A>,
115                S2: Data<Elem = B>,
116                D: Dimension,
117            {
118                fn default_max_relative() -> A::Epsilon {
119                    A::default_max_relative()
120                }
121
122                fn relative_eq(
123                    &self,
124                    other: &ArrayBase<S2, D>,
125                    epsilon: A::Epsilon,
126                    max_relative: A::Epsilon,
127                ) -> bool {
128                    (**self).relative_eq(other, epsilon, max_relative)
129                }
130            }
131
132            #[doc = $doc]
133            impl<A, B, D> UlpsEq<ArrayRef<B, D>> for ArrayRef<A, D>
134            where
135                A: UlpsEq<B>,
136                A::Epsilon: Clone,
137                D: Dimension,
138            {
139                fn default_max_ulps() -> u32 {
140                    A::default_max_ulps()
141                }
142
143                fn ulps_eq(
144                    &self,
145                    other: &ArrayRef<B, D>,
146                    epsilon: A::Epsilon,
147                    max_ulps: u32,
148                ) -> bool {
149                    if self.shape() != other.shape() {
150                        return false;
151                    }
152
153                    Zip::from(self)
154                        .and(other)
155                        .all(move |a, b| A::ulps_eq(a, b, epsilon.clone(), max_ulps))
156                }
157            }
158
159            #[doc = $doc]
160            impl<A, B, S, S2, D> UlpsEq<ArrayBase<S2, D>> for ArrayBase<S, D>
161            where
162                A: UlpsEq<B>,
163                A::Epsilon: Clone,
164                S: Data<Elem = A>,
165                S2: Data<Elem = B>,
166                D: Dimension,
167            {
168                fn default_max_ulps() -> u32 {
169                    A::default_max_ulps()
170                }
171
172                fn ulps_eq(
173                    &self,
174                    other: &ArrayBase<S2, D>,
175                    epsilon: A::Epsilon,
176                    max_ulps: u32,
177                ) -> bool {
178                    (**self).ulps_eq(other, epsilon, max_ulps)
179                }
180            }
181
182            #[cfg(test)]
183            mod tests {
184                use crate::prelude::*;
185                use alloc::vec;
186                use $approx::{
187                    assert_abs_diff_eq, assert_abs_diff_ne, assert_relative_eq, assert_relative_ne,
188                    assert_ulps_eq, assert_ulps_ne,
189                };
190
191                #[test]
192                fn abs_diff_eq() {
193                    let a: Array2<f32> = array![[0., 2.], [-0.000010001, 100000000.]];
194                    let mut b: Array2<f32> = array![[0., 1.], [-0.000010002, 100000001.]];
195                    assert_abs_diff_ne!(a, b);
196                    b[(0, 1)] = 2.;
197                    assert_abs_diff_eq!(a, b);
198
199                    // Check epsilon.
200                    assert_abs_diff_eq!(array![0.0f32], array![1e-40f32], epsilon = 1e-40f32);
201                    assert_abs_diff_ne!(array![0.0f32], array![1e-40f32], epsilon = 1e-41f32);
202
203                    // Make sure we can compare different shapes without failure.
204                    let c = array![[1., 2.]];
205                    assert_abs_diff_ne!(a, c);
206                }
207
208                #[test]
209                fn relative_eq() {
210                    let a: Array2<f32> = array![[1., 2.], [-0.000010001, 100000000.]];
211                    let mut b: Array2<f32> = array![[1., 1.], [-0.000010002, 100000001.]];
212                    assert_relative_ne!(a, b);
213                    b[(0, 1)] = 2.;
214                    assert_relative_eq!(a, b);
215
216                    // Check epsilon.
217                    assert_relative_eq!(array![0.0f32], array![1e-40f32], epsilon = 1e-40f32);
218                    assert_relative_ne!(array![0.0f32], array![1e-40f32], epsilon = 1e-41f32);
219
220                    // Make sure we can compare different shapes without failure.
221                    let c = array![[1., 2.]];
222                    assert_relative_ne!(a, c);
223                }
224
225                #[test]
226                fn ulps_eq() {
227                    let a: Array2<f32> = array![[1., 2.], [-0.000010001, 100000000.]];
228                    let mut b: Array2<f32> = array![[1., 1.], [-0.000010002, 100000001.]];
229                    assert_ulps_ne!(a, b);
230                    b[(0, 1)] = 2.;
231                    assert_ulps_eq!(a, b);
232
233                    // Check epsilon.
234                    assert_ulps_eq!(array![0.0f32], array![1e-40f32], epsilon = 1e-40f32);
235                    assert_ulps_ne!(array![0.0f32], array![1e-40f32], epsilon = 1e-41f32);
236
237                    // Make sure we can compare different shapes without failure.
238                    let c = array![[1., 2.]];
239                    assert_ulps_ne!(a, c);
240                }
241            }
242        }
243    };
244}
245
246#[cfg(feature = "approx")]
247#[cfg_attr(docsrs, doc(cfg(feature = "approx")))]
248impl_approx_traits!(approx, "**Requires crate feature `\"approx\"`.**");