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\"`.**");
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy