malachite_float/conversion/
primitive_float_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, NaN, Zero};
10use crate::{Float, significand_bits};
11use core::cmp::Ordering::{self, *};
12use malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, IsPowerOf2, ShrRound};
13use malachite_base::num::basic::floats::PrimitiveFloat;
14use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom, WrappingFrom};
15use malachite_base::num::logic::traits::SignificantBits;
16use malachite_base::rounding_modes::RoundingMode::{self, *};
17
18fn primitive_float_rounding_from_float<T: PrimitiveFloat>(
19    f: Float,
20    rm: RoundingMode,
21) -> (T, Ordering) {
22    match f {
23        float_nan!() => (T::NAN, Equal),
24        float_infinity!() => (T::INFINITY, Equal),
25        float_negative_infinity!() => (T::NEGATIVE_INFINITY, Equal),
26        float_zero!() => (T::ZERO, Equal),
27        float_negative_zero!() => (T::NEGATIVE_ZERO, Equal),
28        Float(Finite {
29            sign,
30            exponent,
31            significand,
32            ..
33        }) => {
34            let abs_rm = if sign { rm } else { -rm };
35            let (x, o) = {
36                let exponent = i64::from(exponent) - 1;
37                if exponent < T::MIN_EXPONENT {
38                    match abs_rm {
39                        Floor | Down => (T::ZERO, Less),
40                        Ceiling | Up => (T::MIN_POSITIVE_SUBNORMAL, Greater),
41                        Nearest => {
42                            if exponent == T::MIN_EXPONENT - 1 && !significand.is_power_of_2() {
43                                (T::MIN_POSITIVE_SUBNORMAL, Greater)
44                            } else {
45                                (T::ZERO, Less)
46                            }
47                        }
48                        Exact => panic!("Float too small for exact conversion"),
49                    }
50                } else if exponent > T::MAX_EXPONENT {
51                    match abs_rm {
52                        Floor | Down => (T::MAX_FINITE, Less),
53                        Ceiling | Up | Nearest => (T::INFINITY, Greater),
54                        Exact => panic!("Float too large for exact conversion"),
55                    }
56                } else {
57                    let target_prec = T::max_precision_for_sci_exponent(exponent);
58                    let bits = significand_bits(&significand);
59                    let (mantissa, o) =
60                        significand.shr_round(i128::from(bits) - i128::from(target_prec), abs_rm);
61                    let mantissa = u64::wrapping_from(&mantissa);
62                    if mantissa.significant_bits() > target_prec {
63                        if exponent == T::MAX_EXPONENT {
64                            match abs_rm {
65                                Floor | Down => (T::MAX_FINITE, Less),
66                                Ceiling | Up | Nearest => (T::INFINITY, Greater),
67                                Exact => {
68                                    panic!("Float too large for exact conversion")
69                                }
70                            }
71                        } else {
72                            (
73                                T::from_integer_mantissa_and_exponent(
74                                    mantissa >> 1,
75                                    exponent - i64::wrapping_from(target_prec) + 2,
76                                )
77                                .unwrap(),
78                                o,
79                            )
80                        }
81                    } else {
82                        (
83                            T::from_integer_mantissa_and_exponent(
84                                mantissa,
85                                exponent - i64::wrapping_from(target_prec) + 1,
86                            )
87                            .unwrap(),
88                            o,
89                        )
90                    }
91                }
92            };
93            if sign { (x, o) } else { (-x, o.reverse()) }
94        }
95    }
96}
97
98fn primitive_float_rounding_from_float_ref<T: PrimitiveFloat>(
99    f: &Float,
100    rm: RoundingMode,
101) -> (T, Ordering) {
102    match f {
103        float_nan!() => (T::NAN, Equal),
104        float_infinity!() => (T::INFINITY, Equal),
105        float_negative_infinity!() => (T::NEGATIVE_INFINITY, Equal),
106        float_zero!() => (T::ZERO, Equal),
107        float_negative_zero!() => (T::NEGATIVE_ZERO, Equal),
108        Float(Finite {
109            sign,
110            exponent,
111            significand,
112            ..
113        }) => {
114            let abs_rm = if *sign { rm } else { -rm };
115            let (x, o) = {
116                let exponent = i64::from(*exponent) - 1;
117                if exponent < T::MIN_EXPONENT {
118                    match abs_rm {
119                        Floor | Down => (T::ZERO, Less),
120                        Ceiling | Up => (T::MIN_POSITIVE_SUBNORMAL, Greater),
121                        Nearest => {
122                            if exponent == T::MIN_EXPONENT - 1 && !significand.is_power_of_2() {
123                                (T::MIN_POSITIVE_SUBNORMAL, Greater)
124                            } else {
125                                (T::ZERO, Less)
126                            }
127                        }
128                        Exact => panic!("Float too small for exact conversion"),
129                    }
130                } else if exponent > T::MAX_EXPONENT {
131                    match abs_rm {
132                        Floor | Down => (T::MAX_FINITE, Less),
133                        Ceiling | Up | Nearest => (T::INFINITY, Greater),
134                        Exact => panic!("Float too large for exact conversion"),
135                    }
136                } else {
137                    let target_prec = T::max_precision_for_sci_exponent(exponent);
138                    let bits = significand_bits(significand);
139                    let (mantissa, o) =
140                        significand.shr_round(i128::from(bits) - i128::from(target_prec), abs_rm);
141                    let mantissa = u64::wrapping_from(&mantissa);
142                    if mantissa.significant_bits() > target_prec {
143                        if exponent == T::MAX_EXPONENT {
144                            match abs_rm {
145                                Floor | Down => (T::MAX_FINITE, Less),
146                                Ceiling | Up | Nearest => (T::INFINITY, Greater),
147
148                                Exact => {
149                                    panic!("Float too large for exact conversion")
150                                }
151                            }
152                        } else {
153                            (
154                                T::from_integer_mantissa_and_exponent(
155                                    mantissa >> 1,
156                                    exponent - i64::wrapping_from(target_prec) + 2,
157                                )
158                                .unwrap(),
159                                o,
160                            )
161                        }
162                    } else {
163                        (
164                            T::from_integer_mantissa_and_exponent(
165                                mantissa,
166                                exponent - i64::wrapping_from(target_prec) + 1,
167                            )
168                            .unwrap(),
169                            o,
170                        )
171                    }
172                }
173            };
174            if *sign { (x, o) } else { (-x, o.reverse()) }
175        }
176    }
177}
178
179#[derive(Clone, Copy, Debug, Eq, PartialEq)]
180pub enum FloatFromFloatError {
181    Overflow,
182    Underflow,
183    Inexact,
184}
185
186fn primitive_float_try_from_float<T: PrimitiveFloat>(f: Float) -> Result<T, FloatFromFloatError> {
187    match f {
188        float_nan!() => Ok(T::NAN),
189        float_infinity!() => Ok(T::INFINITY),
190        float_negative_infinity!() => Ok(T::NEGATIVE_INFINITY),
191        float_zero!() => Ok(T::ZERO),
192        float_negative_zero!() => Ok(T::NEGATIVE_ZERO),
193        Float(Finite {
194            sign,
195            exponent,
196            significand,
197            ..
198        }) => {
199            let x = {
200                let exponent = i64::from(exponent) - 1;
201                if exponent < T::MIN_EXPONENT {
202                    return Err(FloatFromFloatError::Underflow);
203                } else if exponent > T::MAX_EXPONENT {
204                    return Err(FloatFromFloatError::Overflow);
205                }
206                let target_prec = T::max_precision_for_sci_exponent(exponent);
207                let bits = significand_bits(&significand);
208                if bits > target_prec && !significand.divisible_by_power_of_2(bits - target_prec) {
209                    return Err(FloatFromFloatError::Inexact);
210                }
211                let mantissa = u64::wrapping_from(
212                    &(significand >> (i128::from(bits) - i128::from(target_prec))),
213                );
214                T::from_integer_mantissa_and_exponent(
215                    mantissa,
216                    exponent - i64::wrapping_from(target_prec) + 1,
217                )
218                .unwrap()
219            };
220            Ok(if sign { x } else { -x })
221        }
222    }
223}
224
225fn primitive_float_try_from_float_ref<T: PrimitiveFloat>(
226    f: &Float,
227) -> Result<T, FloatFromFloatError> {
228    match f {
229        float_nan!() => Ok(T::NAN),
230        float_infinity!() => Ok(T::INFINITY),
231        float_negative_infinity!() => Ok(T::NEGATIVE_INFINITY),
232        float_zero!() => Ok(T::ZERO),
233        float_negative_zero!() => Ok(T::NEGATIVE_ZERO),
234        Float(Finite {
235            sign,
236            exponent,
237            significand,
238            ..
239        }) => {
240            let x = if *significand == 0u32 {
241                T::ZERO
242            } else {
243                let exponent = i64::from(*exponent) - 1;
244                if exponent < T::MIN_EXPONENT {
245                    return Err(FloatFromFloatError::Underflow);
246                } else if exponent > T::MAX_EXPONENT {
247                    return Err(FloatFromFloatError::Overflow);
248                }
249                let target_prec = T::max_precision_for_sci_exponent(exponent);
250                let bits = significand_bits(significand);
251                if bits > target_prec && !significand.divisible_by_power_of_2(bits - target_prec) {
252                    return Err(FloatFromFloatError::Inexact);
253                }
254                let mantissa = u64::wrapping_from(
255                    &(significand >> (i128::from(bits) - i128::from(target_prec))),
256                );
257                T::from_integer_mantissa_and_exponent(
258                    mantissa,
259                    exponent - i64::wrapping_from(target_prec) + 1,
260                )
261                .unwrap()
262            };
263            Ok(if *sign { x } else { -x })
264        }
265    }
266}
267
268fn primitive_float_convertible_from_float<T: PrimitiveFloat>(f: &Float) -> bool {
269    match f {
270        Float(Finite {
271            exponent,
272            significand,
273            ..
274        }) => {
275            let exponent = i64::from(*exponent) - 1;
276            exponent >= T::MIN_EXPONENT && exponent <= T::MAX_EXPONENT && {
277                let target_prec = T::max_precision_for_sci_exponent(exponent);
278                let bits = significand_bits(significand);
279                bits <= target_prec || significand.divisible_by_power_of_2(bits - target_prec)
280            }
281        }
282        _ => true,
283    }
284}
285
286macro_rules! impl_primitive_float_from {
287    ($t: ident) => {
288        impl RoundingFrom<Float> for $t {
289            /// Converts a [`Float`] to a primitive float, using a specified [`RoundingMode`] and
290            /// taking the [`Float`] by value. An [`Ordering`] is also returned, indicating whether
291            /// the returned value is less than, equal to, or greater than the original value.
292            /// (Although a NaN is not comparable to any [`Float`], converting a NaN to a NaN will
293            /// also return `Equal`, indicating an exact conversion.)
294            ///
295            /// Overflow and underflow:
296            /// - If the rounding mode is `Floor`, the largest primitive float less than or equal to
297            ///   the [`Float`] is returned. If the [`Float`] is greater than the maximum finite
298            ///   primitive float, then the maximum finite primitive float is returned. If it is
299            ///   smaller than the minimum finite primitive float, then $-\infty$ is returned. If it
300            ///   is between zero and the minimum positive primitive float, then positive zero is
301            ///   returned.
302            /// - If the rounding mode is `Ceiling`, the smallest primitive float greater than or
303            ///   equal to the [`Float`] is returned. If the [`Float`] is greater than the maximum
304            ///   finite primitive float, then $\infty$ is returned. If it is smaller than the
305            ///   minimum finite primitive float, then the minimum finite primitive float is
306            ///   returned. If it is between zero and the maximum negative primitive float, then
307            ///   negative zero is returned.
308            /// - If the rounding mode is `Down`, then the rounding proceeds as with `Floor` if the
309            ///   [`Float`] is non-negative and as with `Ceiling` if the [`Float`] is negative. If
310            ///   the [`Float`] is between the maximum negative primitive float and the minimum
311            ///   positive primitive float, then positive zero is returned when the [`Float`] is
312            ///   non-negative and negative zero otherwise.
313            /// - If the rounding mode is `Up`, then the rounding proceeds as with `Ceiling` if the
314            ///   [`Float`] is non-negative and as with `Floor` if the [`Float`] is negative. Zero
315            ///   is only returned when the [`Float`] is zero.
316            /// - If the rounding mode is `Nearest`, then the nearest primitive float is returned.
317            ///   If the [`Float`] is exactly between two primitive floats, the primitive float with
318            ///   the zero least-significant bit in its representation is selected. If the [`Float`]
319            ///   is greater than the maximum finite primitive float, then $\infty$ is returned. If
320            ///   the [`Float`] is smaller than the minimum finite primitive float, then $-\infty$
321            ///   is returned. If the [`Float`] is closer to zero than to any other primitive float
322            ///   (or if there is a tie between zero and another float), then positive or negative
323            ///   zero is returned, depending on the [`Float`]'s sign.
324            ///
325            /// # Worst-case complexity
326            /// Constant time and additional memory.
327            ///
328            /// # Panics
329            /// Panics if the [`Float`] is not exactly equal to any float of the target type, and
330            /// `rm` is `Exact`.
331            ///
332            /// # Examples
333            /// See [here](super::primitive_float_from_float#rounding_from).
334            #[inline]
335            fn rounding_from(f: Float, rm: RoundingMode) -> ($t, Ordering) {
336                primitive_float_rounding_from_float(f, rm)
337            }
338        }
339
340        impl RoundingFrom<&Float> for $t {
341            /// Converts a [`Float`] to a primitive float, using a specified [`RoundingMode`] and
342            /// taking the [`Float`] by reference. An [`Ordering`] is also returned, indicating
343            /// whether the returned value is less than, equal to, or greater than the original
344            /// value. (Although a NaN is not comparable to any [`Float`], converting a NaN to a NaN
345            /// will also return `Equal`, indicating an exact conversion.)
346            ///
347            /// Overflow and underflow:
348            /// - If the rounding mode is `Floor`, the largest primitive float less than or equal to
349            ///   the [`Float`] is returned. If the [`Float`] is greater than the maximum finite
350            ///   primitive float, then the maximum finite primitive float is returned. If it is
351            ///   smaller than the minimum finite primitive float, then $-\infty$ is returned. If it
352            ///   is between zero and the minimum positive primitive float, then positive zero is
353            ///   returned.
354            /// - If the rounding mode is `Ceiling`, the smallest primitive float greater than or
355            ///   equal to the [`Float`] is returned. If the [`Float`] is greater than the maximum
356            ///   finite primitive float, then $\infty$ is returned. If it is smaller than the
357            ///   minimum finite primitive float, then the minimum finite primitive float is
358            ///   returned. If it is between zero and the maximum negative primitive float, then
359            ///   negative zero is returned.
360            /// - If the rounding mode is `Down`, then the rounding proceeds as with `Floor` if the
361            ///   [`Float`] is non-negative and as with `Ceiling` if the [`Float`] is negative. If
362            ///   the [`Float`] is between the maximum negative primitive float and the minimum
363            ///   positive primitive float, then positive zero is returned when the [`Float`] is
364            ///   non-negative and negative zero otherwise.
365            /// - If the rounding mode is `Up`, then the rounding proceeds as with `Ceiling` if the
366            ///   [`Float`] is non-negative and as with `Floor` if the [`Float`] is negative. Zero
367            ///   is only returned when the [`Float`] is zero.
368            /// - If the rounding mode is `Nearest`, then the nearest primitive float is returned.
369            ///   If the [`Float`] is exactly between two primitive floats, the primitive float with
370            ///   the zero least-significant bit in its representation is selected. If the [`Float`]
371            ///   is greater than the maximum finite primitive float, then $\infty$ is returned. If
372            ///   the [`Float`] is smaller than the minimum finite primitive float, then $-\infty$
373            ///   is returned. If the [`Float`] is closer to zero than to any other primitive float
374            ///   (or if there is a tie between zero and another float), then positive or negative
375            ///   zero is returned, depending on the [`Float`]'s sign.
376            ///
377            /// # Worst-case complexity
378            /// Constant time and additional memory.
379            ///
380            /// # Panics
381            /// Panics if the [`Float`] is not exactly equal to any float of the target type, and
382            /// `rm` is `Exact`.
383            ///
384            /// # Examples
385            /// See [here](super::primitive_float_from_float#rounding_from).
386            #[inline]
387            fn rounding_from(f: &Float, rm: RoundingMode) -> ($t, Ordering) {
388                primitive_float_rounding_from_float_ref(f, rm)
389            }
390        }
391
392        impl TryFrom<Float> for $t {
393            type Error = FloatFromFloatError;
394
395            /// Converts a [`Float`] to a primitive float, taking the [`Float`] by value. If the
396            /// [`Float`] is not equal to a primitive float of the given type, an error is returned.
397            ///
398            /// # Worst-case complexity
399            /// Constant time and additional memory.
400            ///
401            /// # Examples
402            /// See [here](super::primitive_float_from_float#try_from).
403            #[inline]
404            fn try_from(f: Float) -> Result<$t, Self::Error> {
405                primitive_float_try_from_float(f)
406            }
407        }
408
409        impl TryFrom<&Float> for $t {
410            type Error = FloatFromFloatError;
411
412            /// Converts a [`Float`] to a primitive float, taking the [`Float`] by reference. If the
413            /// [`Float`] is not equal to a primitive float of the given type, an error is returned.
414            ///
415            /// # Worst-case complexity
416            /// Constant time and additional memory.
417            ///
418            /// # Examples
419            /// See [here](super::primitive_float_from_float#try_from).
420            #[inline]
421            fn try_from(f: &Float) -> Result<$t, Self::Error> {
422                primitive_float_try_from_float_ref(f)
423            }
424        }
425
426        impl ConvertibleFrom<&Float> for $t {
427            /// Determines whether a [`Float`] can be converted to a primitive float, taking the
428            /// [`Float`] by reference.
429            ///
430            /// # Worst-case complexity
431            /// Constant time and additional memory.
432            ///
433            /// # Examples
434            /// See [here](super::primitive_float_from_float#convertible_from).
435            #[inline]
436            fn convertible_from(f: &Float) -> bool {
437                primitive_float_convertible_from_float::<$t>(f)
438            }
439        }
440    };
441}
442apply_to_primitive_floats!(impl_primitive_float_from);