malachite_float/float/conversion/primitive_int_from_float.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::float::arithmetic::is_power_of_2::float_is_signed_min;
11use crate::{Float, significand_bits};
12use core::cmp::Ordering::{self, *};
13use malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, ShrRound};
14use malachite_base::num::basic::signeds::PrimitiveSigned;
15use malachite_base::num::basic::unsigneds::PrimitiveUnsigned;
16use malachite_base::num::conversion::from::{SignedFromFloatError, UnsignedFromFloatError};
17use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom, WrappingFrom};
18use malachite_base::rounding_modes::RoundingMode::{self, *};
19use malachite_nz::integer::Integer;
20use malachite_nz::natural::Natural;
21
22#[allow(clippy::type_repetition_in_bounds)]
23fn unsigned_rounding_from_float<T: PrimitiveUnsigned>(f: Float, rm: RoundingMode) -> (T, Ordering)
24where
25 for<'a> T: TryFrom<&'a Natural>,
26{
27 match f {
28 float_nan!() => panic!("Can't convert NaN to {}", T::NAME),
29 float_infinity!() => match rm {
30 Floor | Down | Nearest => (T::MAX, Less),
31 _ => panic!("Can't convert Infinity to {} using {}", T::NAME, rm),
32 },
33 float_negative_infinity!() => match rm {
34 Ceiling | Down | Nearest => (T::ZERO, Greater),
35 _ => panic!("Can't convert -Infinity to {} using {}", T::NAME, rm),
36 },
37 float_either_zero!() => (T::ZERO, Equal),
38 Float(Finite {
39 sign,
40 exponent,
41 significand,
42 ..
43 }) => {
44 let exponent = i64::from(exponent);
45 if !sign {
46 match rm {
47 Ceiling | Down | Nearest => (T::ZERO, Greater),
48 _ => panic!("Cannot convert negative Float to {} using {}", T::NAME, rm),
49 }
50 } else if exponent < 0 {
51 match rm {
52 Floor | Down | Nearest => (T::ZERO, Less),
53 Ceiling | Up => (T::ONE, Greater),
54 Exact => {
55 panic!("Cannot convert Float to {} using {}", T::NAME, rm)
56 }
57 }
58 } else if exponent > i64::wrapping_from(T::WIDTH) {
59 match rm {
60 Floor | Down | Nearest => (T::MAX, Less),
61 _ => panic!("Cannot convert large Float to {} using {}", T::NAME, rm),
62 }
63 } else {
64 let sb = significand_bits(&significand);
65 let eb = exponent.unsigned_abs();
66 let (n, o) = if sb >= eb {
67 significand.shr_round(sb - eb, rm)
68 } else {
69 (significand << (eb - sb), Equal)
70 };
71 if let Ok(n) = T::try_from(&n) {
72 (n, o)
73 } else {
74 match rm {
75 Floor | Down | Nearest => (T::MAX, Less),
76 _ => panic!("Cannot convert large Float to {} using {}", T::NAME, rm),
77 }
78 }
79 }
80 }
81 }
82}
83
84#[allow(clippy::type_repetition_in_bounds)]
85fn unsigned_rounding_from_float_ref<T: PrimitiveUnsigned>(
86 f: &Float,
87 rm: RoundingMode,
88) -> (T, Ordering)
89where
90 for<'a> T: TryFrom<&'a Natural>,
91{
92 match f {
93 float_nan!() => panic!("Can't convert NaN to {}", T::NAME),
94 float_infinity!() => match rm {
95 Floor | Down | Nearest => (T::MAX, Less),
96 _ => panic!("Can't convert Infinity to {} using {}", T::NAME, rm),
97 },
98 float_negative_infinity!() => match rm {
99 Ceiling | Down | Nearest => (T::ZERO, Greater),
100 _ => panic!("Can't convert -Infinity to {} using {}", T::NAME, rm),
101 },
102 float_either_zero!() => (T::ZERO, Equal),
103 Float(Finite {
104 sign,
105 exponent,
106 significand,
107 ..
108 }) => {
109 let exponent = i64::from(*exponent);
110 if !sign {
111 match rm {
112 Ceiling | Down | Nearest => (T::ZERO, Greater),
113 _ => panic!("Cannot convert negative Float to {} using {}", T::NAME, rm),
114 }
115 } else if exponent < 0 {
116 match rm {
117 Floor | Down | Nearest => (T::ZERO, Less),
118 Ceiling | Up => (T::ONE, Greater),
119 Exact => {
120 panic!("Cannot convert Float to {} using {}", T::NAME, rm)
121 }
122 }
123 } else if exponent > i64::wrapping_from(T::WIDTH) {
124 match rm {
125 Floor | Down | Nearest => (T::MAX, Less),
126 _ => panic!("Cannot convert large Float to {} using {}", T::NAME, rm),
127 }
128 } else {
129 let sb = significand_bits(significand);
130 let eb = exponent.unsigned_abs();
131 let (n, o) = if sb >= eb {
132 significand.shr_round(sb - eb, rm)
133 } else {
134 (significand << (eb - sb), Equal)
135 };
136 if let Ok(n) = T::try_from(&n) {
137 (n, o)
138 } else {
139 match rm {
140 Floor | Down | Nearest => (T::MAX, Less),
141 _ => panic!("Cannot convert large Float to {} using {}", T::NAME, rm),
142 }
143 }
144 }
145 }
146 }
147}
148
149#[allow(clippy::type_repetition_in_bounds)]
150fn unsigned_try_from_float<T: PrimitiveUnsigned>(f: Float) -> Result<T, UnsignedFromFloatError>
151where
152 for<'a> T: WrappingFrom<&'a Natural>,
153{
154 match f {
155 float_either_zero!() => Ok(T::ZERO),
156 Float(Finite {
157 sign,
158 exponent,
159 significand,
160 ..
161 }) => {
162 let exponent = i64::from(exponent);
163 if !sign {
164 Err(UnsignedFromFloatError::FloatNegative)
165 } else if exponent <= 0 || exponent > i64::wrapping_from(T::WIDTH) {
166 Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange)
167 } else {
168 let sb = significand_bits(&significand);
169 let eb = exponent.unsigned_abs();
170 let n = if sb >= eb {
171 let bits = sb - eb;
172 if significand.divisible_by_power_of_2(bits) {
173 Ok(significand >> bits)
174 } else {
175 Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange)
176 }
177 } else {
178 Ok(significand << (eb - sb))
179 };
180 n.map(|n| T::wrapping_from(&n))
181 }
182 }
183 _ => Err(UnsignedFromFloatError::FloatInfiniteOrNan),
184 }
185}
186
187#[allow(clippy::type_repetition_in_bounds)]
188fn unsigned_try_from_float_ref<T: PrimitiveUnsigned>(f: &Float) -> Result<T, UnsignedFromFloatError>
189where
190 for<'a> T: WrappingFrom<&'a Natural>,
191{
192 match f {
193 float_either_zero!() => Ok(T::ZERO),
194 Float(Finite {
195 sign,
196 exponent,
197 significand,
198 ..
199 }) => {
200 let exponent = i64::from(*exponent);
201 if !sign {
202 Err(UnsignedFromFloatError::FloatNegative)
203 } else if exponent <= 0 || exponent > i64::wrapping_from(T::WIDTH) {
204 Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange)
205 } else {
206 let sb = significand_bits(significand);
207 let eb = exponent.unsigned_abs();
208 let n = if sb >= eb {
209 let bits = sb - eb;
210 if significand.divisible_by_power_of_2(bits) {
211 Ok(significand >> bits)
212 } else {
213 Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange)
214 }
215 } else {
216 Ok(significand << (eb - sb))
217 };
218 n.map(|n| T::wrapping_from(&n))
219 }
220 }
221 _ => Err(UnsignedFromFloatError::FloatInfiniteOrNan),
222 }
223}
224
225fn unsigned_convertible_from_float<T: PrimitiveUnsigned>(f: &Float) -> bool {
226 match f {
227 float_either_zero!() => true,
228 Float(Finite {
229 sign,
230 exponent,
231 significand,
232 ..
233 }) => {
234 let exponent = i64::from(*exponent);
235 *sign && exponent > 0 && exponent <= i64::wrapping_from(T::WIDTH) && {
236 let sb = significand_bits(significand);
237 let eb = exponent.unsigned_abs();
238 sb < eb || significand.divisible_by_power_of_2(sb - eb)
239 }
240 }
241 _ => false,
242 }
243}
244
245macro_rules! impl_unsigned_from {
246 ($t: ident) => {
247 impl RoundingFrom<Float> for $t {
248 /// Converts a [`Float`] to an unsigned primitive integer, using a specified
249 /// [`RoundingMode`] and taking the [`Float`] by value. An [`Ordering`] is also
250 /// returned, indicating whether the returned value is less than, equal to, or greater
251 /// than the original value.
252 ///
253 /// If the [`Float`] is negative (including $-\infty$), then it will be rounded to zero
254 /// when the [`RoundingMode`] is `Ceiling`, `Down`, or `Nearest`. Otherwise, this
255 /// function will panic.
256 ///
257 /// If the [`Float`] is greater than the maximum representable value of the unsigned
258 /// type (including $\infty$), then it will be rounded to the maximum value when the
259 /// [`RoundingMode`] is `Floor`, `Down`, or `Nearest`. Otherwise, this function will
260 /// panic.
261 ///
262 /// If the [`Float`] is NaN, the function will panic regardless of the rounding mode.
263 ///
264 /// # Worst-case complexity
265 /// $T(n) = O(n)$
266 ///
267 /// $M(n) = O(1)$
268 ///
269 /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
270 /// rounding must examine the bits that are discarded.
271 ///
272 /// # Panics
273 /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`]
274 /// is less than zero and `rm` is not `Down`, `Ceiling`, or `Nearest`, if the [`Float`]
275 /// is greater than the maximum representable value of the unsigned type and `rm` is not
276 /// `Down`, `Floor`, or `Nearest`, or if the [`Float`] is NaN.
277 ///
278 /// # Examples
279 /// See [here](super::primitive_int_from_float#rounding_from).
280 #[inline]
281 fn rounding_from(f: Float, rm: RoundingMode) -> ($t, Ordering) {
282 unsigned_rounding_from_float(f, rm)
283 }
284 }
285
286 impl RoundingFrom<&Float> for $t {
287 /// Converts a [`Float`] to an unsigned primitive integer, using a specified
288 /// [`RoundingMode`] and taking the [`Float`] by reference. An [`Ordering`] is also
289 /// returned, indicating whether the returned value is less than, equal to, or greater
290 /// than the original value.
291 ///
292 /// If the [`Float`] is negative (including $-\infty$), then it will be rounded to zero
293 /// when the [`RoundingMode`] is `Ceiling`, `Down`, or `Nearest`. Otherwise, this
294 /// function will panic.
295 ///
296 /// If the [`Float`] is greater than the maximum representable value of the unsigned
297 /// type (including $\infty$), then it will be rounded to the maximum value when the
298 /// [`RoundingMode`] is `Floor`, `Down`, or `Nearest`. Otherwise, this function will
299 /// panic.
300 ///
301 /// If the [`Float`] is NaN, the function will panic regardless of the rounding mode.
302 ///
303 /// # Worst-case complexity
304 /// $T(n) = O(n)$
305 ///
306 /// $M(n) = O(1)$
307 ///
308 /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
309 /// rounding must examine the bits that are discarded.
310 ///
311 /// # Panics
312 /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`]
313 /// is less than zero and `rm` is not `Down`, `Ceiling`, or `Nearest`, if the [`Float`]
314 /// is greater than the maximum representable value of the unsigned type and `rm` is not
315 /// `Down`, `Floor`, or `Nearest`, or if the [`Float`] is NaN.
316 ///
317 /// # Examples
318 /// See [here](super::primitive_int_from_float#rounding_from).
319 #[inline]
320 fn rounding_from(f: &Float, rm: RoundingMode) -> ($t, Ordering) {
321 unsigned_rounding_from_float_ref(f, rm)
322 }
323 }
324
325 impl TryFrom<Float> for $t {
326 type Error = UnsignedFromFloatError;
327
328 /// Converts a [`Float`] to a primitive unsigned integer, taking the [`Float`] by value.
329 /// If the [`Float`] is not equal to an unsigned primitive integer of the given type, an
330 /// error is returned.
331 ///
332 /// Both positive and negative zero convert to a primitive unsigned integer zero.
333 ///
334 /// # Worst-case complexity
335 /// $T(n) = O(n)$
336 ///
337 /// $M(n) = O(1)$
338 ///
339 /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
340 /// rounding must examine the bits that are discarded.
341 ///
342 /// # Examples
343 /// See [here](super::primitive_int_from_float#try_from).
344 #[inline]
345 fn try_from(f: Float) -> Result<$t, Self::Error> {
346 unsigned_try_from_float(f)
347 }
348 }
349
350 impl TryFrom<&Float> for $t {
351 type Error = UnsignedFromFloatError;
352
353 /// Converts a [`Float`] to a primitive unsigned integer, taking the [`Float`] by
354 /// reference. If the [`Float`] is not equal to an unsigned primitive integer of the
355 /// given type, an error is returned.
356 ///
357 /// Both positive and negative zero convert to a primitive unsigned integer zero.
358 ///
359 /// # Worst-case complexity
360 /// $T(n) = O(n)$
361 ///
362 /// $M(n) = O(1)$
363 ///
364 /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
365 /// rounding must examine the bits that are discarded.
366 ///
367 /// # Examples
368 /// See [here](super::primitive_int_from_float#try_from).
369 #[inline]
370 fn try_from(f: &Float) -> Result<$t, Self::Error> {
371 unsigned_try_from_float_ref(f)
372 }
373 }
374
375 impl ConvertibleFrom<&Float> for $t {
376 /// Determines whether a [`Float`] can be converted to an unsigned primitive integer,
377 /// taking the [`Float`] by reference.
378 ///
379 /// Both positive and negative zero are convertible to any unsigned primitive integer.
380 /// (Although negative zero is nominally negative, the real number it represents is
381 /// zero, which is not negative.)
382 ///
383 /// # Worst-case complexity
384 /// $T(n) = O(n)$
385 ///
386 /// $M(n) = O(1)$
387 ///
388 /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
389 /// rounding must examine the bits that are discarded.
390 ///
391 /// # Examples
392 /// See [here](super::primitive_int_from_float#convertible_from).
393 #[inline]
394 fn convertible_from(f: &Float) -> bool {
395 unsigned_convertible_from_float::<$t>(f)
396 }
397 }
398 };
399}
400apply_to_unsigneds!(impl_unsigned_from);
401
402#[allow(clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds)]
403fn signed_rounding_from_float<T: PrimitiveSigned>(f: Float, rm: RoundingMode) -> (T, Ordering)
404where
405 for<'a> T: TryFrom<&'a Natural> + TryFrom<&'a Integer>,
406{
407 match f {
408 float_nan!() => panic!("Can't convert NaN to {}", T::NAME),
409 float_infinity!() => match rm {
410 Floor | Down | Nearest => (T::MAX, Less),
411 _ => panic!("Can't convert Infinity to {} using {}", T::NAME, rm),
412 },
413 float_negative_infinity!() => match rm {
414 Ceiling | Down | Nearest => (T::MIN, Greater),
415 _ => panic!("Can't convert -Infinity to {} using {}", T::NAME, rm),
416 },
417 float_either_zero!() => (T::ZERO, Equal),
418 Float(Finite {
419 sign,
420 exponent,
421 significand,
422 ..
423 }) => {
424 let exponent = i64::from(exponent);
425 if sign {
426 if exponent < 0 {
427 match rm {
428 Floor | Down | Nearest => (T::ZERO, Less),
429 Ceiling | Up => (T::ONE, Greater),
430 Exact => {
431 panic!("Cannot convert Float to Integer using {rm}")
432 }
433 }
434 } else if exponent >= i64::wrapping_from(T::WIDTH) {
435 match rm {
436 Floor | Down | Nearest => (T::MAX, Less),
437 _ => {
438 panic!("Cannot convert Float to Integer using {rm}")
439 }
440 }
441 } else {
442 let sb = significand_bits(&significand);
443 let eb = exponent.unsigned_abs();
444 let (n, o) = if sb >= eb {
445 significand.shr_round(sb - eb, rm)
446 } else {
447 (significand << (eb - sb), Equal)
448 };
449 if let Ok(n) = T::try_from(&n) {
450 (n, o)
451 } else {
452 match rm {
453 Floor | Down | Nearest => (T::MAX, Less),
454 _ => {
455 panic!("Cannot convert large Float to {} using {}", T::NAME, rm)
456 }
457 }
458 }
459 }
460 } else if exponent < 0 {
461 match rm {
462 Ceiling | Down | Nearest => (T::ZERO, Greater),
463 Floor | Up => (T::NEGATIVE_ONE, Less),
464 Exact => {
465 panic!("Cannot convert Float to Integer using {rm}")
466 }
467 }
468 } else if exponent > i64::wrapping_from(T::WIDTH) {
469 // This doesn't catch the case where -2^(W+1) < x < -2^W, but that's ok because the
470 // next else block handles it.
471 match rm {
472 Ceiling | Down | Nearest => (T::MIN, Greater),
473 _ => {
474 panic!("Cannot convert Float to Integer using {rm}")
475 }
476 }
477 } else {
478 let sb = significand_bits(&significand);
479 let eb = exponent.unsigned_abs();
480 let (n, o) = if sb >= eb {
481 significand.shr_round(sb - eb, -rm)
482 } else {
483 (significand << (eb - sb), Equal)
484 };
485 if let Ok(n) = T::try_from(&-n) {
486 (n, o.reverse())
487 } else {
488 match rm {
489 Ceiling | Down | Nearest => (T::MIN, Greater),
490 _ => panic!(
491 "Cannot convert large negative Float to {} using {}",
492 T::NAME,
493 rm
494 ),
495 }
496 }
497 }
498 }
499 }
500}
501
502#[allow(clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds)]
503fn signed_rounding_from_float_ref<T: PrimitiveSigned>(f: &Float, rm: RoundingMode) -> (T, Ordering)
504where
505 for<'a> T: TryFrom<&'a Natural> + TryFrom<&'a Integer>,
506{
507 match f {
508 float_nan!() => panic!("Can't convert NaN to {}", T::NAME),
509 float_infinity!() => match rm {
510 Floor | Down | Nearest => (T::MAX, Less),
511 _ => panic!("Can't convert Infinity to {} using {}", T::NAME, rm),
512 },
513 float_negative_infinity!() => match rm {
514 Ceiling | Down | Nearest => (T::MIN, Greater),
515 _ => panic!("Can't convert -Infinity to {} using {}", T::NAME, rm),
516 },
517 float_either_zero!() => (T::ZERO, Equal),
518 Float(Finite {
519 sign,
520 exponent,
521 significand,
522 ..
523 }) => {
524 let exponent = i64::from(*exponent);
525 if *sign {
526 if exponent < 0 {
527 match rm {
528 Floor | Down | Nearest => (T::ZERO, Less),
529 Ceiling | Up => (T::ONE, Greater),
530 Exact => {
531 panic!("Cannot convert Float to Integer using {rm}")
532 }
533 }
534 } else if exponent >= i64::wrapping_from(T::WIDTH) {
535 match rm {
536 Floor | Down | Nearest => (T::MAX, Less),
537 _ => {
538 panic!("Cannot convert Float to Integer using {rm}")
539 }
540 }
541 } else {
542 let sb = significand_bits(significand);
543 let eb = exponent.unsigned_abs();
544 let (n, o) = if sb >= eb {
545 significand.shr_round(sb - eb, rm)
546 } else {
547 (significand << (eb - sb), Equal)
548 };
549 if let Ok(n) = T::try_from(&n) {
550 (n, o)
551 } else {
552 match rm {
553 Floor | Down | Nearest => (T::MAX, Less),
554 _ => {
555 panic!("Cannot convert large Float to {} using {}", T::NAME, rm)
556 }
557 }
558 }
559 }
560 } else if exponent < 0 {
561 match rm {
562 Ceiling | Down | Nearest => (T::ZERO, Greater),
563 Floor | Up => (T::NEGATIVE_ONE, Less),
564 Exact => {
565 panic!("Cannot convert Float to Integer using {rm}")
566 }
567 }
568 } else if exponent > i64::wrapping_from(T::WIDTH) {
569 // This doesn't catch the case where -2^(W+1) < x < -2^W, but that's ok because the
570 // next else block handles it.
571 match rm {
572 Ceiling | Down | Nearest => (T::MIN, Greater),
573 _ => {
574 panic!("Cannot convert Float to Integer using {rm}")
575 }
576 }
577 } else {
578 let sb = significand_bits(significand);
579 let eb = exponent.unsigned_abs();
580 let (n, o) = if sb >= eb {
581 significand.shr_round(sb - eb, -rm)
582 } else {
583 (significand << (eb - sb), Equal)
584 };
585 if let Ok(n) = T::try_from(&-n) {
586 (n, o.reverse())
587 } else {
588 match rm {
589 Ceiling | Down | Nearest => (T::MIN, Greater),
590 _ => panic!(
591 "Cannot convert large negative Float to {} using {}",
592 T::NAME,
593 rm
594 ),
595 }
596 }
597 }
598 }
599 }
600}
601
602#[allow(clippy::type_repetition_in_bounds)]
603fn signed_try_from_float<T: PrimitiveSigned>(f: Float) -> Result<T, SignedFromFloatError>
604where
605 for<'a> T: TryFrom<&'a Integer>,
606{
607 match f {
608 float_either_zero!() => Ok(T::ZERO),
609 Float(Finite {
610 sign,
611 exponent,
612 significand,
613 ..
614 }) => {
615 let exponent = i64::from(exponent);
616 if exponent <= 0
617 || (sign && exponent >= i64::wrapping_from(T::WIDTH)
618 || !sign && exponent > i64::wrapping_from(T::WIDTH))
619 {
620 Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange)
621 } else {
622 let sb = significand_bits(&significand);
623 let eb = exponent.unsigned_abs();
624 let i = Integer::from_sign_and_abs(
625 sign,
626 if sb >= eb {
627 let bits = sb - eb;
628 if significand.divisible_by_power_of_2(bits) {
629 significand >> bits
630 } else {
631 return Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange);
632 }
633 } else {
634 significand << (eb - sb)
635 },
636 );
637 T::try_from(&i).map_err(|_| SignedFromFloatError::FloatNonIntegerOrOutOfRange)
638 }
639 }
640 _ => Err(SignedFromFloatError::FloatInfiniteOrNan),
641 }
642}
643
644#[allow(clippy::type_repetition_in_bounds)]
645fn signed_try_from_float_ref<T: PrimitiveSigned>(f: &Float) -> Result<T, SignedFromFloatError>
646where
647 for<'a> T: TryFrom<&'a Integer>,
648{
649 match f {
650 float_either_zero!() => Ok(T::ZERO),
651 Float(Finite {
652 sign,
653 exponent,
654 significand,
655 ..
656 }) => {
657 let exponent = i64::from(*exponent);
658 if exponent <= 0
659 || (*sign && exponent >= i64::wrapping_from(T::WIDTH)
660 || !*sign && exponent > i64::wrapping_from(T::WIDTH))
661 {
662 Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange)
663 } else {
664 let sb = significand_bits(significand);
665 let eb = exponent.unsigned_abs();
666 let i = Integer::from_sign_and_abs(
667 *sign,
668 if sb >= eb {
669 let bits = sb - eb;
670 if significand.divisible_by_power_of_2(bits) {
671 significand >> bits
672 } else {
673 return Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange);
674 }
675 } else {
676 significand << (eb - sb)
677 },
678 );
679 T::try_from(&i).map_err(|_| SignedFromFloatError::FloatNonIntegerOrOutOfRange)
680 }
681 }
682 _ => Err(SignedFromFloatError::FloatInfiniteOrNan),
683 }
684}
685
686fn signed_convertible_from_float<T: PrimitiveSigned>(f: &Float) -> bool {
687 match f {
688 float_either_zero!() => true,
689 Float(Finite {
690 exponent,
691 significand,
692 ..
693 }) => {
694 let exponent = i64::from(*exponent);
695 if exponent <= 0 {
696 return false;
697 }
698 if exponent >= i64::wrapping_from(T::WIDTH) {
699 float_is_signed_min::<T>(f)
700 } else {
701 let sb = significand_bits(significand);
702 let eb = exponent.unsigned_abs();
703 sb < eb || significand.divisible_by_power_of_2(sb - eb)
704 }
705 }
706 _ => false,
707 }
708}
709
710macro_rules! impl_signed_from {
711 ($t: ident) => {
712 impl RoundingFrom<Float> for $t {
713 /// Converts a [`Float`] to a signed primitive integer, using a specified
714 /// [`RoundingMode`] and taking the [`Float`] by value. An [`Ordering`] is also
715 /// returned, indicating whether the returned value is less than, equal to, or greater
716 /// than the original value.
717 ///
718 /// If the [`Float`] is less than the minimum representable value of the signed type
719 /// (including $-\infty$), then it will be rounded to zero when the [`RoundingMode`] is
720 /// `Ceiling`, `Down`, or `Nearest`. Otherwise, this function will panic.
721 ///
722 /// If the [`Float`] is greater than the maximum representable value of the signed type
723 /// (including $\infty$), then it will be rounded to the maximum value when the
724 /// [`RoundingMode`] is `Floor`, `Down`, or `Nearest`. Otherwise, this function will
725 /// panic.
726 ///
727 /// If the [`Float`] is NaN, the function will panic regardless of the rounding mode.
728 ///
729 /// # Worst-case complexity
730 /// $T(n) = O(n)$
731 ///
732 /// $M(n) = O(1)$
733 ///
734 /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
735 /// rounding must examine the bits that are discarded.
736 ///
737 /// # Panics
738 /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`]
739 /// is smaller than the minimum representable value of the signed type and `rm` is not
740 /// `Down`, `Ceiling`, or `Nearest`, if the [`Float`] is greater than the maximum
741 /// representable value of the signed type and `rm` is not `Down`, `Floor`, or
742 /// `Nearest`, or if the [`Float`] is NaN.
743 ///
744 /// # Examples
745 /// See [here](super::primitive_int_from_float#rounding_from).
746 #[inline]
747 fn rounding_from(f: Float, rm: RoundingMode) -> ($t, Ordering) {
748 signed_rounding_from_float(f, rm)
749 }
750 }
751
752 impl RoundingFrom<&Float> for $t {
753 /// Converts a [`Float`] to a signed primitive integer, using a specified
754 /// [`RoundingMode`] and taking the [`Float`] by reference. An [`Ordering`] is also
755 /// returned, indicating whether the returned value is less than, equal to, or greater
756 /// than the original value.
757 ///
758 /// If the [`Float`] is less than the minimum representable value of the signed type
759 /// (including $-\infty$), then it will be rounded to zero when the [`RoundingMode`] is
760 /// `Ceiling`, `Down`, or `Nearest`. Otherwise, this function will panic.
761 ///
762 /// If the [`Float`] is greater than the maximum representable value of the signed type
763 /// (including $\infty$), then it will be rounded to the maximum value when the
764 /// [`RoundingMode`] is `Floor`, `Down`, or `Nearest`. Otherwise, this function will
765 /// panic.
766 ///
767 /// If the [`Float`] is NaN, the function will panic regardless of the rounding mode.
768 ///
769 /// # Worst-case complexity
770 /// $T(n) = O(n)$
771 ///
772 /// $M(n) = O(1)$
773 ///
774 /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
775 /// rounding must examine the bits that are discarded.
776 ///
777 /// # Panics
778 /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`]
779 /// is smaller than the minimum representable value of the signed type and `rm` is not
780 /// `Down`, `Ceiling`, or `Nearest`, if the [`Float`] is greater than the maximum
781 /// representable value of the signed type and `rm` is not `Down`, `Floor`, or
782 /// `Nearest`, or if the [`Float`] is NaN.
783 ///
784 /// # Examples
785 /// See [here](super::primitive_int_from_float#rounding_from).
786 #[inline]
787 fn rounding_from(f: &Float, rm: RoundingMode) -> ($t, Ordering) {
788 signed_rounding_from_float_ref(f, rm)
789 }
790 }
791
792 impl TryFrom<Float> for $t {
793 type Error = SignedFromFloatError;
794
795 /// Converts a [`Float`] to a primitive signed integer, taking the [`Float`] by value.
796 /// If the [`Float`] is not equal to a signed primitive integer of the given type, an
797 /// error is returned.
798 ///
799 /// # Worst-case complexity
800 /// $T(n) = O(n)$
801 ///
802 /// $M(n) = O(1)$
803 ///
804 /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
805 /// rounding must examine the bits that are discarded.
806 ///
807 /// # Examples
808 /// See [here](super::primitive_int_from_float#try_from).
809 #[inline]
810 fn try_from(f: Float) -> Result<$t, Self::Error> {
811 signed_try_from_float(f)
812 }
813 }
814
815 impl TryFrom<&Float> for $t {
816 type Error = SignedFromFloatError;
817
818 /// Converts a [`Float`] to a primitive signed integer, taking the [`Float`] by
819 /// reference. If the [`Float`] is not equal to a signed primitive integer of the given
820 /// type, an error is returned.
821 ///
822 /// # Worst-case complexity
823 /// $T(n) = O(n)$
824 ///
825 /// $M(n) = O(1)$
826 ///
827 /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
828 /// rounding must examine the bits that are discarded.
829 ///
830 /// # Examples
831 /// See [here](super::primitive_int_from_float#try_from).
832 #[inline]
833 fn try_from(f: &Float) -> Result<$t, Self::Error> {
834 signed_try_from_float_ref(f)
835 }
836 }
837
838 impl ConvertibleFrom<&Float> for $t {
839 /// Determines whether a [`Float`] can be converted to a signed primitive integer,
840 /// taking the [`Float`] by reference.
841 ///
842 /// # Worst-case complexity
843 /// $T(n) = O(n)$
844 ///
845 /// $M(n) = O(1)$
846 ///
847 /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
848 /// rounding must examine the bits that are discarded.
849 ///
850 /// # Examples
851 /// See [here](super::primitive_int_from_float#convertible_from).
852 #[inline]
853 fn convertible_from(f: &Float) -> bool {
854 signed_convertible_from_float::<$t>(f)
855 }
856 }
857 };
858}
859apply_to_signeds!(impl_signed_from);