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

ndarray/
array_approx.rs

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        /// A test for equality that uses the elementwise absolute difference to compute the
12        /// approximate equality of two arrays.
13        ///
14        /// **Requires crate feature `"approx"`**
15        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        /// A test for equality that uses an elementwise relative comparison if the values are far
25        /// apart; and the absolute difference otherwise.
26        ///
27        /// **Requires crate feature `"approx"`**
28        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                    // Check epsilon.
148                    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                    // Make sure we can compare different shapes without failure.
152                    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                    // Check epsilon.
165                    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                    // Make sure we can compare different shapes without failure.
169                    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                    // Check epsilon.
182                    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                    // Make sure we can compare different shapes without failure.
186                    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\"`.**");