Skip to main content

malachite_float/float/basic/
classification.rs

1// Copyright © 2026 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::{
11    Float, float_either_infinity, float_either_zero, float_finite, float_nan, float_negative_zero,
12    float_zero,
13};
14use core::num::FpCategory;
15
16impl Float {
17    /// Determines whether a [`Float`] is NaN.
18    ///
19    /// # Worst-case complexity
20    /// Constant time and additional memory.
21    ///
22    /// # Examples
23    /// ```
24    /// use malachite_base::num::basic::traits::{NaN, One};
25    /// use malachite_float::Float;
26    ///
27    /// assert_eq!(Float::NAN.is_nan(), true);
28    /// assert_eq!(Float::ONE.is_nan(), false);
29    /// ```
30    #[inline]
31    pub const fn is_nan(&self) -> bool {
32        matches!(self, float_nan!())
33    }
34
35    /// Determines whether a [`Float`] is finite.
36    ///
37    /// NaN is not finite.
38    ///
39    /// # Worst-case complexity
40    /// Constant time and additional memory.
41    ///
42    /// # Examples
43    /// ```
44    /// use malachite_base::num::basic::traits::{Infinity, NaN, One};
45    /// use malachite_float::Float;
46    ///
47    /// assert_eq!(Float::NAN.is_finite(), false);
48    /// assert_eq!(Float::INFINITY.is_finite(), false);
49    /// assert_eq!(Float::ONE.is_finite(), true);
50    /// ```
51    #[inline]
52    pub const fn is_finite(&self) -> bool {
53        matches!(self, Self(Zero { .. } | Finite { .. }))
54    }
55
56    /// Determines whether a [`Float`] is infinite.
57    ///
58    /// NaN is not infinite.
59    ///
60    /// # Worst-case complexity
61    /// Constant time and additional memory.
62    ///
63    /// # Examples
64    /// ```
65    /// use malachite_base::num::basic::traits::{Infinity, NaN, One};
66    /// use malachite_float::Float;
67    ///
68    /// assert_eq!(Float::NAN.is_infinite(), false);
69    /// assert_eq!(Float::INFINITY.is_infinite(), true);
70    /// assert_eq!(Float::ONE.is_infinite(), false);
71    /// ```
72    #[inline]
73    pub const fn is_infinite(&self) -> bool {
74        matches!(self, float_either_infinity!())
75    }
76
77    /// Determines whether a [`Float`] is positive zero.
78    ///
79    /// # Worst-case complexity
80    /// Constant time and additional memory.
81    ///
82    /// # Examples
83    /// ```
84    /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeZero, One, Zero};
85    /// use malachite_float::Float;
86    ///
87    /// assert_eq!(Float::NAN.is_positive_zero(), false);
88    /// assert_eq!(Float::INFINITY.is_positive_zero(), false);
89    /// assert_eq!(Float::ONE.is_positive_zero(), false);
90    /// assert_eq!(Float::ZERO.is_positive_zero(), true);
91    /// assert_eq!(Float::NEGATIVE_ZERO.is_positive_zero(), false);
92    /// ```
93    #[inline]
94    pub const fn is_positive_zero(&self) -> bool {
95        matches!(self, float_zero!())
96    }
97
98    /// Determines whether a [`Float`] is negative zero.
99    ///
100    /// # Worst-case complexity
101    /// Constant time and additional memory.
102    ///
103    /// # Examples
104    /// ```
105    /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeZero, One, Zero};
106    /// use malachite_float::Float;
107    ///
108    /// assert_eq!(Float::NAN.is_negative_zero(), false);
109    /// assert_eq!(Float::INFINITY.is_negative_zero(), false);
110    /// assert_eq!(Float::ONE.is_negative_zero(), false);
111    /// assert_eq!(Float::ZERO.is_negative_zero(), false);
112    /// assert_eq!(Float::NEGATIVE_ZERO.is_negative_zero(), true);
113    /// ```
114    #[inline]
115    pub const fn is_negative_zero(&self) -> bool {
116        matches!(self, float_negative_zero!())
117    }
118
119    /// Determines whether a [`Float`] is zero (positive or negative).
120    ///
121    /// # Worst-case complexity
122    /// Constant time and additional memory.
123    ///
124    /// # Examples
125    /// ```
126    /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeZero, One, Zero};
127    /// use malachite_float::Float;
128    ///
129    /// assert_eq!(Float::NAN.is_zero(), false);
130    /// assert_eq!(Float::INFINITY.is_zero(), false);
131    /// assert_eq!(Float::ONE.is_zero(), false);
132    /// assert_eq!(Float::ZERO.is_zero(), true);
133    /// assert_eq!(Float::NEGATIVE_ZERO.is_zero(), true);
134    /// ```
135    #[inline]
136    pub const fn is_zero(&self) -> bool {
137        matches!(self, float_either_zero!())
138    }
139
140    /// Determines whether a [`Float`] is normal, that is, finite and nonzero.
141    ///
142    /// There is no notion of subnormal [`Float`]s.
143    ///
144    /// # Worst-case complexity
145    /// Constant time and additional memory.
146    ///
147    /// # Examples
148    /// ```
149    /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeZero, One, Zero};
150    /// use malachite_float::Float;
151    ///
152    /// assert_eq!(Float::NAN.is_normal(), false);
153    /// assert_eq!(Float::INFINITY.is_normal(), false);
154    /// assert_eq!(Float::ZERO.is_normal(), false);
155    /// assert_eq!(Float::NEGATIVE_ZERO.is_normal(), false);
156    /// assert_eq!(Float::ONE.is_normal(), true);
157    /// ```
158    pub const fn is_normal(&self) -> bool {
159        matches!(self, float_finite!())
160    }
161
162    /// Determines whether a [`Float`]'s sign is positive.
163    ///
164    /// A NaN has no sign, so this function returns false when given a NaN.
165    ///
166    /// # Worst-case complexity
167    /// Constant time and additional memory.
168    ///
169    /// # Examples
170    /// ```
171    /// use malachite_base::num::basic::traits::{
172    ///     Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero,
173    /// };
174    /// use malachite_float::Float;
175    ///
176    /// assert_eq!(Float::NAN.is_sign_positive(), false);
177    /// assert_eq!(Float::INFINITY.is_sign_positive(), true);
178    /// assert_eq!(Float::NEGATIVE_INFINITY.is_sign_positive(), false);
179    /// assert_eq!(Float::ZERO.is_sign_positive(), true);
180    /// assert_eq!(Float::NEGATIVE_ZERO.is_sign_positive(), false);
181    /// assert_eq!(Float::ONE.is_sign_positive(), true);
182    /// assert_eq!(Float::NEGATIVE_ONE.is_sign_positive(), false);
183    /// ```
184    pub const fn is_sign_positive(&self) -> bool {
185        match self {
186            float_nan!() => false,
187            Self(Infinity { sign } | Finite { sign, .. } | Zero { sign, .. }) => *sign,
188        }
189    }
190
191    /// Determines whether a [`Float`]'s sign is negative.
192    ///
193    /// A NaN has no sign, so this function returns false when given a NaN.
194    ///
195    /// # Worst-case complexity
196    /// Constant time and additional memory.
197    ///
198    /// # Examples
199    /// ```
200    /// use malachite_base::num::basic::traits::{
201    ///     Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero,
202    /// };
203    /// use malachite_float::Float;
204    ///
205    /// assert_eq!(Float::NAN.is_sign_negative(), false);
206    /// assert_eq!(Float::INFINITY.is_sign_negative(), false);
207    /// assert_eq!(Float::NEGATIVE_INFINITY.is_sign_negative(), true);
208    /// assert_eq!(Float::ZERO.is_sign_negative(), false);
209    /// assert_eq!(Float::NEGATIVE_ZERO.is_sign_negative(), true);
210    /// assert_eq!(Float::ONE.is_sign_negative(), false);
211    /// assert_eq!(Float::NEGATIVE_ONE.is_sign_negative(), true);
212    /// ```
213    pub const fn is_sign_negative(&self) -> bool {
214        match self {
215            float_nan!() => false,
216            Self(Infinity { sign } | Finite { sign, .. } | Zero { sign, .. }) => !*sign,
217        }
218    }
219
220    /// Classifies a [`Float`] into one of several categories.
221    ///
222    /// # Worst-case complexity
223    /// Constant time and additional memory.
224    ///
225    /// # Examples
226    /// ```
227    /// use malachite_base::num::basic::traits::{
228    ///     Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero,
229    /// };
230    /// use malachite_float::Float;
231    /// use std::num::FpCategory;
232    ///
233    /// assert_eq!(Float::NAN.classify(), FpCategory::Nan);
234    /// assert_eq!(Float::INFINITY.classify(), FpCategory::Infinite);
235    /// assert_eq!(Float::NEGATIVE_INFINITY.classify(), FpCategory::Infinite);
236    /// assert_eq!(Float::ZERO.classify(), FpCategory::Zero);
237    /// assert_eq!(Float::NEGATIVE_ZERO.classify(), FpCategory::Zero);
238    /// assert_eq!(Float::ONE.classify(), FpCategory::Normal);
239    /// assert_eq!(Float::NEGATIVE_ONE.classify(), FpCategory::Normal);
240    /// ```
241    pub const fn classify(&self) -> FpCategory {
242        match self {
243            float_nan!() => FpCategory::Nan,
244            float_either_infinity!() => FpCategory::Infinite,
245            Self(Zero { .. }) => FpCategory::Zero,
246            _ => FpCategory::Normal,
247        }
248    }
249
250    /// Turns a NaN into a `None` and wraps any non-NaN [`Float`] with a `Some`. The [`Float`] is
251    /// taken by value.
252    ///
253    /// # Worst-case complexity
254    /// Constant time and additional memory.
255    ///
256    /// # Examples
257    /// ```
258    /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeZero, One, Zero};
259    /// use malachite_float::Float;
260    ///
261    /// assert_eq!(Float::NAN.into_non_nan(), None);
262    /// assert_eq!(Float::INFINITY.into_non_nan(), Some(Float::INFINITY));
263    /// assert_eq!(Float::ZERO.into_non_nan(), Some(Float::ZERO));
264    /// assert_eq!(
265    ///     Float::NEGATIVE_ZERO.into_non_nan(),
266    ///     Some(Float::NEGATIVE_ZERO)
267    /// );
268    /// assert_eq!(Float::ONE.into_non_nan(), Some(Float::ONE));
269    /// ```
270    #[allow(clippy::missing_const_for_fn)] // destructor doesn't work with const
271    pub fn into_non_nan(self) -> Option<Self> {
272        match self {
273            float_nan!() => None,
274            x => Some(x),
275        }
276    }
277
278    /// Turns a NaN into a `None` and wraps any non-NaN [`Float`] with a `Some`. The [`Float`] is
279    /// taken by reference.
280    ///
281    /// # Worst-case complexity
282    /// $T(n) = O(n)$
283    ///
284    /// $M(n) = O(n)$
285    ///
286    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
287    ///
288    /// # Examples
289    /// ```
290    /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeZero, One, Zero};
291    /// use malachite_float::Float;
292    ///
293    /// assert_eq!(Float::NAN.to_non_nan(), None);
294    /// assert_eq!(Float::INFINITY.to_non_nan(), Some(Float::INFINITY));
295    /// assert_eq!(Float::ZERO.to_non_nan(), Some(Float::ZERO));
296    /// assert_eq!(
297    ///     Float::NEGATIVE_ZERO.to_non_nan(),
298    ///     Some(Float::NEGATIVE_ZERO)
299    /// );
300    /// assert_eq!(Float::ONE.to_non_nan(), Some(Float::ONE));
301    /// ```
302    #[allow(clippy::missing_const_for_fn)] // destructor doesn't work with const
303    pub fn to_non_nan(&self) -> Option<Self> {
304        match self {
305            float_nan!() => None,
306            x => Some(x.clone()),
307        }
308    }
309
310    /// Turns any [`Float`] that's NaN or infinite into a `None` and wraps any finite [`Float`] with
311    /// a `Some`. The [`Float`] is taken by value.
312    ///
313    /// # Worst-case complexity
314    /// Constant time and additional memory.
315    ///
316    /// # Examples
317    /// ```
318    /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeZero, One, Zero};
319    /// use malachite_float::Float;
320    ///
321    /// assert_eq!(Float::NAN.into_finite(), None);
322    /// assert_eq!(Float::INFINITY.into_finite(), None);
323    /// assert_eq!(Float::ZERO.into_finite(), Some(Float::ZERO));
324    /// assert_eq!(
325    ///     Float::NEGATIVE_ZERO.into_finite(),
326    ///     Some(Float::NEGATIVE_ZERO)
327    /// );
328    /// assert_eq!(Float::ONE.into_finite(), Some(Float::ONE));
329    /// ```
330    #[allow(clippy::missing_const_for_fn)] // destructor doesn't work with const
331    pub fn into_finite(self) -> Option<Self> {
332        match self {
333            Self(NaN | Infinity { .. }) => None,
334            x => Some(x),
335        }
336    }
337
338    /// Turns any [`Float`] that's NaN or infinite into a `None` and wraps any finite [`Float`] with
339    /// a `Some`. The [`Float`] is taken by reference.
340    ///
341    /// # Worst-case complexity
342    /// $T(n) = O(n)$
343    ///
344    /// $M(n) = O(n)$
345    ///
346    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
347    ///
348    /// # Examples
349    /// ```
350    /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeZero, One, Zero};
351    /// use malachite_float::Float;
352    ///
353    /// assert_eq!(Float::NAN.to_finite(), None);
354    /// assert_eq!(Float::INFINITY.to_finite(), None);
355    /// assert_eq!(Float::ZERO.to_finite(), Some(Float::ZERO));
356    /// assert_eq!(Float::NEGATIVE_ZERO.to_finite(), Some(Float::NEGATIVE_ZERO));
357    /// assert_eq!(Float::ONE.to_finite(), Some(Float::ONE));
358    /// ```
359    pub fn to_finite(&self) -> Option<Self> {
360        match self {
361            Self(NaN | Infinity { .. }) => None,
362            x => Some(x.clone()),
363        }
364    }
365}