malachite_float/comparison/
eq_abs_primitive_int.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::Float;
10use crate::InnerFloat::{Finite, Zero};
11use core::cmp::Ordering::*;
12use malachite_base::num::arithmetic::traits::UnsignedAbs;
13use malachite_base::num::basic::signeds::PrimitiveSigned;
14use malachite_base::num::basic::unsigneds::PrimitiveUnsigned;
15use malachite_base::num::comparison::traits::EqAbs;
16use malachite_nz::natural::Natural;
17
18fn float_eq_abs_unsigned<T: PrimitiveUnsigned>(x: &Float, y: &T) -> bool
19where
20    Natural: From<T>,
21{
22    match x {
23        float_either_zero!() => *y == T::ZERO,
24        Float(Finite {
25            exponent,
26            significand,
27            ..
28        }) => {
29            *y != T::ZERO
30                && *exponent >= 0
31                && y.significant_bits() == u64::from(exponent.unsigned_abs())
32                && significand.cmp_normalized(&Natural::from(*y)) == Equal
33        }
34        _ => false,
35    }
36}
37
38macro_rules! impl_eq_abs_unsigned {
39    ($t: ident) => {
40        impl EqAbs<$t> for Float {
41            /// Determines whether the absolute value of a [`Float`] is equal to an unsigned
42            /// primitive integer.
43            ///
44            /// $\infty$, $-\infty$, and NaN are not equal to any primitive integer. Both the
45            /// [`Float`] zero and the [`Float`] negative zero are equal to the integer zero.
46            ///
47            /// # Worst-case complexity
48            /// $T(n) = O(n)$
49            ///
50            /// $M(n) = O(1)$
51            ///
52            /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
53            ///
54            /// # Examples
55            /// See [here](super::partial_eq_primitive_int#partial_eq).
56            #[inline]
57            fn eq_abs(&self, other: &$t) -> bool {
58                float_eq_abs_unsigned(self, other)
59            }
60        }
61
62        impl EqAbs<Float> for $t {
63            /// Determines whether an unsigned primitive integer is equal to the absolute value of a
64            /// [`Float`].
65            ///
66            /// No primitive integer is equal to $\infty$, $-\infty$, or NaN. The integer zero is
67            /// equal to both the [`Float`] zero and the [`Float`] negative zero.
68            ///
69            /// # Worst-case complexity
70            /// $T(n) = O(n)$
71            ///
72            /// $M(n) = O(1)$
73            ///
74            /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`.
75            ///
76            /// # Examples
77            /// See [here](super::partial_eq_primitive_int#partial_eq).
78            #[inline]
79            fn eq_abs(&self, other: &Float) -> bool {
80                other.eq_abs(self)
81            }
82        }
83    };
84}
85apply_to_unsigneds!(impl_eq_abs_unsigned);
86
87fn float_eq_abs_signed<T: PrimitiveSigned>(x: &Float, y: &T) -> bool
88where
89    Natural: From<<T as UnsignedAbs>::Output>,
90{
91    match x {
92        float_either_zero!() => *y == T::ZERO,
93        Float(Finite {
94            exponent,
95            significand,
96            ..
97        }) => {
98            *y != T::ZERO
99                && *exponent >= 0
100                && y.significant_bits() == u64::from(exponent.unsigned_abs())
101                && significand.cmp_normalized(&Natural::from(y.unsigned_abs())) == Equal
102        }
103        _ => false,
104    }
105}
106
107macro_rules! impl_eq_abs_signed {
108    ($t: ident) => {
109        impl EqAbs<$t> for Float {
110            /// Determines whether the absolute value of a [`Float`] is equal to the absolute value
111            /// of a signed primitive integer.
112            ///
113            /// $\infty$, $-\infty$, and NaN are not equal to any primitive integer. Both the
114            /// [`Float`] zero and the [`Float`] negative zero are equal to the integer zero.
115            ///
116            /// # Worst-case complexity
117            /// $T(n) = O(n)$
118            ///
119            /// $M(n) = O(1)$
120            ///
121            /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
122            ///
123            /// # Examples
124            /// See [here](super::eq_abs#eq_abs).
125            #[inline]
126            fn eq_abs(&self, other: &$t) -> bool {
127                float_eq_abs_signed(self, other)
128            }
129        }
130
131        impl EqAbs<Float> for $t {
132            /// Determines whether the absolute value of a signed primitive integer is equal to the
133            /// absolute value of a [`Float`].
134            ///
135            /// No primitive integer is equal to $\infty$, $-\infty$, or NaN. The integer zero is
136            /// equal to both the [`Float`] zero and the [`Float`] negative zero.
137            ///
138            /// # Worst-case complexity
139            /// $T(n) = O(n)$
140            ///
141            /// $M(n) = O(1)$
142            ///
143            /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`.
144            ///
145            /// # Examples
146            /// See [here](super::eq_abs#eq_abs).
147            #[inline]
148            fn eq_abs(&self, other: &Float) -> bool {
149                other.eq_abs(self)
150            }
151        }
152    };
153}
154apply_to_signeds!(impl_eq_abs_signed);