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}