malachite_float/comparison/
partial_eq_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_nz::natural::Natural;
16
17fn float_partial_eq_unsigned<T: PrimitiveUnsigned>(x: &Float, y: &T) -> bool
18where
19    Natural: From<T>,
20{
21    match x {
22        float_either_zero!() => *y == T::ZERO,
23        Float(Finite {
24            sign,
25            exponent,
26            significand,
27            ..
28        }) => {
29            *y != T::ZERO
30                && *sign
31                && *exponent >= 0
32                && y.significant_bits() == u64::from(exponent.unsigned_abs())
33                && significand.cmp_normalized(&Natural::from(*y)) == Equal
34        }
35        _ => false,
36    }
37}
38
39macro_rules! impl_partial_eq_unsigned {
40    ($t: ident) => {
41        impl PartialEq<$t> for Float {
42            /// Determines whether a [`Float`] is equal to an unsigned 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(&self, other: &$t) -> bool {
58                float_partial_eq_unsigned(self, other)
59            }
60        }
61
62        impl PartialEq<Float> for $t {
63            /// Determines whether an unsigned primitive integer is equal to a [`Float`].
64            ///
65            /// No primitive integer is equal to $\infty$, $-\infty$, or NaN. The integer zero is
66            /// equal to both the [`Float`] zero and the [`Float`] negative zero.
67            ///
68            /// # Worst-case complexity
69            /// $T(n) = O(n)$
70            ///
71            /// $M(n) = O(1)$
72            ///
73            /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`.
74            ///
75            /// # Examples
76            /// See [here](super::partial_eq_primitive_int#partial_eq).
77            #[inline]
78            fn eq(&self, other: &Float) -> bool {
79                other == self
80            }
81        }
82    };
83}
84apply_to_unsigneds!(impl_partial_eq_unsigned);
85
86fn float_partial_eq_signed<T: PrimitiveSigned>(x: &Float, y: &T) -> bool
87where
88    Natural: From<<T as UnsignedAbs>::Output>,
89{
90    match x {
91        float_either_zero!() => *y == T::ZERO,
92        Float(Finite {
93            sign,
94            exponent,
95            significand,
96            ..
97        }) => {
98            *y != T::ZERO
99                && *sign == (*y >= T::ZERO)
100                && *exponent >= 0
101                && y.significant_bits() == u64::from(exponent.unsigned_abs())
102                && significand.cmp_normalized(&Natural::from(y.unsigned_abs())) == Equal
103        }
104        _ => false,
105    }
106}
107
108macro_rules! impl_partial_eq_signed {
109    ($t: ident) => {
110        impl PartialEq<$t> for Float {
111            /// Determines whether a [`Float`] is equal to 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::partial_eq_primitive_int#partial_eq).
125            #[inline]
126            fn eq(&self, other: &$t) -> bool {
127                float_partial_eq_signed(self, other)
128            }
129        }
130
131        impl PartialEq<Float> for $t {
132            /// Determines whether a signed primitive integer is equal to a [`Float`].
133            ///
134            /// No primitive integer is equal to $\infty$, $-\infty$, or NaN. The integer zero is
135            /// equal to both the [`Float`] zero and the [`Float`] negative zero.
136            ///
137            /// # Worst-case complexity
138            /// $T(n) = O(n)$
139            ///
140            /// $M(n) = O(1)$
141            ///
142            /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`.
143            ///
144            /// # Examples
145            /// See [here](super::partial_eq_primitive_int#partial_eq).
146            #[inline]
147            fn eq(&self, other: &Float) -> bool {
148                other == self
149            }
150        }
151    };
152}
153apply_to_signeds!(impl_partial_eq_signed);