malachite_float/conversion/
natural_from_float.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, Zero};
10use crate::{Float, significand_bits};
11use core::cmp::Ordering::{self, *};
12use malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, ShrRound};
13use malachite_base::num::basic::traits::{One, Zero as ZeroTrait};
14use malachite_base::num::conversion::from::UnsignedFromFloatError;
15use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom};
16use malachite_base::rounding_modes::RoundingMode::{self, *};
17use malachite_nz::natural::Natural;
18
19impl RoundingFrom<Float> for Natural {
20    /// Converts a [`Float`] to a [`Natural`], using a specified [`RoundingMode`] and taking the
21    /// [`Float`] by value. An [`Ordering`] is also returned, indicating whether the returned value
22    /// is less than, equal to, or greater than the original value.
23    ///
24    /// If the [`Float`] is negative (including $-\infty$), then it will be rounded to zero when the
25    /// [`RoundingMode`] is `Ceiling`, `Down`, or `Nearest`. Otherwise, this function will panic.
26    ///
27    /// If the [`Float`] is NaN or $\infty$, the function will panic regardless of the rounding
28    /// mode.
29    ///
30    /// # Worst-case complexity
31    /// $T(n) = O(n)$
32    ///
33    /// $M(n) = O(n)$
34    ///
35    /// where $T$ is time, $M$ is additional memory, and $n$ is `f.complexity()`.
36    ///
37    /// # Panics
38    /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`] is less
39    /// than zero and `rm` is not `Down`, `Ceiling`, or `Nearest`, or if the [`Float`] is NaN or
40    /// $\infty$.
41    ///
42    /// # Examples
43    /// ```
44    /// use malachite_base::num::basic::traits::NegativeInfinity;
45    /// use malachite_base::num::conversion::traits::RoundingFrom;
46    /// use malachite_base::rounding_modes::RoundingMode::*;
47    /// use malachite_base::strings::ToDebugString;
48    /// use malachite_float::Float;
49    /// use malachite_nz::natural::Natural;
50    ///
51    /// assert_eq!(
52    ///     Natural::rounding_from(Float::from(1.5), Floor).to_debug_string(),
53    ///     "(1, Less)"
54    /// );
55    /// assert_eq!(
56    ///     Natural::rounding_from(Float::from(1.5), Ceiling).to_debug_string(),
57    ///     "(2, Greater)"
58    /// );
59    /// assert_eq!(
60    ///     Natural::rounding_from(Float::from(1.5), Nearest).to_debug_string(),
61    ///     "(2, Greater)"
62    /// );
63    ///
64    /// assert_eq!(
65    ///     Natural::rounding_from(Float::NEGATIVE_INFINITY, Down).to_debug_string(),
66    ///     "(0, Greater)"
67    /// );
68    /// assert_eq!(
69    ///     Natural::rounding_from(Float::NEGATIVE_INFINITY, Ceiling).to_debug_string(),
70    ///     "(0, Greater)"
71    /// );
72    /// assert_eq!(
73    ///     Natural::rounding_from(Float::NEGATIVE_INFINITY, Nearest).to_debug_string(),
74    ///     "(0, Greater)"
75    /// );
76    /// ```
77    fn rounding_from(f: Float, rm: RoundingMode) -> (Self, Ordering) {
78        match f {
79            float_either_zero!() => (Self::ZERO, Equal),
80            float_negative_infinity!() => match rm {
81                Ceiling | Down | Nearest => (Self::ZERO, Greater),
82                _ => panic!("Can't convert -Infinity to Natural using {rm}"),
83            },
84            Float(Finite {
85                sign,
86                exponent,
87                significand,
88                ..
89            }) => {
90                if !sign {
91                    match rm {
92                        Ceiling | Down | Nearest => (Self::ZERO, Greater),
93                        _ => panic!("Cannot convert negative number to Natural using {rm}"),
94                    }
95                } else if exponent < 0 {
96                    match rm {
97                        Floor | Down | Nearest => (Self::ZERO, Less),
98                        Ceiling | Up => (Self::ONE, Greater),
99                        Exact => panic!("Cannot convert Float to Natural using {rm}"),
100                    }
101                } else {
102                    let sb = significand_bits(&significand);
103                    let eb = u64::from(exponent.unsigned_abs());
104                    if sb >= eb {
105                        significand.shr_round(sb - eb, rm)
106                    } else {
107                        (significand << (eb - sb), Equal)
108                    }
109                }
110            }
111            _ => panic!("Can't convert {f} to Natural using {rm}"),
112        }
113    }
114}
115
116impl RoundingFrom<&Float> for Natural {
117    /// Converts a [`Float`] to a [`Natural`], using a specified [`RoundingMode`] and taking the
118    /// [`Float`] by reference. An [`Ordering`] is also returned, indicating whether the returned
119    /// value is less than, equal to, or greater than the original value.
120    ///
121    /// If the [`Float`] is negative (including $-\infty$), then it will be rounded to zero when the
122    /// [`RoundingMode`] is `Ceiling`, `Down`, or `Nearest`. Otherwise, this function will panic.
123    ///
124    /// If the [`Float`] is NaN or $\infty$, the function will panic regardless of the rounding
125    /// mode.
126    ///
127    /// # Worst-case complexity
128    /// $T(n) = O(n)$
129    ///
130    /// $M(n) = O(n)$
131    ///
132    /// where $T$ is time, $M$ is additional memory, and $n$ is `f.complexity()`.
133    ///
134    /// # Panics
135    /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`] is less
136    /// than zero and `rm` is not `Down`, `Ceiling`, or `Nearest`, or if the [`Float`] is NaN or
137    /// $\infty$.
138    ///
139    /// # Examples
140    /// ```
141    /// use malachite_base::num::basic::traits::NegativeInfinity;
142    /// use malachite_base::num::conversion::traits::RoundingFrom;
143    /// use malachite_base::rounding_modes::RoundingMode::*;
144    /// use malachite_base::strings::ToDebugString;
145    /// use malachite_float::Float;
146    /// use malachite_nz::natural::Natural;
147    ///
148    /// assert_eq!(
149    ///     Natural::rounding_from(&Float::from(1.5), Floor).to_debug_string(),
150    ///     "(1, Less)"
151    /// );
152    /// assert_eq!(
153    ///     Natural::rounding_from(&Float::from(1.5), Ceiling).to_debug_string(),
154    ///     "(2, Greater)"
155    /// );
156    /// assert_eq!(
157    ///     Natural::rounding_from(&Float::from(1.5), Nearest).to_debug_string(),
158    ///     "(2, Greater)"
159    /// );
160    ///
161    /// assert_eq!(
162    ///     Natural::rounding_from(&Float::NEGATIVE_INFINITY, Down).to_debug_string(),
163    ///     "(0, Greater)"
164    /// );
165    /// assert_eq!(
166    ///     Natural::rounding_from(&Float::NEGATIVE_INFINITY, Ceiling).to_debug_string(),
167    ///     "(0, Greater)"
168    /// );
169    /// assert_eq!(
170    ///     Natural::rounding_from(&Float::NEGATIVE_INFINITY, Nearest).to_debug_string(),
171    ///     "(0, Greater)"
172    /// );
173    /// ```
174    fn rounding_from(f: &Float, rm: RoundingMode) -> (Self, Ordering) {
175        match f {
176            float_either_zero!() => (Self::ZERO, Equal),
177            float_negative_infinity!() => match rm {
178                Ceiling | Down | Nearest => (Self::ZERO, Greater),
179                _ => panic!("Can't convert -Infinity to Natural using {rm}"),
180            },
181            Float(Finite {
182                sign,
183                exponent,
184                significand,
185                ..
186            }) => {
187                if !sign {
188                    match rm {
189                        Ceiling | Down | Nearest => (Self::ZERO, Greater),
190                        _ => panic!("Cannot convert -Infinity to Natural using {rm}"),
191                    }
192                } else if *exponent < 0 {
193                    match rm {
194                        Floor | Down | Nearest => (Self::ZERO, Less),
195                        Ceiling | Up => (Self::ONE, Greater),
196                        Exact => panic!("Cannot convert Float to Natural using {rm}"),
197                    }
198                } else {
199                    let sb = significand_bits(significand);
200                    let eb = u64::from(exponent.unsigned_abs());
201                    if sb >= eb {
202                        significand.shr_round(sb - eb, rm)
203                    } else {
204                        (significand << (eb - sb), Equal)
205                    }
206                }
207            }
208            _ => panic!("Can't convert {f} to Natural using {rm}"),
209        }
210    }
211}
212
213impl TryFrom<Float> for Natural {
214    type Error = UnsignedFromFloatError;
215
216    /// Converts a [`Float`] to a [`Natural`], taking the [`Float`] by value. If the [`Float`] is
217    /// not equal to a non-negative integer, an error is returned.
218    ///
219    /// Both positive and negative zero convert to a [`Natural`] zero.
220    ///
221    /// # Worst-case complexity
222    /// $T(n) = O(n)$
223    ///
224    /// $M(n) = O(n)$
225    ///
226    /// where $T$ is time, $M$ is additional memory, and $n$ is `f.complexity()`.
227    ///
228    /// # Examples
229    /// ```
230    /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero};
231    /// use malachite_base::num::conversion::from::UnsignedFromFloatError::*;
232    /// use malachite_float::Float;
233    /// use malachite_nz::natural::Natural;
234    ///
235    /// assert_eq!(Natural::try_from(Float::ZERO).unwrap(), 0);
236    /// assert_eq!(Natural::try_from(Float::from(123.0)).unwrap(), 123);
237    ///
238    /// assert_eq!(Natural::try_from(Float::from(-123.0)), Err(FloatNegative));
239    /// assert_eq!(
240    ///     Natural::try_from(Float::from(1.5)),
241    ///     Err(FloatNonIntegerOrOutOfRange)
242    /// );
243    /// assert_eq!(Natural::try_from(Float::INFINITY), Err(FloatInfiniteOrNan));
244    /// assert_eq!(Natural::try_from(Float::NAN), Err(FloatInfiniteOrNan));
245    /// ```
246    fn try_from(f: Float) -> Result<Self, Self::Error> {
247        match f {
248            float_either_zero!() => Ok(Self::ZERO),
249            Float(Finite {
250                sign,
251                exponent,
252                significand,
253                ..
254            }) => {
255                if !sign {
256                    Err(UnsignedFromFloatError::FloatNegative)
257                } else if exponent <= 0 {
258                    Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange)
259                } else {
260                    let sb = significand_bits(&significand);
261                    let eb = u64::from(exponent.unsigned_abs());
262                    if sb >= eb {
263                        let bits = sb - eb;
264                        if significand.divisible_by_power_of_2(bits) {
265                            Ok(significand >> bits)
266                        } else {
267                            Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange)
268                        }
269                    } else {
270                        Ok(significand << (eb - sb))
271                    }
272                }
273            }
274            _ => Err(UnsignedFromFloatError::FloatInfiniteOrNan),
275        }
276    }
277}
278
279impl TryFrom<&Float> for Natural {
280    type Error = UnsignedFromFloatError;
281
282    /// Converts a [`Float`] to a [`Natural`], taking the [`Float`] by reference. If the [`Float`]
283    /// is not equal to a non-negative integer, an error is returned.
284    ///
285    /// Both positive and negative zero convert to a [`Natural`] zero.
286    ///
287    /// # Worst-case complexity
288    /// $T(n) = O(n)$
289    ///
290    /// $M(n) = O(n)$
291    ///
292    /// where $T$ is time, $M$ is additional memory, and $n$ is `f.complexity()`.
293    ///
294    /// # Examples
295    /// ```
296    /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero};
297    /// use malachite_base::num::conversion::from::UnsignedFromFloatError::*;
298    /// use malachite_float::Float;
299    /// use malachite_nz::natural::Natural;
300    ///
301    /// assert_eq!(Natural::try_from(&Float::ZERO).unwrap(), 0);
302    /// assert_eq!(Natural::try_from(&Float::from(123.0)).unwrap(), 123);
303    ///
304    /// assert_eq!(Natural::try_from(&Float::from(-123.0)), Err(FloatNegative));
305    /// assert_eq!(
306    ///     Natural::try_from(&Float::from(1.5)),
307    ///     Err(FloatNonIntegerOrOutOfRange)
308    /// );
309    /// assert_eq!(Natural::try_from(&Float::INFINITY), Err(FloatInfiniteOrNan));
310    /// assert_eq!(Natural::try_from(&Float::NAN), Err(FloatInfiniteOrNan));
311    /// ```
312    fn try_from(f: &Float) -> Result<Self, Self::Error> {
313        match f {
314            float_either_zero!() => Ok(Self::ZERO),
315            Float(Finite {
316                sign,
317                exponent,
318                significand,
319                ..
320            }) => {
321                if !*sign {
322                    Err(UnsignedFromFloatError::FloatNegative)
323                } else if *exponent <= 0 {
324                    Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange)
325                } else {
326                    let sb = significand_bits(significand);
327                    let eb = u64::from(exponent.unsigned_abs());
328                    if sb >= eb {
329                        let bits = sb - eb;
330                        if significand.divisible_by_power_of_2(bits) {
331                            Ok(significand >> bits)
332                        } else {
333                            Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange)
334                        }
335                    } else {
336                        Ok(significand << (eb - sb))
337                    }
338                }
339            }
340            _ => Err(UnsignedFromFloatError::FloatInfiniteOrNan),
341        }
342    }
343}
344
345impl ConvertibleFrom<&Float> for Natural {
346    /// Determines whether a [`Float`] can be converted to a [`Natural`] (when the [`Float`] is
347    /// non-negative and an integer), taking the [`Float`] by reference.
348    ///
349    /// Both positive and negative zero are convertible to a [`Natural`]. (Although negative zero is
350    /// nominally negative, the real number it represents is zero, which is not negative.)
351    ///
352    /// # Worst-case complexity
353    /// $T(n) = O(n)$
354    ///
355    /// $M(n) = O(n)$
356    ///
357    /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`.
358    ///
359    /// # Examples
360    /// ```
361    /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero};
362    /// use malachite_base::num::conversion::traits::ConvertibleFrom;
363    /// use malachite_float::Float;
364    /// use malachite_nz::natural::Natural;
365    ///
366    /// assert_eq!(Natural::convertible_from(&Float::ZERO), true);
367    /// assert_eq!(Natural::convertible_from(&Float::from(123.0)), true);
368    ///
369    /// assert_eq!(Natural::convertible_from(&Float::from(-123.0)), false);
370    /// assert_eq!(Natural::convertible_from(&Float::from(1.5)), false);
371    /// assert_eq!(Natural::convertible_from(&Float::INFINITY), false);
372    /// assert_eq!(Natural::convertible_from(&Float::NAN), false);
373    /// ```
374    fn convertible_from(f: &Float) -> bool {
375        match f {
376            float_either_zero!() => true,
377            Float(Finite {
378                sign,
379                exponent,
380                significand,
381                ..
382            }) => {
383                *sign && *exponent > 0 && {
384                    let sb = significand_bits(significand);
385                    let eb = u64::from(exponent.unsigned_abs());
386                    sb < eb || significand.divisible_by_power_of_2(sb - eb)
387                }
388            }
389            _ => false,
390        }
391    }
392}