malachite_float/comparison/
eq_abs.rs

1// Copyright © 2025 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::InnerFloat::{Finite, Infinity, NaN, Zero};
10use crate::{ComparableFloat, ComparableFloatRef, Float};
11use core::cmp::Ordering::*;
12use malachite_base::num::comparison::traits::EqAbs;
13
14impl EqAbs for Float {
15    /// Compares the absolute values of two [`Float`]s for equality.
16    ///
17    /// This implementation follows the IEEE 754 standard. `NaN` is not equal to anything, not even
18    /// itself. Positive zero is equal to negative zero. [`Float`]s with different precisions are
19    /// equal if they represent the same numeric value.
20    ///
21    /// For different equality behavior, consider using [`ComparableFloat`] or
22    /// [`ComparableFloatRef`].
23    ///
24    /// # Worst-case complexity
25    /// $T(n) = O(n)$
26    ///
27    /// $M(n) = O(1)$
28    ///
29    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
30    /// other.significant_bits())`.
31    ///
32    /// # Examples
33    /// ```
34    /// use malachite_base::num::basic::traits::{NaN, NegativeZero, One, Two, Zero};
35    /// use malachite_float::Float;
36    ///
37    /// assert_ne!(Float::NAN, Float::NAN);
38    /// assert_eq!(Float::ZERO, Float::ZERO);
39    /// assert_eq!(Float::NEGATIVE_ZERO, Float::NEGATIVE_ZERO);
40    /// assert_eq!(Float::ZERO, Float::NEGATIVE_ZERO);
41    ///
42    /// assert_eq!(Float::ONE, Float::ONE);
43    /// assert_ne!(Float::ONE, Float::TWO);
44    /// assert_eq!(Float::ONE, Float::one_prec(100));
45    /// ```
46    fn eq_abs(&self, other: &Self) -> bool {
47        match (self, other) {
48            (float_either_infinity!(), float_either_infinity!())
49            | (float_either_zero!(), float_either_zero!()) => true,
50            (
51                Self(Finite {
52                    exponent: e_x,
53                    significand: x,
54                    ..
55                }),
56                Self(Finite {
57                    exponent: e_y,
58                    significand: y,
59                    ..
60                }),
61            ) => e_x == e_y && x.cmp_normalized_no_shift(y) == Equal,
62            _ => false,
63        }
64    }
65}
66
67impl EqAbs for ComparableFloat {
68    /// Compares the absolute values of two [`ComparableFloat`]s for equality.
69    ///
70    /// This implementation ignores the IEEE 754 standard in favor of an equality operation that
71    /// respects the expected properties of symmetry, reflexivity, and transitivity. Using
72    /// [`ComparableFloat`], `NaN`s are equal to themselves. There is a single, unique `NaN`;
73    /// there's no concept of signalling `NaN`s. [`ComparableFloat`]s with different precisions are
74    /// unequal.
75    ///
76    /// # Worst-case complexity
77    /// $T(n) = O(n)$
78    ///
79    /// $M(n) = O(1)$
80    ///
81    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
82    /// other.significant_bits())`.
83    ///
84    /// # Examples
85    /// ```
86    /// use malachite_base::num::basic::traits::{NaN, NegativeZero, One, Two, Zero};
87    /// use malachite_float::{ComparableFloat, Float};
88    ///
89    /// assert_eq!(ComparableFloat(Float::NAN), ComparableFloat(Float::NAN));
90    /// assert_eq!(ComparableFloat(Float::ZERO), ComparableFloat(Float::ZERO));
91    /// assert_eq!(
92    ///     ComparableFloat(Float::NEGATIVE_ZERO),
93    ///     ComparableFloat(Float::NEGATIVE_ZERO)
94    /// );
95    /// assert_ne!(
96    ///     ComparableFloat(Float::ZERO),
97    ///     ComparableFloat(Float::NEGATIVE_ZERO)
98    /// );
99    ///
100    /// assert_eq!(ComparableFloat(Float::ONE), ComparableFloat(Float::ONE));
101    /// assert_ne!(ComparableFloat(Float::ONE), ComparableFloat(Float::TWO));
102    /// assert_ne!(
103    ///     ComparableFloat(Float::ONE),
104    ///     ComparableFloat(Float::one_prec(100))
105    /// );
106    /// ```
107    #[inline]
108    fn eq_abs(&self, other: &Self) -> bool {
109        self.as_ref().eq_abs(&other.as_ref())
110    }
111}
112
113impl<'a> EqAbs<ComparableFloatRef<'a>> for ComparableFloatRef<'_> {
114    /// Compares the absolute values of two [`ComparableFloatRef`]s for equality.
115    ///
116    /// This implementation ignores the IEEE 754 standard in favor of an equality operation that
117    /// respects the expected properties of symmetry, reflexivity, and transitivity. Using
118    /// [`ComparableFloatRef`], `NaN`s are equal to themselves. There is a single, unique `NaN`;
119    /// there's no concept of signalling `NaN`s. [`ComparableFloatRef`]s with different precisions
120    /// are unequal.
121    ///
122    /// # Worst-case complexity
123    /// $T(n) = O(n)$
124    ///
125    /// $M(n) = O(1)$
126    ///
127    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
128    /// other.significant_bits())`.
129    ///
130    /// # Examples
131    /// ```
132    /// use malachite_base::num::basic::traits::{NaN, NegativeZero, One, Two, Zero};
133    /// use malachite_float::{ComparableFloatRef, Float};
134    ///
135    /// assert_eq!(
136    ///     ComparableFloatRef(&Float::NAN),
137    ///     ComparableFloatRef(&Float::NAN)
138    /// );
139    /// assert_eq!(
140    ///     ComparableFloatRef(&Float::ZERO),
141    ///     ComparableFloatRef(&Float::ZERO)
142    /// );
143    /// assert_eq!(
144    ///     ComparableFloatRef(&Float::NEGATIVE_ZERO),
145    ///     ComparableFloatRef(&Float::NEGATIVE_ZERO)
146    /// );
147    /// assert_ne!(
148    ///     ComparableFloatRef(&Float::ZERO),
149    ///     ComparableFloatRef(&Float::NEGATIVE_ZERO)
150    /// );
151    ///
152    /// assert_eq!(
153    ///     ComparableFloatRef(&Float::ONE),
154    ///     ComparableFloatRef(&Float::ONE)
155    /// );
156    /// assert_ne!(
157    ///     ComparableFloatRef(&Float::ONE),
158    ///     ComparableFloatRef(&Float::TWO)
159    /// );
160    /// assert_ne!(
161    ///     ComparableFloatRef(&Float::ONE),
162    ///     ComparableFloatRef(&Float::one_prec(100))
163    /// );
164    /// ```
165    fn eq_abs(&self, other: &ComparableFloatRef<'a>) -> bool {
166        match (&self.0, &other.0) {
167            (float_nan!(), float_nan!())
168            | (float_either_infinity!(), float_either_infinity!())
169            | (float_either_zero!(), float_either_zero!()) => true,
170            (
171                Float(Finite {
172                    exponent: e_x,
173                    precision: p_x,
174                    significand: x,
175                    ..
176                }),
177                Float(Finite {
178                    exponent: e_y,
179                    precision: p_y,
180                    significand: y,
181                    ..
182                }),
183            ) => e_x == e_y && p_x == p_y && x == y,
184            _ => false,
185        }
186    }
187}