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