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);