typed_floats/types/impls/
eq.rs

1use crate::{
2    Negative, NegativeFinite, NonNaN, NonNaNFinite, NonZeroNonNaN, NonZeroNonNaNFinite, Positive,
3    PositiveFinite, StrictlyNegative, StrictlyNegativeFinite, StrictlyPositive,
4    StrictlyPositiveFinite,
5};
6
7// This is safe because we know that both values are not NaN
8
9macro_rules! impl_eq_self {
10    ($type:ident) => {
11        impl Eq for $type<f32> {}
12        impl Eq for $type<f64> {}
13
14        impl PartialEq for $type<f32> {
15            #[inline]
16            fn eq(&self, other: &Self) -> bool {
17                self.0 == other.0
18            }
19        }
20
21        impl PartialEq for $type<f64> {
22            #[inline]
23            fn eq(&self, other: &Self) -> bool {
24                self.0 == other.0
25            }
26        }
27    };
28}
29
30macro_rules! impl_eq_base {
31    ($type:ident) => {
32        impl PartialEq<$type<f32>> for f32 {
33            #[inline]
34            fn eq(&self, other: &$type<f32>) -> bool {
35                *self == other.0
36            }
37        }
38
39        impl PartialEq<$type<f64>> for f64 {
40            #[inline]
41            fn eq(&self, other: &$type<f64>) -> bool {
42                *self == other.0
43            }
44        }
45
46        impl PartialEq<f32> for $type<f32> {
47            #[inline]
48            fn eq(&self, other: &f32) -> bool {
49                self.0 == *other
50            }
51        }
52
53        impl PartialEq<f64> for $type<f64> {
54            #[inline]
55            fn eq(&self, other: &f64) -> bool {
56                self.0 == *other
57            }
58        }
59    };
60}
61
62// This fast implementation can only be used for types that rejects `-0.0` and/or `+0.0`
63macro_rules! impl_fast_eq_self {
64    ($type:ident) => {
65        impl Eq for $type<f32> {}
66        impl Eq for $type<f64> {}
67
68        impl PartialEq for $type<f32> {
69            #[inline]
70            fn eq(&self, other: &Self) -> bool {
71                self.0.to_bits() == other.0.to_bits()
72            }
73        }
74
75        impl PartialEq for $type<f64> {
76            #[inline]
77            fn eq(&self, other: &Self) -> bool {
78                self.0.to_bits() == other.0.to_bits()
79            }
80        }
81    };
82}
83
84// This fast implementation can only be used for types that rejects `-0.0` AND `+0.0`
85macro_rules! impl_fast_eq_base {
86    ($type:ident) => {
87        impl PartialEq<$type<f32>> for f32 {
88            #[inline]
89            fn eq(&self, other: &$type<f32>) -> bool {
90                self.to_bits() == (&other.0).to_bits()
91            }
92        }
93
94        impl PartialEq<$type<f64>> for f64 {
95            #[inline]
96            fn eq(&self, other: &$type<f64>) -> bool {
97                self.to_bits() == (&other.0).to_bits()
98            }
99        }
100
101        impl PartialEq<f32> for $type<f32> {
102            #[inline]
103            fn eq(&self, other: &f32) -> bool {
104                (&self.0).to_bits() == other.to_bits()
105            }
106        }
107
108        impl PartialEq<f64> for $type<f64> {
109            #[inline]
110            fn eq(&self, other: &f64) -> bool {
111                (&self.0).to_bits() == other.to_bits()
112            }
113        }
114    };
115}
116
117impl_eq_base!(NonNaN);
118impl_eq_self!(NonNaN);
119
120impl_fast_eq_base!(NonZeroNonNaN);
121impl_fast_eq_self!(NonZeroNonNaN);
122
123impl_eq_base!(NonNaNFinite);
124impl_eq_self!(NonNaNFinite);
125
126impl_fast_eq_base!(NonZeroNonNaNFinite);
127impl_fast_eq_self!(NonZeroNonNaNFinite);
128
129impl_eq_base!(Positive);
130impl_fast_eq_self!(Positive);
131
132impl_eq_base!(Negative);
133impl_fast_eq_self!(Negative);
134
135impl_eq_base!(PositiveFinite);
136impl_fast_eq_self!(PositiveFinite);
137
138impl_eq_base!(NegativeFinite);
139impl_fast_eq_self!(NegativeFinite);
140
141impl_fast_eq_base!(StrictlyPositive);
142impl_fast_eq_self!(StrictlyPositive);
143
144impl_fast_eq_base!(StrictlyNegative);
145impl_fast_eq_self!(StrictlyNegative);
146
147impl_fast_eq_base!(StrictlyPositiveFinite);
148impl_fast_eq_self!(StrictlyPositiveFinite);
149
150impl_fast_eq_base!(StrictlyNegativeFinite);
151impl_fast_eq_self!(StrictlyNegativeFinite);
152
153#[cfg(test)]
154mod tests {
155    use super::*;
156
157    macro_rules! impl_eq_test {
158        ($test:ident, $type:ident) => {
159            #[test]
160            fn $test() {
161                let values_f32 = crate::tf32::get_test_values();
162                let nan = f32::NAN;
163                for &value in &values_f32 {
164                    if let Ok(t) = $type::<f32>::new(value) {
165                        assert_eq!(t, t);
166                        assert_eq!(t, value);
167                        assert_eq!(value, t);
168
169                        assert_ne!(t, nan);
170                        assert_ne!(nan, t);
171
172                        if value == 0.0 {
173                            assert_eq!(t, -value);
174                            assert_eq!(-value, t);
175                            assert_eq!(t, 0.0);
176                            assert_eq!(t, -0.0);
177                        } else {
178                            assert_ne!(t, -value);
179                            assert_ne!(-value, t);
180                            assert_ne!(t, 0.0);
181                            assert_ne!(t, -0.0);
182                        }
183
184                        for &other in &values_f32 {
185                            if let Ok(other_t) = $type::<f32>::new(other) {
186                                if other == value {
187                                    assert_eq!(t, other_t);
188                                    assert_eq!(other_t, t);
189                                    assert_eq!(t, other);
190                                    assert_eq!(other, t);
191                                    assert_eq!(value, other);
192                                    assert_eq!(other, value);
193                                } else {
194                                    assert_ne!(t, other_t);
195                                    assert_ne!(other_t, t);
196                                    assert_ne!(t, other);
197                                    assert_ne!(other, t);
198                                    assert_ne!(value, other);
199                                    assert_ne!(other, value);
200                                }
201                            }
202                        }
203                    }
204                }
205
206                let nan = f64::NAN;
207                let values_f64 = crate::tf64::get_test_values();
208                for &value in &values_f64 {
209                    if let Ok(t) = $type::<f64>::new(value) {
210                        assert_eq!(t, t);
211                        assert_eq!(t, value);
212                        assert_eq!(value, t);
213
214                        assert_ne!(t, nan);
215                        assert_ne!(nan, t);
216
217                        if value == 0.0 {
218                            assert_eq!(t, -value);
219                            assert_eq!(-value, t);
220                            assert_eq!(t, 0.0);
221                            assert_eq!(t, -0.0);
222                        } else {
223                            assert_ne!(t, -value);
224                            assert_ne!(-value, t);
225                            assert_ne!(t, 0.0);
226                            assert_ne!(t, -0.0);
227                        }
228
229                        for &other in &values_f64 {
230                            if let Ok(other_t) = $type::<f64>::new(other) {
231                                if other == value {
232                                    assert_eq!(t, other_t);
233                                    assert_eq!(other_t, t);
234                                    assert_eq!(t, other);
235                                    assert_eq!(other, t);
236                                } else {
237                                    assert_ne!(t, other_t);
238                                    assert_ne!(other_t, t);
239                                    assert_ne!(t, other);
240                                    assert_ne!(other, t);
241                                }
242                            }
243                        }
244                    }
245                }
246            }
247        };
248    }
249
250    impl_eq_test!(non_nan, NonNaN);
251    impl_eq_test!(non_nan_finite, NonNaNFinite);
252    impl_eq_test!(non_zero_non_nan, NonZeroNonNaN);
253    impl_eq_test!(non_zero_non_nan_finite, NonZeroNonNaNFinite);
254    impl_eq_test!(positive, Positive);
255    impl_eq_test!(negative, Negative);
256    impl_eq_test!(positive_finite, PositiveFinite);
257    impl_eq_test!(negative_finite, NegativeFinite);
258    impl_eq_test!(strictly_positive, StrictlyPositive);
259    impl_eq_test!(strictly_negative, StrictlyNegative);
260    impl_eq_test!(strictly_positive_finite, StrictlyPositiveFinite);
261    impl_eq_test!(strictly_negative_finite, StrictlyNegativeFinite);
262}