1#![allow(clippy::unneeded_field_pattern)]
5#![allow(clippy::too_many_arguments)]
6#![deny(missing_docs)]
7
8use algebraics::prelude::*;
11use bitflags::bitflags;
12use num_bigint::BigInt;
13use num_bigint::BigUint;
14use num_integer::Integer;
15use num_rational::Ratio;
16use num_traits::FromPrimitive;
17use num_traits::NumAssign;
18use num_traits::NumAssignRef;
19use num_traits::NumRef;
20use num_traits::ToPrimitive;
21use num_traits::Unsigned;
22use std::cmp::Ordering;
23use std::error::Error;
24use std::fmt;
25use std::ops::Add;
26use std::ops::AddAssign;
27use std::ops::BitAnd;
28use std::ops::BitAndAssign;
29use std::ops::BitOr;
30use std::ops::BitOrAssign;
31use std::ops::BitXor;
32use std::ops::BitXorAssign;
33use std::ops::Deref;
34use std::ops::DerefMut;
35use std::ops::Div;
36use std::ops::DivAssign;
37use std::ops::Mul;
38use std::ops::MulAssign;
39use std::ops::Neg;
40use std::ops::Shl;
41use std::ops::ShlAssign;
42use std::ops::Shr;
43use std::ops::ShrAssign;
44use std::ops::Sub;
45use std::ops::SubAssign;
46
47#[cfg(feature = "python")]
48use crate::python::PyPlatformProperties;
49#[cfg(feature = "python")]
50use crate::python::ToPythonRepr;
51#[cfg(feature = "python")]
52use pyo3::prelude::*;
53#[cfg(feature = "python")]
54use std::borrow::Cow;
55
56#[macro_use]
57mod python_macros;
58mod python;
59
60#[cfg(test)]
61mod test_cases;
62
63python_enum! {
64 #[pyenum(module = simple_soft_float, repr = u8, test_fn = test_sign_enum)]
65 pub enum Sign {
67 Positive = 0,
69 Negative = 1,
71 }
72}
73
74impl Neg for Sign {
75 type Output = Self;
76 fn neg(self) -> Self {
77 match self {
78 Self::Positive => Self::Negative,
79 Self::Negative => Self::Positive,
80 }
81 }
82}
83
84impl Mul for Sign {
85 type Output = Self;
86 fn mul(self, rhs: Self) -> Self {
87 match self {
88 Self::Positive => rhs,
89 Self::Negative => -rhs,
90 }
91 }
92}
93
94impl MulAssign for Sign {
95 fn mul_assign(&mut self, rhs: Self) {
96 *self = *self * rhs;
97 }
98}
99
100pub trait FloatBitsType:
102 Unsigned
103 + Integer
104 + Clone
105 + NumAssign
106 + NumAssignRef
107 + NumRef
108 + Shl<usize, Output = Self>
109 + Shr<usize, Output = Self>
110 + ShlAssign<usize>
111 + ShrAssign<usize>
112 + BitAnd<Self, Output = Self>
113 + BitOr<Self, Output = Self>
114 + BitXor<Self, Output = Self>
115 + for<'a> BitAnd<&'a Self, Output = Self>
116 + for<'a> BitOr<&'a Self, Output = Self>
117 + for<'a> BitXor<&'a Self, Output = Self>
118 + BitAndAssign<Self>
119 + BitOrAssign<Self>
120 + BitXorAssign<Self>
121 + for<'a> BitAndAssign<&'a Self>
122 + for<'a> BitOrAssign<&'a Self>
123 + for<'a> BitXorAssign<&'a Self>
124 + fmt::UpperHex
125 + fmt::LowerHex
126 + fmt::Octal
127 + fmt::Binary
128 + fmt::Display
129 + FromPrimitive
130 + ToPrimitive
131 + Into<BigInt>
132 + From<u8>
133{
134 fn from_bigint(v: &BigInt) -> Option<Self>;
137}
138
139macro_rules! impl_float_bits_type {
140 ($t:ty, $cvt_from_bigint:ident) => {
141 impl FloatBitsType for $t {
142 fn from_bigint(v: &BigInt) -> Option<Self> {
143 v.$cvt_from_bigint()
144 }
145 }
146 };
147}
148
149impl_float_bits_type!(BigUint, to_biguint);
150impl_float_bits_type!(u8, to_u8);
151impl_float_bits_type!(u16, to_u16);
152impl_float_bits_type!(u32, to_u32);
153impl_float_bits_type!(u64, to_u64);
154impl_float_bits_type!(u128, to_u128);
155
156python_enum! {
157 #[pyenum(module = simple_soft_float, repr = u8, test_fn = test_rounding_mode_enum)]
158 pub enum RoundingMode {
160 TiesToEven = 0,
162 TowardZero = 1,
164 TowardNegative = 2,
166 TowardPositive = 3,
168 TiesToAway = 4,
170 }
171}
172
173impl Default for RoundingMode {
174 fn default() -> Self {
175 RoundingMode::TiesToEven
176 }
177}
178
179bitflags! {
180 pub struct StatusFlags: u32 {
182 const INVALID_OPERATION = 0b00001;
184 const DIVISION_BY_ZERO = 0b00010;
187 const OVERFLOW = 0b00100;
191 const UNDERFLOW = 0b01000;
193 const INEXACT = 0b10000;
195 }
196}
197
198impl Default for StatusFlags {
199 fn default() -> Self {
200 StatusFlags::empty()
201 }
202}
203
204python_enum! {
205 #[pyenum(module = simple_soft_float, repr = u8, test_fn = test_exception_handling_mode_enum)]
206 pub enum ExceptionHandlingMode {
222 IgnoreExactUnderflow,
224 SignalExactUnderflow,
226 }
227}
228
229impl Default for ExceptionHandlingMode {
230 fn default() -> ExceptionHandlingMode {
231 ExceptionHandlingMode::IgnoreExactUnderflow
232 }
233}
234
235python_enum! {
236 #[pyenum(module = simple_soft_float, repr = u8, test_fn = test_tininess_detection_mode_enum)]
237 pub enum TininessDetectionMode {
239 AfterRounding,
241 BeforeRounding,
243 }
244}
245
246impl Default for TininessDetectionMode {
247 fn default() -> TininessDetectionMode {
248 TininessDetectionMode::AfterRounding
249 }
250}
251
252python_enum! {
253 #[pyenum(module = simple_soft_float, repr = u8, test_fn = test_binary_nan_propagation_mode_enum)]
254 pub enum BinaryNaNPropagationMode {
256 AlwaysCanonical,
258 FirstSecond,
262 SecondFirst,
266 FirstSecondPreferringSNaN,
272 SecondFirstPreferringSNaN,
278 }
279}
280
281python_enum! {
282 #[pyenum(module = simple_soft_float, repr = u8, test_fn = test_unary_nan_propagation_mode_enum)]
283 pub enum UnaryNaNPropagationMode {
285 AlwaysCanonical,
287 First,
290 }
291}
292
293#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
295pub enum BinaryNaNPropagationResults {
296 Canonical,
298 First,
300 Second,
302}
303
304impl Default for BinaryNaNPropagationResults {
305 fn default() -> Self {
306 Self::Canonical
307 }
308}
309
310impl BinaryNaNPropagationMode {
311 pub fn calculate_propagation_results(
313 self,
314 first_class: FloatClass,
315 second_class: FloatClass,
316 ) -> BinaryNaNPropagationResults {
317 use BinaryNaNPropagationMode::*;
318 use BinaryNaNPropagationResults::*;
319 match self {
320 AlwaysCanonical => Canonical,
321 FirstSecond => {
322 if first_class.is_nan() {
323 First
324 } else if second_class.is_nan() {
325 Second
326 } else {
327 Canonical
328 }
329 }
330 SecondFirst => {
331 if second_class.is_nan() {
332 Second
333 } else if first_class.is_nan() {
334 First
335 } else {
336 Canonical
337 }
338 }
339 FirstSecondPreferringSNaN => {
340 if first_class.is_signaling_nan() {
341 First
342 } else if second_class.is_signaling_nan() {
343 Second
344 } else if first_class.is_nan() {
345 First
346 } else if second_class.is_nan() {
347 Second
348 } else {
349 Canonical
350 }
351 }
352 SecondFirstPreferringSNaN => {
353 if second_class.is_signaling_nan() {
354 Second
355 } else if first_class.is_signaling_nan() {
356 First
357 } else if second_class.is_nan() {
358 Second
359 } else if first_class.is_nan() {
360 First
361 } else {
362 Canonical
363 }
364 }
365 }
366 }
367}
368
369#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
371pub enum UnaryNaNPropagationResults {
372 Canonical,
374 First,
376}
377
378impl Default for UnaryNaNPropagationResults {
379 fn default() -> Self {
380 Self::Canonical
381 }
382}
383
384impl UnaryNaNPropagationMode {
385 pub fn calculate_propagation_results(
387 self,
388 first_class: FloatClass,
389 ) -> UnaryNaNPropagationResults {
390 match self {
391 UnaryNaNPropagationMode::AlwaysCanonical => UnaryNaNPropagationResults::Canonical,
392 UnaryNaNPropagationMode::First => {
393 if first_class.is_nan() {
394 UnaryNaNPropagationResults::First
395 } else {
396 UnaryNaNPropagationResults::Canonical
397 }
398 }
399 }
400 }
401}
402
403impl From<TernaryNaNPropagationMode> for BinaryNaNPropagationMode {
404 fn from(v: TernaryNaNPropagationMode) -> Self {
405 use BinaryNaNPropagationMode::*;
406 use TernaryNaNPropagationMode::*;
407 match v {
408 TernaryNaNPropagationMode::AlwaysCanonical => BinaryNaNPropagationMode::AlwaysCanonical,
409 FirstSecondThird | FirstThirdSecond | ThirdFirstSecond => FirstSecond,
410 SecondFirstThird | SecondThirdFirst | ThirdSecondFirst => SecondFirst,
411 FirstSecondThirdPreferringSNaN
412 | FirstThirdSecondPreferringSNaN
413 | ThirdFirstSecondPreferringSNaN => FirstSecondPreferringSNaN,
414 SecondFirstThirdPreferringSNaN
415 | SecondThirdFirstPreferringSNaN
416 | ThirdSecondFirstPreferringSNaN => SecondFirstPreferringSNaN,
417 }
418 }
419}
420
421impl From<BinaryNaNPropagationMode> for UnaryNaNPropagationMode {
422 fn from(v: BinaryNaNPropagationMode) -> Self {
423 use BinaryNaNPropagationMode::*;
424 use UnaryNaNPropagationMode::*;
425 match v {
426 BinaryNaNPropagationMode::AlwaysCanonical => UnaryNaNPropagationMode::AlwaysCanonical,
427 FirstSecond | SecondFirst | FirstSecondPreferringSNaN | SecondFirstPreferringSNaN => {
428 First
429 }
430 }
431 }
432}
433
434#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
436pub enum TernaryNaNPropagationResults {
437 Canonical,
439 First,
441 Second,
443 Third,
445}
446
447impl Default for TernaryNaNPropagationResults {
448 fn default() -> Self {
449 Self::Canonical
450 }
451}
452
453python_enum! {
454 #[pyenum(module = simple_soft_float, repr = u8, test_fn = test_ternary_nan_propagation_mode_enum)]
455 pub enum TernaryNaNPropagationMode {
457 AlwaysCanonical,
459 FirstSecondThird,
464 FirstThirdSecond,
469 SecondFirstThird,
474 SecondThirdFirst,
479 ThirdFirstSecond,
484 ThirdSecondFirst,
489 FirstSecondThirdPreferringSNaN,
497 FirstThirdSecondPreferringSNaN,
505 SecondFirstThirdPreferringSNaN,
513 SecondThirdFirstPreferringSNaN,
521 ThirdFirstSecondPreferringSNaN,
529 ThirdSecondFirstPreferringSNaN,
537 }
538}
539
540impl Default for TernaryNaNPropagationMode {
541 fn default() -> TernaryNaNPropagationMode {
542 TernaryNaNPropagationMode::AlwaysCanonical
543 }
544}
545
546impl TernaryNaNPropagationMode {
547 pub fn calculate_propagation_results(
549 self,
550 first_class: FloatClass,
551 second_class: FloatClass,
552 third_class: FloatClass,
553 ) -> TernaryNaNPropagationResults {
554 #![allow(clippy::cognitive_complexity)]
555 use TernaryNaNPropagationMode::*;
556 use TernaryNaNPropagationResults::*;
557 match self {
558 AlwaysCanonical => Canonical,
559 FirstSecondThird => {
560 if first_class.is_nan() {
561 First
562 } else if second_class.is_nan() {
563 Second
564 } else if third_class.is_nan() {
565 Third
566 } else {
567 Canonical
568 }
569 }
570 FirstSecondThirdPreferringSNaN => {
571 if first_class.is_signaling_nan() {
572 First
573 } else if second_class.is_signaling_nan() {
574 Second
575 } else if third_class.is_signaling_nan() {
576 Third
577 } else if first_class.is_nan() {
578 First
579 } else if second_class.is_nan() {
580 Second
581 } else if third_class.is_nan() {
582 Third
583 } else {
584 Canonical
585 }
586 }
587 FirstThirdSecond => {
588 if first_class.is_nan() {
589 First
590 } else if third_class.is_nan() {
591 Third
592 } else if second_class.is_nan() {
593 Second
594 } else {
595 Canonical
596 }
597 }
598 FirstThirdSecondPreferringSNaN => {
599 if first_class.is_signaling_nan() {
600 First
601 } else if third_class.is_signaling_nan() {
602 Third
603 } else if second_class.is_signaling_nan() {
604 Second
605 } else if first_class.is_nan() {
606 First
607 } else if third_class.is_nan() {
608 Third
609 } else if second_class.is_nan() {
610 Second
611 } else {
612 Canonical
613 }
614 }
615 SecondFirstThird => {
616 if second_class.is_nan() {
617 Second
618 } else if first_class.is_nan() {
619 First
620 } else if third_class.is_nan() {
621 Third
622 } else {
623 Canonical
624 }
625 }
626 SecondFirstThirdPreferringSNaN => {
627 if second_class.is_signaling_nan() {
628 Second
629 } else if first_class.is_signaling_nan() {
630 First
631 } else if third_class.is_signaling_nan() {
632 Third
633 } else if second_class.is_nan() {
634 Second
635 } else if first_class.is_nan() {
636 First
637 } else if third_class.is_nan() {
638 Third
639 } else {
640 Canonical
641 }
642 }
643 SecondThirdFirst => {
644 if second_class.is_nan() {
645 Second
646 } else if third_class.is_nan() {
647 Third
648 } else if first_class.is_nan() {
649 First
650 } else {
651 Canonical
652 }
653 }
654 SecondThirdFirstPreferringSNaN => {
655 if second_class.is_signaling_nan() {
656 Second
657 } else if third_class.is_signaling_nan() {
658 Third
659 } else if first_class.is_signaling_nan() {
660 First
661 } else if second_class.is_nan() {
662 Second
663 } else if third_class.is_nan() {
664 Third
665 } else if first_class.is_nan() {
666 First
667 } else {
668 Canonical
669 }
670 }
671 ThirdFirstSecond => {
672 if third_class.is_nan() {
673 Third
674 } else if first_class.is_nan() {
675 First
676 } else if second_class.is_nan() {
677 Second
678 } else {
679 Canonical
680 }
681 }
682 ThirdFirstSecondPreferringSNaN => {
683 if third_class.is_signaling_nan() {
684 Third
685 } else if first_class.is_signaling_nan() {
686 First
687 } else if second_class.is_signaling_nan() {
688 Second
689 } else if third_class.is_nan() {
690 Third
691 } else if first_class.is_nan() {
692 First
693 } else if second_class.is_nan() {
694 Second
695 } else {
696 Canonical
697 }
698 }
699 ThirdSecondFirst => {
700 if third_class.is_nan() {
701 Third
702 } else if second_class.is_nan() {
703 Second
704 } else if first_class.is_nan() {
705 First
706 } else {
707 Canonical
708 }
709 }
710 ThirdSecondFirstPreferringSNaN => {
711 if third_class.is_signaling_nan() {
712 Third
713 } else if second_class.is_signaling_nan() {
714 Second
715 } else if first_class.is_signaling_nan() {
716 First
717 } else if third_class.is_nan() {
718 Third
719 } else if second_class.is_nan() {
720 Second
721 } else if first_class.is_nan() {
722 First
723 } else {
724 Canonical
725 }
726 }
727 }
728 }
729}
730
731python_enum! {
732 #[pyenum(module = simple_soft_float, repr = u8, test_fn = test_fma_inf_zero_qnan_result_enum)]
733 pub enum FMAInfZeroQNaNResult {
735 FollowNaNPropagationMode,
737 CanonicalAndGenerateInvalid,
739 PropagateAndGenerateInvalid,
741 }
742}
743
744impl Default for FMAInfZeroQNaNResult {
745 fn default() -> FMAInfZeroQNaNResult {
746 FMAInfZeroQNaNResult::FollowNaNPropagationMode
747 }
748}
749
750python_enum! {
751 #[pyenum(module = simple_soft_float, repr = u8, test_fn = test_float_to_float_conversion_nan_propagation_mode_enum)]
752 pub enum FloatToFloatConversionNaNPropagationMode {
754 AlwaysCanonical,
756 RetainMostSignificantBits,
759 }
760}
761
762#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
764pub struct FPState {
765 pub rounding_mode: RoundingMode,
767 pub status_flags: StatusFlags,
769 pub exception_handling_mode: ExceptionHandlingMode,
771 pub tininess_detection_mode: TininessDetectionMode,
773 _non_exhaustive: (),
775}
776
777#[derive(Clone, Debug, Default)]
779pub struct FPStateMergeFailed;
780
781impl fmt::Display for FPStateMergeFailed {
782 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
783 f.write_str("FPState::merge failed: incompatible states")
784 }
785}
786
787impl Error for FPStateMergeFailed {}
788
789#[cfg(feature = "python")]
790impl From<FPStateMergeFailed> for PyErr {
791 fn from(value: FPStateMergeFailed) -> PyErr {
792 PyErr::new::<pyo3::exceptions::TypeError, _>(format!("{}", value))
793 }
794}
795
796impl FPState {
797 pub fn checked_merge_assign(&mut self, rhs: Self) -> Result<(), FPStateMergeFailed> {
799 let status_flags = self.status_flags | rhs.status_flags;
800 let same = Self {
801 status_flags,
802 ..*self
803 } == Self {
804 status_flags,
805 ..rhs
806 };
807 if same {
808 self.status_flags = status_flags;
809 Ok(())
810 } else {
811 Err(FPStateMergeFailed)
812 }
813 }
814 pub fn merge_assign(&mut self, rhs: Self) {
816 self.checked_merge_assign(rhs).unwrap();
817 }
818 pub fn checked_merge(mut self, rhs: Self) -> Result<Self, FPStateMergeFailed> {
820 self.checked_merge_assign(rhs)?;
821 Ok(self)
822 }
823 pub fn merge(mut self, rhs: Self) -> Self {
825 self.merge_assign(rhs);
826 self
827 }
828}
829
830python_enum! {
831 #[pyenum(module = simple_soft_float, repr = u8, test_fn = test_float_class_enum)]
832 pub enum FloatClass {
834 NegativeInfinity,
836 NegativeNormal,
838 NegativeSubnormal,
840 NegativeZero,
842 PositiveInfinity,
844 PositiveNormal,
846 PositiveSubnormal,
848 PositiveZero,
850 QuietNaN,
852 SignalingNaN,
854 }
855}
856
857impl FloatClass {
858 #[inline]
860 pub fn sign(self) -> Option<Sign> {
861 match self {
862 FloatClass::NegativeInfinity
863 | FloatClass::NegativeNormal
864 | FloatClass::NegativeSubnormal
865 | FloatClass::NegativeZero => Some(Sign::Negative),
866 FloatClass::PositiveInfinity
867 | FloatClass::PositiveNormal
868 | FloatClass::PositiveSubnormal
869 | FloatClass::PositiveZero => Some(Sign::Positive),
870 FloatClass::QuietNaN | FloatClass::SignalingNaN => None,
871 }
872 }
873 #[inline]
875 pub fn abs(self) -> Self {
876 match self {
877 FloatClass::NegativeInfinity => FloatClass::PositiveInfinity,
878 FloatClass::NegativeNormal => FloatClass::PositiveNormal,
879 FloatClass::NegativeSubnormal => FloatClass::PositiveSubnormal,
880 FloatClass::NegativeZero => FloatClass::PositiveZero,
881 FloatClass::PositiveInfinity => FloatClass::PositiveInfinity,
882 FloatClass::PositiveNormal => FloatClass::PositiveNormal,
883 FloatClass::PositiveSubnormal => FloatClass::PositiveSubnormal,
884 FloatClass::PositiveZero => FloatClass::PositiveZero,
885 FloatClass::QuietNaN => FloatClass::QuietNaN,
886 FloatClass::SignalingNaN => FloatClass::SignalingNaN,
887 }
888 }
889 #[inline]
891 pub fn is_negative_infinity(self) -> bool {
892 self == FloatClass::NegativeInfinity
893 }
894 #[inline]
896 pub fn is_negative_normal(self) -> bool {
897 self == FloatClass::NegativeNormal
898 }
899 #[inline]
901 pub fn is_negative_subnormal(self) -> bool {
902 self == FloatClass::NegativeSubnormal
903 }
904 #[inline]
906 pub fn is_negative_zero(self) -> bool {
907 self == FloatClass::NegativeZero
908 }
909 #[inline]
911 pub fn is_positive_infinity(self) -> bool {
912 self == FloatClass::PositiveInfinity
913 }
914 #[inline]
916 pub fn is_positive_normal(self) -> bool {
917 self == FloatClass::PositiveNormal
918 }
919 #[inline]
921 pub fn is_positive_subnormal(self) -> bool {
922 self == FloatClass::PositiveSubnormal
923 }
924 #[inline]
926 pub fn is_positive_zero(self) -> bool {
927 self == FloatClass::PositiveZero
928 }
929 #[inline]
931 pub fn is_quiet_nan(self) -> bool {
932 self == FloatClass::QuietNaN
933 }
934 #[inline]
936 pub fn is_signaling_nan(self) -> bool {
937 self == FloatClass::SignalingNaN
938 }
939 #[inline]
941 pub fn is_infinity(self) -> bool {
942 self == FloatClass::NegativeInfinity || self == FloatClass::PositiveInfinity
943 }
944 #[inline]
946 pub fn is_normal(self) -> bool {
947 self == FloatClass::NegativeNormal || self == FloatClass::PositiveNormal
948 }
949 #[inline]
951 pub fn is_subnormal(self) -> bool {
952 self == FloatClass::NegativeSubnormal || self == FloatClass::PositiveSubnormal
953 }
954 #[inline]
956 pub fn is_zero(self) -> bool {
957 self == FloatClass::NegativeZero || self == FloatClass::PositiveZero
958 }
959 #[inline]
961 pub fn is_nan(self) -> bool {
962 self == FloatClass::QuietNaN || self == FloatClass::SignalingNaN
963 }
964 #[inline]
966 pub fn is_finite(self) -> bool {
967 match self {
968 FloatClass::NegativeZero
969 | FloatClass::NegativeSubnormal
970 | FloatClass::NegativeNormal
971 | FloatClass::PositiveZero
972 | FloatClass::PositiveSubnormal
973 | FloatClass::PositiveNormal => true,
974 _ => false,
975 }
976 }
977 #[inline]
979 pub fn is_subnormal_or_zero(self) -> bool {
980 match self {
981 FloatClass::NegativeZero
982 | FloatClass::NegativeSubnormal
983 | FloatClass::PositiveZero
984 | FloatClass::PositiveSubnormal => true,
985 _ => false,
986 }
987 }
988}
989
990impl Neg for FloatClass {
991 type Output = Self;
992 fn neg(self) -> Self {
993 use FloatClass::*;
994 match self {
995 NegativeInfinity => PositiveInfinity,
996 NegativeNormal => PositiveNormal,
997 NegativeSubnormal => PositiveSubnormal,
998 NegativeZero => PositiveZero,
999 PositiveInfinity => NegativeInfinity,
1000 PositiveNormal => NegativeNormal,
1001 PositiveSubnormal => NegativeSubnormal,
1002 PositiveZero => NegativeZero,
1003 QuietNaN => QuietNaN,
1004 SignalingNaN => SignalingNaN,
1005 }
1006 }
1007}
1008
1009python_enum! {
1010 #[pyenum(module = simple_soft_float, repr = u8, test_fn = test_quiet_nan_format_enum)]
1011 pub enum QuietNaNFormat {
1018 Standard,
1020 MIPSLegacy,
1022 }
1023}
1024
1025impl QuietNaNFormat {
1026 pub fn is_nan_quiet(self, mantissa_msb_set: bool) -> bool {
1028 match self {
1029 QuietNaNFormat::Standard => mantissa_msb_set,
1030 QuietNaNFormat::MIPSLegacy => !mantissa_msb_set,
1031 }
1032 }
1033}
1034
1035impl Default for QuietNaNFormat {
1036 fn default() -> QuietNaNFormat {
1037 QuietNaNFormat::Standard
1038 }
1039}
1040
1041#[derive(Copy, Clone, Eq, PartialEq, Hash)]
1043pub struct PlatformProperties {
1044 pub canonical_nan_sign: Sign,
1046 pub canonical_nan_mantissa_msb: bool,
1048 pub canonical_nan_mantissa_second_to_msb: bool,
1050 pub canonical_nan_mantissa_rest: bool,
1052 pub std_bin_ops_nan_propagation_mode: BinaryNaNPropagationMode,
1054 pub fma_nan_propagation_mode: TernaryNaNPropagationMode,
1056 pub fma_inf_zero_qnan_result: FMAInfZeroQNaNResult,
1059 pub round_to_integral_nan_propagation_mode: UnaryNaNPropagationMode,
1061 pub next_up_or_down_nan_propagation_mode: UnaryNaNPropagationMode,
1063 pub scale_b_nan_propagation_mode: UnaryNaNPropagationMode,
1065 pub sqrt_nan_propagation_mode: UnaryNaNPropagationMode,
1067 pub float_to_float_conversion_nan_propagation_mode: FloatToFloatConversionNaNPropagationMode,
1069 pub rsqrt_nan_propagation_mode: UnaryNaNPropagationMode,
1071 _non_exhaustive: (),
1073}
1074
1075impl Default for PlatformProperties {
1076 fn default() -> PlatformProperties {
1077 PlatformProperties::default()
1078 }
1079}
1080
1081impl PlatformProperties {
1082 fn fallback_debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
1083 macro_rules! platform_properties_debug_full {
1084 (let f = $f:expr; $($var_assignments:tt)+) => {
1085 {
1086 $($var_assignments)+
1087 platform_properties_debug_full!(@fmt $f, $($var_assignments)+)
1088 }
1089 };
1090 (@fmt $f:expr, let Self { _non_exhaustive, $($field:ident,)+ } = self; $(let $fake_field:ident = $fake_field_init:expr;)+) => {
1091 $f.debug_struct("PlatformProperties")
1092 $(.field(stringify!($field), $field))+
1093 $(.field(stringify!($fake_field), &$fake_field))+
1094 .finish()
1095 };
1096 }
1097
1098 platform_properties_debug_full! {
1099 let f = f;
1100 let Self {
1101 _non_exhaustive,
1102 canonical_nan_sign,
1103 canonical_nan_mantissa_msb,
1104 canonical_nan_mantissa_second_to_msb,
1105 canonical_nan_mantissa_rest,
1106 std_bin_ops_nan_propagation_mode,
1107 fma_nan_propagation_mode,
1108 fma_inf_zero_qnan_result,
1109 round_to_integral_nan_propagation_mode,
1110 next_up_or_down_nan_propagation_mode,
1111 scale_b_nan_propagation_mode,
1112 sqrt_nan_propagation_mode,
1113 float_to_float_conversion_nan_propagation_mode,
1114 rsqrt_nan_propagation_mode,
1115 } = self;
1116 let quiet_nan_format = self.quiet_nan_format();
1117 }
1118 }
1119}
1120
1121macro_rules! platform_properties_constants {
1122 (
1123 $(
1124 $(#[$meta:meta])*
1125 pub const $ident:ident: PlatformProperties = $init:expr;
1126 )+
1127 ) => {
1128 #[cfg(feature = "python")]
1129 impl PyPlatformProperties {
1130 fn add_to_module(py: Python, m: &PyModule) -> PyResult<()> {
1131 m.add_class::<Self>()?;
1132 $(m.add::<PyObject>(concat!("PlatformProperties_", stringify!($ident)), PlatformProperties::$ident.into_py(py))?;)+
1133 Ok(())
1134 }
1135 }
1136
1137 #[cfg(feature = "python")]
1138 impl ToPythonRepr for PlatformProperties {
1139 fn to_python_repr(&self) -> Cow<str> {
1140 $(if *self == PlatformProperties::$ident {
1141 Cow::Borrowed(concat!("PlatformProperties_", stringify!($ident)))
1142 } else)+ {
1143 self.fallback_to_python_repr()
1144 }
1145 }
1146 }
1147
1148 impl PlatformProperties {
1149 $(
1150 $(#[$meta])*
1151 pub const $ident: PlatformProperties = $init;
1152 )+
1153 }
1154
1155 impl fmt::Debug for PlatformProperties {
1156 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1157 $(if *self == PlatformProperties::$ident {
1158 f.write_str(concat!("PlatformProperties::", stringify!($ident)))
1159 } else)+ {
1160 self.fallback_debug(f)
1161 }
1162 }
1163 }
1164 };
1165}
1166
1167platform_properties_constants! {
1168 pub const ARM: PlatformProperties = PlatformProperties::new_simple(
1170 Sign::Positive,
1171 true,
1172 false,
1173 false,
1174 UnaryNaNPropagationMode::First,
1176 BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
1177 TernaryNaNPropagationMode::ThirdFirstSecondPreferringSNaN,
1178 FMAInfZeroQNaNResult::CanonicalAndGenerateInvalid,
1179 FloatToFloatConversionNaNPropagationMode::RetainMostSignificantBits,
1180 );
1181 pub const RISC_V: PlatformProperties = PlatformProperties::new_simple(
1183 Sign::Positive,
1184 true,
1185 false,
1186 false,
1187 UnaryNaNPropagationMode::AlwaysCanonical,
1188 BinaryNaNPropagationMode::AlwaysCanonical,
1189 TernaryNaNPropagationMode::AlwaysCanonical,
1190 FMAInfZeroQNaNResult::CanonicalAndGenerateInvalid,
1191 FloatToFloatConversionNaNPropagationMode::AlwaysCanonical,
1192 );
1193 pub const POWER: PlatformProperties = PlatformProperties::new_simple(
1195 Sign::Positive,
1196 true,
1197 false,
1198 false,
1199 UnaryNaNPropagationMode::First,
1201 BinaryNaNPropagationMode::FirstSecond,
1202 TernaryNaNPropagationMode::FirstThirdSecond,
1203 FMAInfZeroQNaNResult::PropagateAndGenerateInvalid,
1204 FloatToFloatConversionNaNPropagationMode::RetainMostSignificantBits,
1205 );
1206 pub const MIPS_2008: PlatformProperties = PlatformProperties::new_simple(
1208 Sign::Positive,
1209 true,
1210 false,
1211 false,
1212 UnaryNaNPropagationMode::First,
1214 BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
1215 TernaryNaNPropagationMode::ThirdFirstSecondPreferringSNaN,
1216 FMAInfZeroQNaNResult::PropagateAndGenerateInvalid,
1217 FloatToFloatConversionNaNPropagationMode::RetainMostSignificantBits,
1218 );
1219 pub const X86_SSE: PlatformProperties = PlatformProperties::new_simple(
1222 Sign::Negative,
1223 true,
1224 false,
1225 false,
1226 UnaryNaNPropagationMode::First,
1228 BinaryNaNPropagationMode::FirstSecond,
1229 TernaryNaNPropagationMode::FirstSecondThird,
1230 FMAInfZeroQNaNResult::FollowNaNPropagationMode,
1231 FloatToFloatConversionNaNPropagationMode::RetainMostSignificantBits,
1232 );
1233 pub const SPARC: PlatformProperties = PlatformProperties::new_simple(
1235 Sign::Positive,
1236 true,
1237 true,
1238 true,
1239 UnaryNaNPropagationMode::First,
1241 BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
1242 TernaryNaNPropagationMode::FirstSecondThirdPreferringSNaN,
1243 FMAInfZeroQNaNResult::FollowNaNPropagationMode,
1244 FloatToFloatConversionNaNPropagationMode::RetainMostSignificantBits,
1245 );
1246 pub const HPPA: PlatformProperties = PlatformProperties::new_simple(
1248 Sign::Positive,
1249 false,
1250 true,
1251 false,
1252 UnaryNaNPropagationMode::First,
1254 BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
1255 TernaryNaNPropagationMode::FirstSecondThirdPreferringSNaN,
1256 FMAInfZeroQNaNResult::FollowNaNPropagationMode,
1257 FloatToFloatConversionNaNPropagationMode::RetainMostSignificantBits,
1258 );
1259 pub const MIPS_LEGACY: PlatformProperties = PlatformProperties::new_simple(
1261 Sign::Positive,
1262 false,
1263 true,
1264 true,
1265 UnaryNaNPropagationMode::First,
1267 BinaryNaNPropagationMode::FirstSecondPreferringSNaN,
1268 TernaryNaNPropagationMode::FirstSecondThirdPreferringSNaN,
1269 FMAInfZeroQNaNResult::CanonicalAndGenerateInvalid,
1270 FloatToFloatConversionNaNPropagationMode::RetainMostSignificantBits,
1271 );
1272}
1273
1274impl PlatformProperties {
1275 pub const fn new_simple(
1277 canonical_nan_sign: Sign,
1278 canonical_nan_mantissa_msb: bool,
1279 canonical_nan_mantissa_second_to_msb: bool,
1280 canonical_nan_mantissa_rest: bool,
1281 unary_nan_propagation_mode: UnaryNaNPropagationMode,
1282 binary_nan_propagation_mode: BinaryNaNPropagationMode,
1283 ternary_nan_propagation_mode: TernaryNaNPropagationMode,
1284 fma_inf_zero_qnan_result: FMAInfZeroQNaNResult,
1285 float_to_float_conversion_nan_propagation_mode: FloatToFloatConversionNaNPropagationMode,
1286 ) -> Self {
1287 Self {
1288 canonical_nan_sign,
1289 canonical_nan_mantissa_msb,
1290 canonical_nan_mantissa_second_to_msb,
1291 canonical_nan_mantissa_rest,
1292 std_bin_ops_nan_propagation_mode: binary_nan_propagation_mode,
1293 fma_nan_propagation_mode: ternary_nan_propagation_mode,
1294 fma_inf_zero_qnan_result,
1295 round_to_integral_nan_propagation_mode: unary_nan_propagation_mode,
1296 next_up_or_down_nan_propagation_mode: unary_nan_propagation_mode,
1297 scale_b_nan_propagation_mode: unary_nan_propagation_mode,
1298 sqrt_nan_propagation_mode: unary_nan_propagation_mode,
1299 float_to_float_conversion_nan_propagation_mode,
1300 rsqrt_nan_propagation_mode: unary_nan_propagation_mode,
1301 _non_exhaustive: (),
1302 }
1303 }
1304 pub const fn default() -> Self {
1307 Self::RISC_V
1308 }
1309 pub fn quiet_nan_format(self) -> QuietNaNFormat {
1311 if self.canonical_nan_mantissa_msb {
1312 QuietNaNFormat::Standard
1313 } else {
1314 QuietNaNFormat::MIPSLegacy
1315 }
1316 }
1317}
1318
1319#[derive(Clone, Debug, Default)]
1321pub struct FloatPropertiesIncompatible;
1322
1323impl fmt::Display for FloatPropertiesIncompatible {
1324 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1325 f.write_str("FloatProperties values incompatible: must be equal")
1326 }
1327}
1328
1329impl Error for FloatPropertiesIncompatible {}
1330
1331#[cfg(feature = "python")]
1332impl From<FloatPropertiesIncompatible> for PyErr {
1333 fn from(value: FloatPropertiesIncompatible) -> PyErr {
1334 PyErr::new::<pyo3::exceptions::TypeError, _>(format!("{}", value))
1335 }
1336}
1337
1338#[derive(Copy, Clone, Eq, PartialEq, Hash)]
1340pub struct FloatProperties {
1341 exponent_width: usize,
1342 mantissa_width: usize,
1343 has_implicit_leading_bit: bool,
1344 has_sign_bit: bool,
1345 platform_properties: PlatformProperties,
1346}
1347
1348impl FloatProperties {
1349 #[inline]
1351 pub fn check_compatibility(self, other: Self) -> Result<(), FloatPropertiesIncompatible> {
1352 if self == other {
1353 Ok(())
1354 } else {
1355 Err(FloatPropertiesIncompatible)
1356 }
1357 }
1358 #[inline]
1360 pub const fn new_with_extended_flags(
1361 exponent_width: usize,
1362 mantissa_width: usize,
1363 has_implicit_leading_bit: bool,
1364 has_sign_bit: bool,
1365 platform_properties: PlatformProperties,
1366 ) -> Self {
1367 Self {
1368 exponent_width,
1369 mantissa_width,
1370 has_implicit_leading_bit,
1371 has_sign_bit,
1372 platform_properties,
1373 }
1374 }
1375 #[inline]
1377 pub const fn new(exponent_width: usize, mantissa_width: usize) -> Self {
1378 Self {
1379 exponent_width,
1380 mantissa_width,
1381 has_implicit_leading_bit: true,
1382 has_sign_bit: true,
1383 platform_properties: PlatformProperties::default(),
1384 }
1385 }
1386 #[inline]
1388 pub const fn new_with_platform_properties(
1389 exponent_width: usize,
1390 mantissa_width: usize,
1391 platform_properties: PlatformProperties,
1392 ) -> Self {
1393 Self {
1394 exponent_width,
1395 mantissa_width,
1396 has_implicit_leading_bit: true,
1397 has_sign_bit: true,
1398 platform_properties,
1399 }
1400 }
1401 pub const STANDARD_16: Self =
1403 Self::standard_16_with_platform_properties(PlatformProperties::default());
1404 pub const STANDARD_32: Self =
1406 Self::standard_32_with_platform_properties(PlatformProperties::default());
1407 pub const STANDARD_64: Self =
1409 Self::standard_64_with_platform_properties(PlatformProperties::default());
1410 pub const STANDARD_128: Self =
1412 Self::standard_128_with_platform_properties(PlatformProperties::default());
1413 pub const fn standard_16_with_platform_properties(
1415 platform_properties: PlatformProperties,
1416 ) -> Self {
1417 Self::new_with_platform_properties(5, 10, platform_properties)
1418 }
1419 pub const fn standard_32_with_platform_properties(
1421 platform_properties: PlatformProperties,
1422 ) -> Self {
1423 Self::new_with_platform_properties(8, 23, platform_properties)
1424 }
1425 pub const fn standard_64_with_platform_properties(
1427 platform_properties: PlatformProperties,
1428 ) -> Self {
1429 Self::new_with_platform_properties(11, 52, platform_properties)
1430 }
1431 pub const fn standard_128_with_platform_properties(
1433 platform_properties: PlatformProperties,
1434 ) -> Self {
1435 Self::new_with_platform_properties(15, 112, platform_properties)
1436 }
1437 #[inline]
1439 pub fn standard_with_platform_properties(
1440 width: usize,
1441 platform_properties: PlatformProperties,
1442 ) -> Option<Self> {
1443 match width {
1444 16 => Some(Self::new_with_platform_properties(
1445 5,
1446 10,
1447 platform_properties,
1448 )),
1449 32 => Some(Self::new_with_platform_properties(
1450 8,
1451 23,
1452 platform_properties,
1453 )),
1454 64 => Some(Self::new_with_platform_properties(
1455 11,
1456 52,
1457 platform_properties,
1458 )),
1459 128 => Some(Self::new_with_platform_properties(
1460 15,
1461 112,
1462 platform_properties,
1463 )),
1464 _ => {
1465 if width > 128 && width.is_multiple_of(&32) {
1466 let exponent_width = ((width as f64).log2() * 4.0).round() as usize - 13;
1467 Some(Self::new_with_platform_properties(
1468 exponent_width,
1469 width - exponent_width - 1,
1470 platform_properties,
1471 ))
1472 } else {
1473 None
1474 }
1475 }
1476 }
1477 }
1478 #[inline]
1480 pub fn standard(width: usize) -> Option<Self> {
1481 Self::standard_with_platform_properties(width, PlatformProperties::default())
1482 }
1483 #[inline]
1485 pub fn is_standard(self) -> bool {
1486 Self::standard_with_platform_properties(self.width(), self.platform_properties())
1487 == Some(self)
1488 }
1489 #[inline]
1491 pub const fn exponent_width(self) -> usize {
1492 self.exponent_width
1493 }
1494 #[inline]
1496 pub const fn mantissa_width(self) -> usize {
1497 self.mantissa_width
1498 }
1499 #[inline]
1501 pub const fn has_implicit_leading_bit(self) -> bool {
1502 self.has_implicit_leading_bit
1503 }
1504 #[inline]
1506 pub const fn has_sign_bit(self) -> bool {
1507 self.has_sign_bit
1508 }
1509 #[inline]
1511 pub const fn platform_properties(self) -> PlatformProperties {
1512 self.platform_properties
1513 }
1514 #[inline]
1516 pub fn quiet_nan_format(self) -> QuietNaNFormat {
1517 self.platform_properties.quiet_nan_format()
1518 }
1519 #[inline]
1521 pub const fn width(self) -> usize {
1522 self.has_sign_bit as usize + self.exponent_width + self.mantissa_width
1523 }
1524 #[inline]
1526 pub const fn fraction_width(self) -> usize {
1527 self.mantissa_width - !self.has_implicit_leading_bit as usize
1528 }
1529 #[inline]
1534 pub const fn sign_field_shift(self) -> usize {
1535 self.exponent_width + self.mantissa_width
1536 }
1537 pub fn sign_field_mask<Bits: FloatBitsType>(self) -> Bits {
1541 Bits::one() << self.sign_field_shift()
1542 }
1543 #[inline]
1548 pub const fn exponent_field_shift(self) -> usize {
1549 self.mantissa_width
1550 }
1551 pub fn exponent_field_mask<Bits: FloatBitsType>(self) -> Bits {
1555 ((Bits::one() << self.exponent_width) - Bits::one()) << self.exponent_field_shift()
1556 }
1557 #[inline]
1562 pub const fn mantissa_field_shift(self) -> usize {
1563 0
1564 }
1565 pub fn mantissa_field_mask<Bits: FloatBitsType>(self) -> Bits {
1569 (Bits::one() << self.mantissa_width) - Bits::one()
1570 }
1571 pub fn mantissa_field_max<Bits: FloatBitsType>(self) -> Bits {
1573 (Bits::one() << self.mantissa_width) - Bits::one()
1574 }
1575 pub fn mantissa_field_normal_min<Bits: FloatBitsType>(self) -> Bits {
1577 if self.has_implicit_leading_bit {
1578 Bits::zero()
1579 } else {
1580 Bits::one() << self.fraction_width()
1581 }
1582 }
1583 #[inline]
1588 pub const fn mantissa_field_msb_shift(self) -> usize {
1589 self.mantissa_width - 1
1590 }
1591 pub fn mantissa_field_msb_mask<Bits: FloatBitsType>(self) -> Bits {
1595 Bits::one() << self.mantissa_field_msb_shift()
1596 }
1597 pub fn exponent_bias<Bits: FloatBitsType>(self) -> Bits {
1604 if self.exponent_width == 0 {
1605 Bits::zero()
1606 } else {
1607 (Bits::one() << (self.exponent_width - 1)) - Bits::one()
1608 }
1609 }
1610 pub fn exponent_inf_nan<Bits: FloatBitsType>(self) -> Bits {
1612 (Bits::one() << self.exponent_width) - Bits::one()
1613 }
1614 pub fn exponent_zero_subnormal<Bits: FloatBitsType>(self) -> Bits {
1616 Bits::zero()
1617 }
1618 pub fn exponent_min_normal<Bits: FloatBitsType>(self) -> Bits {
1624 Bits::one()
1625 }
1626 pub fn exponent_max_normal<Bits: FloatBitsType>(self) -> Bits {
1632 self.exponent_inf_nan::<Bits>() - Bits::one()
1633 }
1634 pub fn overall_mask<Bits: FloatBitsType>(self) -> Bits {
1636 self.sign_field_mask::<Bits>()
1637 | self.exponent_field_mask::<Bits>()
1638 | self.mantissa_field_mask::<Bits>()
1639 }
1640 fn fallback_debug(&self, f: &mut fmt::Formatter, is_standard: bool) -> fmt::Result {
1641 f.debug_struct("FloatProperties")
1642 .field("exponent_width", &self.exponent_width())
1643 .field("mantissa_width", &self.mantissa_width())
1644 .field("has_implicit_leading_bit", &self.has_implicit_leading_bit())
1645 .field("has_sign_bit", &self.has_sign_bit())
1646 .field("platform_properties", &self.platform_properties())
1647 .field("quiet_nan_format", &self.quiet_nan_format())
1648 .field("width", &self.width())
1649 .field("fraction_width", &self.fraction_width())
1650 .field("is_standard", &is_standard)
1651 .finish()
1652 }
1653}
1654
1655impl fmt::Debug for FloatProperties {
1656 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1657 let is_standard = self.is_standard();
1658 if !f.alternate() && is_standard {
1659 if self.platform_properties() == PlatformProperties::default() {
1660 match self.width() {
1661 16 => f.write_str("FloatProperties::STANDARD_16"),
1662 32 => f.write_str("FloatProperties::STANDARD_32"),
1663 64 => f.write_str("FloatProperties::STANDARD_64"),
1664 128 => f.write_str("FloatProperties::STANDARD_128"),
1665 width => write!(f, "FloatProperties::standard({})", width),
1666 }
1667 } else {
1668 match self.width() {
1669 16 => write!(
1670 f,
1671 "FloatProperties::standard_16_with_platform_properties({:?})",
1672 self.platform_properties()
1673 ),
1674 32 => write!(
1675 f,
1676 "FloatProperties::standard_32_with_platform_properties({:?})",
1677 self.platform_properties()
1678 ),
1679 64 => write!(
1680 f,
1681 "FloatProperties::standard_64_with_platform_properties({:?})",
1682 self.platform_properties()
1683 ),
1684 128 => write!(
1685 f,
1686 "FloatProperties::standard_128_with_platform_properties({:?})",
1687 self.platform_properties()
1688 ),
1689 width => write!(
1690 f,
1691 "FloatProperties::standard_with_platform_properties({}, {:?})",
1692 width,
1693 self.platform_properties()
1694 ),
1695 }
1696 }
1697 } else {
1698 self.fallback_debug(f, is_standard)
1699 }
1700 }
1701}
1702
1703pub trait FloatTraits: Clone + fmt::Debug + PartialEq {
1705 type Bits: FloatBitsType;
1707 fn properties(&self) -> FloatProperties;
1709}
1710
1711#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug, Default)]
1713pub struct F16Traits;
1714
1715#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
1718pub struct F16WithPlatformPropertiesTraits(pub PlatformProperties);
1719
1720#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug, Default)]
1722pub struct F32Traits;
1723
1724#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
1727pub struct F32WithPlatformPropertiesTraits(pub PlatformProperties);
1728
1729#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug, Default)]
1731pub struct F64Traits;
1732
1733#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
1736pub struct F64WithPlatformPropertiesTraits(pub PlatformProperties);
1737
1738#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug, Default)]
1740pub struct F128Traits;
1741
1742#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
1745pub struct F128WithPlatformPropertiesTraits(pub PlatformProperties);
1746
1747impl FloatTraits for FloatProperties {
1748 type Bits = BigUint;
1749 fn properties(&self) -> FloatProperties {
1750 *self
1751 }
1752}
1753
1754impl FloatTraits for F16Traits {
1755 type Bits = u16;
1756 fn properties(&self) -> FloatProperties {
1757 FloatProperties::STANDARD_16
1758 }
1759}
1760
1761impl FloatTraits for F16WithPlatformPropertiesTraits {
1762 type Bits = u16;
1763 fn properties(&self) -> FloatProperties {
1764 FloatProperties::standard_16_with_platform_properties(self.0)
1765 }
1766}
1767
1768impl FloatTraits for F32Traits {
1769 type Bits = u32;
1770 fn properties(&self) -> FloatProperties {
1771 FloatProperties::STANDARD_32
1772 }
1773}
1774
1775impl FloatTraits for F32WithPlatformPropertiesTraits {
1776 type Bits = u32;
1777 fn properties(&self) -> FloatProperties {
1778 FloatProperties::standard_32_with_platform_properties(self.0)
1779 }
1780}
1781
1782impl FloatTraits for F64Traits {
1783 type Bits = u64;
1784 fn properties(&self) -> FloatProperties {
1785 FloatProperties::STANDARD_64
1786 }
1787}
1788
1789impl FloatTraits for F64WithPlatformPropertiesTraits {
1790 type Bits = u64;
1791 fn properties(&self) -> FloatProperties {
1792 FloatProperties::standard_64_with_platform_properties(self.0)
1793 }
1794}
1795
1796impl FloatTraits for F128Traits {
1797 type Bits = u128;
1798 fn properties(&self) -> FloatProperties {
1799 FloatProperties::STANDARD_128
1800 }
1801}
1802
1803impl FloatTraits for F128WithPlatformPropertiesTraits {
1804 type Bits = u128;
1805 fn properties(&self) -> FloatProperties {
1806 FloatProperties::standard_128_with_platform_properties(self.0)
1807 }
1808}
1809
1810struct RoundedMantissa {
1811 inexact: bool,
1812 exponent: i64,
1813 mantissa: BigInt,
1814}
1815
1816impl RoundedMantissa {
1817 fn new(
1818 value: &RealAlgebraicNumber,
1819 exponent: i64,
1820 sign: Sign,
1821 rounding_mode: RoundingMode,
1822 properties: FloatProperties,
1823 max_mantissa: &BigInt,
1824 ) -> Self {
1825 assert!(!value.is_negative());
1826 let ulp_shift = exponent
1827 - properties
1828 .fraction_width()
1829 .to_i64()
1830 .expect("fraction_width doesn't fit in i64");
1831 let ulp = if ulp_shift < 0 {
1832 let shift = (-ulp_shift)
1833 .to_usize()
1834 .expect("ulp_shift doesn't fit in usize");
1835 Ratio::new(BigInt::one(), BigInt::one() << shift)
1836 } else {
1837 Ratio::from(
1838 BigInt::one() << ulp_shift.to_usize().expect("exponent doesn't fit in usize"),
1839 )
1840 };
1841 let value_in_ulps = value / RealAlgebraicNumber::from(ulp);
1842 let lower_float_exponent = exponent;
1843 let lower_float_mantissa = value_in_ulps.to_integer_floor();
1844 let remainder_in_ulps =
1845 value_in_ulps - RealAlgebraicNumber::from(lower_float_mantissa.clone());
1846 assert!(!lower_float_mantissa.is_negative());
1847 assert!(lower_float_mantissa <= *max_mantissa);
1848 if remainder_in_ulps.is_zero() {
1849 Self {
1850 inexact: false,
1851 exponent: lower_float_exponent,
1852 mantissa: lower_float_mantissa,
1853 }
1854 } else {
1855 let mut upper_float_mantissa = &lower_float_mantissa + 1i32;
1856 let mut upper_float_exponent = lower_float_exponent;
1857 if upper_float_mantissa > *max_mantissa {
1858 upper_float_mantissa >>= 1;
1859 upper_float_exponent += 1;
1860 }
1861 match (rounding_mode, sign) {
1862 (RoundingMode::TiesToEven, _) | (RoundingMode::TiesToAway, _) => {
1863 match remainder_in_ulps.cmp(&RealAlgebraicNumber::from(Ratio::new(1, 2))) {
1864 Ordering::Less => Self {
1865 inexact: true,
1866 exponent: lower_float_exponent,
1867 mantissa: lower_float_mantissa,
1868 },
1869 Ordering::Equal => {
1870 if rounding_mode == RoundingMode::TiesToAway
1871 || lower_float_mantissa.is_odd()
1872 {
1873 Self {
1874 inexact: true,
1875 exponent: upper_float_exponent,
1876 mantissa: upper_float_mantissa,
1877 }
1878 } else {
1879 Self {
1880 inexact: true,
1881 exponent: lower_float_exponent,
1882 mantissa: lower_float_mantissa,
1883 }
1884 }
1885 }
1886 Ordering::Greater => Self {
1887 inexact: true,
1888 exponent: upper_float_exponent,
1889 mantissa: upper_float_mantissa,
1890 },
1891 }
1892 }
1893 (RoundingMode::TowardZero, _) => Self {
1894 inexact: true,
1895 exponent: lower_float_exponent,
1896 mantissa: lower_float_mantissa,
1897 },
1898 (RoundingMode::TowardNegative, Sign::Negative)
1899 | (RoundingMode::TowardPositive, Sign::Positive) => Self {
1900 inexact: true,
1901 exponent: upper_float_exponent,
1902 mantissa: upper_float_mantissa,
1903 },
1904 (RoundingMode::TowardNegative, Sign::Positive)
1905 | (RoundingMode::TowardPositive, Sign::Negative) => Self {
1906 inexact: true,
1907 exponent: lower_float_exponent,
1908 mantissa: lower_float_mantissa,
1909 },
1910 }
1911 }
1912 }
1913}
1914
1915python_enum! {
1916 #[pyenum(module = simple_soft_float, repr = u8, test_fn = test_up_or_down_enum)]
1917 pub enum UpOrDown {
1919 Up,
1921 Down,
1923 }
1924}
1925
1926impl Default for UpOrDown {
1927 fn default() -> Self {
1928 Self::Up
1929 }
1930}
1931
1932impl From<UpOrDown> for Sign {
1933 fn from(up_or_down: UpOrDown) -> Sign {
1934 match up_or_down {
1935 UpOrDown::Up => Sign::Positive,
1936 UpOrDown::Down => Sign::Negative,
1937 }
1938 }
1939}
1940
1941#[derive(Copy, Clone)]
1943pub struct Float<FT: FloatTraits> {
1944 traits: FT,
1945 bits: FT::Bits,
1946}
1947
1948impl<FT: FloatTraits + Default> Default for Float<FT> {
1949 fn default() -> Self {
1950 Self::positive_zero()
1951 }
1952}
1953
1954macro_rules! impl_from_int_type {
1955 ($from_int_with_traits:ident, $from_int:ident, $int:ident) => {
1956 pub fn $from_int_with_traits(
1958 value: $int,
1959 rounding_mode: Option<RoundingMode>,
1960 fp_state: Option<&mut FPState>,
1961 traits: FT,
1962 ) -> Self {
1963 Self::from_real_algebraic_number_with_traits(
1964 &value.into(),
1965 rounding_mode,
1966 fp_state,
1967 traits,
1968 )
1969 }
1970 pub fn $from_int(
1972 value: $int,
1973 rounding_mode: Option<RoundingMode>,
1974 fp_state: Option<&mut FPState>,
1975 ) -> Self
1976 where
1977 FT: Default,
1978 {
1979 Self::$from_int_with_traits(value, rounding_mode, fp_state, FT::default())
1980 }
1981 };
1982}
1983
1984macro_rules! impl_to_int_type {
1985 ($name:ident, $from_bigint:ident, $int:ident) => {
1986 pub fn $name(
1988 &self,
1989 exact: bool,
1990 rounding_mode: Option<RoundingMode>,
1991 fp_state: Option<&mut FPState>,
1992 ) -> Option<$int> {
1993 let mut default_fp_state = FPState::default();
1994 let fp_state = fp_state.unwrap_or(&mut default_fp_state);
1995 let old_status_flags = fp_state.status_flags;
1996 if let Some(retval) = self.round_to_integer(exact, rounding_mode, Some(fp_state)).and_then(|v| v.$from_bigint()) {
1997 Some(retval)
1998 } else {
1999 fp_state.status_flags = old_status_flags | StatusFlags::INVALID_OPERATION;
2001 None
2002 }
2003 }
2004 };
2005}
2006
2007impl<Bits: FloatBitsType, FT: FloatTraits<Bits = Bits>> Float<FT> {
2008 fn check_bits(bits: Bits, traits: &FT) -> Bits {
2009 assert!(
2010 traits.properties().overall_mask::<Bits>() & &bits == bits,
2011 "bits out of range"
2012 );
2013 bits
2014 }
2015 pub fn from_bits_and_traits(bits: Bits, traits: FT) -> Self {
2017 Self {
2018 bits: Self::check_bits(bits, &traits),
2019 traits,
2020 }
2021 }
2022 pub fn from_bits(bits: Bits) -> Self
2024 where
2025 FT: Default,
2026 {
2027 Self::from_bits_and_traits(bits, FT::default())
2028 }
2029 pub fn bits(&self) -> &Bits {
2031 &self.bits
2032 }
2033 pub fn set_bits(&mut self, bits: Bits) {
2035 self.bits = Self::check_bits(bits, &self.traits);
2036 }
2037 pub fn traits(&self) -> &FT {
2039 &self.traits
2040 }
2041 pub fn into_bits_and_traits(self) -> (Bits, FT) {
2043 (self.bits, self.traits)
2044 }
2045 pub fn into_bits(self) -> Bits {
2047 self.bits
2048 }
2049 pub fn into_traits(self) -> FT {
2051 self.traits
2052 }
2053 pub fn properties(&self) -> FloatProperties {
2055 self.traits.properties()
2056 }
2057 pub fn sign(&self) -> Sign {
2059 let properties = self.properties();
2060 if properties.has_sign_bit() {
2061 if (self.bits.clone() >> properties.sign_field_shift()).is_zero() {
2062 Sign::Positive
2063 } else {
2064 Sign::Negative
2065 }
2066 } else {
2067 Sign::Positive
2068 }
2069 }
2070 fn xor_bits(&mut self, bits: Bits) {
2071 BitXorAssign::<Bits>::bitxor_assign(&mut self.bits, bits);
2072 }
2073 fn or_bits(&mut self, bits: Bits) {
2074 BitOrAssign::<Bits>::bitor_assign(&mut self.bits, bits);
2075 }
2076 fn and_not_bits(&mut self, bits: Bits) {
2077 BitOrAssign::<&Bits>::bitor_assign(&mut self.bits, &bits);
2078 self.xor_bits(bits)
2079 }
2080 pub fn set_sign(&mut self, sign: Sign) {
2082 let properties = self.properties();
2083 if !properties.has_sign_bit() {
2084 assert_eq!(sign, Sign::Positive);
2085 return;
2086 }
2087 match sign {
2088 Sign::Positive => self.and_not_bits(properties.sign_field_mask()),
2089 Sign::Negative => self.or_bits(properties.sign_field_mask()),
2090 }
2091 }
2092 pub fn toggle_sign(&mut self) {
2094 let properties = self.properties();
2095 assert!(properties.has_sign_bit());
2096 self.xor_bits(properties.sign_field_mask());
2097 }
2098 pub fn exponent_field(&self) -> Bits {
2104 let properties = self.properties();
2105 (properties.exponent_field_mask::<Bits>() & &self.bits) >> properties.exponent_field_shift()
2106 }
2107 pub fn set_exponent_field(&mut self, mut exponent: Bits) {
2113 let properties = self.properties();
2114 exponent <<= properties.exponent_field_shift();
2115 let mask: Bits = properties.exponent_field_mask();
2116 assert!(
2117 mask.clone() & &exponent == exponent,
2118 "exponent out of range"
2119 );
2120 self.and_not_bits(mask);
2121 self.or_bits(exponent);
2122 }
2123 pub fn mantissa_field(&self) -> Bits {
2125 let properties = self.properties();
2126 (properties.mantissa_field_mask::<Bits>() & &self.bits) >> properties.mantissa_field_shift()
2127 }
2128 pub fn set_mantissa_field(&mut self, mut mantissa: Bits) {
2130 let properties = self.properties();
2131 mantissa <<= properties.mantissa_field_shift();
2132 let mask: Bits = properties.mantissa_field_mask();
2133 assert!(
2134 mask.clone() & &mantissa == mantissa,
2135 "mantissa out of range"
2136 );
2137 self.and_not_bits(mask);
2138 self.or_bits(mantissa);
2139 }
2140 pub fn mantissa_field_msb(&self) -> bool {
2142 let properties = self.properties();
2143 !(properties.mantissa_field_msb_mask::<Bits>() & &self.bits).is_zero()
2144 }
2145 pub fn set_mantissa_field_msb(&mut self, mantissa_msb: bool) {
2147 let properties = self.properties();
2148 if mantissa_msb {
2149 self.or_bits(properties.mantissa_field_msb_mask());
2150 } else {
2151 self.and_not_bits(properties.mantissa_field_msb_mask());
2152 }
2153 }
2154 pub fn class(&self) -> FloatClass {
2156 let properties = self.properties();
2157 let sign = self.sign();
2158 let mut exponent_field = self.exponent_field();
2159 let mut mantissa_field = self.mantissa_field();
2160 let retval = if exponent_field == properties.exponent_zero_subnormal() {
2161 if mantissa_field.is_zero() {
2162 FloatClass::PositiveZero
2163 } else {
2164 FloatClass::PositiveSubnormal
2165 }
2166 } else if exponent_field == properties.exponent_inf_nan() {
2167 if mantissa_field.is_zero() {
2168 FloatClass::PositiveInfinity
2169 } else if properties
2170 .quiet_nan_format()
2171 .is_nan_quiet(self.mantissa_field_msb())
2172 {
2173 FloatClass::QuietNaN
2174 } else {
2175 FloatClass::SignalingNaN
2176 }
2177 } else if properties.has_implicit_leading_bit() {
2178 FloatClass::PositiveNormal
2179 } else if mantissa_field.is_zero() {
2180 FloatClass::PositiveZero
2181 } else {
2182 loop {
2183 if (properties.mantissa_field_msb_mask::<Bits>() & &mantissa_field).is_zero() {
2184 mantissa_field <<= 1;
2185 exponent_field -= Bits::one();
2186 if exponent_field == properties.exponent_zero_subnormal() {
2187 break FloatClass::PositiveSubnormal;
2188 }
2189 } else {
2190 break FloatClass::PositiveNormal;
2191 }
2192 }
2193 };
2194 match sign {
2195 Sign::Positive => retval,
2196 Sign::Negative => -retval,
2197 }
2198 }
2199 #[inline]
2201 pub fn is_negative_infinity(&self) -> bool {
2202 self.class().is_negative_infinity()
2203 }
2204 #[inline]
2206 pub fn is_negative_normal(&self) -> bool {
2207 self.class().is_negative_normal()
2208 }
2209 #[inline]
2211 pub fn is_negative_subnormal(&self) -> bool {
2212 self.class().is_negative_subnormal()
2213 }
2214 #[inline]
2216 pub fn is_negative_zero(&self) -> bool {
2217 self.class().is_negative_zero()
2218 }
2219 #[inline]
2221 pub fn is_positive_infinity(&self) -> bool {
2222 self.class().is_positive_infinity()
2223 }
2224 #[inline]
2226 pub fn is_positive_normal(&self) -> bool {
2227 self.class().is_positive_normal()
2228 }
2229 #[inline]
2231 pub fn is_positive_subnormal(&self) -> bool {
2232 self.class().is_positive_subnormal()
2233 }
2234 #[inline]
2236 pub fn is_positive_zero(&self) -> bool {
2237 self.class().is_positive_zero()
2238 }
2239 #[inline]
2241 pub fn is_quiet_nan(&self) -> bool {
2242 self.class().is_quiet_nan()
2243 }
2244 #[inline]
2246 pub fn is_signaling_nan(&self) -> bool {
2247 self.class().is_signaling_nan()
2248 }
2249 #[inline]
2251 pub fn is_infinity(&self) -> bool {
2252 self.class().is_infinity()
2253 }
2254 #[inline]
2256 pub fn is_normal(&self) -> bool {
2257 self.class().is_normal()
2258 }
2259 #[inline]
2261 pub fn is_subnormal(&self) -> bool {
2262 self.class().is_subnormal()
2263 }
2264 #[inline]
2266 pub fn is_zero(&self) -> bool {
2267 self.class().is_zero()
2268 }
2269 #[inline]
2271 pub fn is_nan(&self) -> bool {
2272 self.class().is_nan()
2273 }
2274 #[inline]
2276 pub fn is_finite(&self) -> bool {
2277 self.class().is_finite()
2278 }
2279 #[inline]
2281 pub fn is_subnormal_or_zero(&self) -> bool {
2282 self.class().is_subnormal_or_zero()
2283 }
2284 pub fn to_ratio(&self) -> Option<Ratio<BigInt>> {
2287 if !self.is_finite() {
2288 return None;
2289 }
2290 let properties = self.properties();
2291 let sign = self.sign();
2292 let exponent_field = self.exponent_field();
2293 let mantissa_field = self.mantissa_field();
2294 let mut mantissa: BigInt = mantissa_field.into();
2295 let mut exponent = exponent_field
2296 .to_i64()
2297 .expect("exponent_field doesn't fit in i64");
2298 if self.is_subnormal_or_zero() {
2299 exponent = properties
2300 .exponent_min_normal::<Bits>()
2301 .to_i64()
2302 .expect("exponent_field doesn't fit in i64");
2303 } else if properties.has_implicit_leading_bit() {
2304 mantissa |= BigInt::one() << properties.fraction_width();
2305 }
2306 exponent -= properties
2307 .exponent_bias::<Bits>()
2308 .to_i64()
2309 .expect("exponent bias doesn't fit in i64");
2310 exponent -= properties
2311 .fraction_width()
2312 .to_i64()
2313 .expect("fraction_width doesn't fit in i64");
2314 let mut retval = if exponent.is_negative() {
2315 let shift = (-exponent)
2316 .to_usize()
2317 .expect("exponent doesn't fit in usize");
2318 Ratio::new(mantissa, BigInt::one() << shift)
2319 } else {
2320 Ratio::from(mantissa << exponent.to_usize().expect("exponent doesn't fit in usize"))
2321 };
2322 if sign == Sign::Negative {
2323 retval = -retval;
2324 }
2325 Some(retval)
2326 }
2327 pub fn to_real_algebraic_number(&self) -> Option<RealAlgebraicNumber> {
2330 self.to_ratio().map(Into::into)
2331 }
2332 pub fn positive_zero_with_traits(traits: FT) -> Self {
2334 Self::from_bits_and_traits(Bits::zero(), traits)
2335 }
2336 pub fn positive_zero() -> Self
2338 where
2339 FT: Default,
2340 {
2341 Self::positive_zero_with_traits(FT::default())
2342 }
2343 pub fn negative_zero_with_traits(traits: FT) -> Self {
2345 let properties = traits.properties();
2346 assert!(properties.has_sign_bit());
2347 let bits = properties.sign_field_mask::<Bits>();
2348 Self::from_bits_and_traits(bits, traits)
2349 }
2350 pub fn negative_zero() -> Self
2352 where
2353 FT: Default,
2354 {
2355 Self::negative_zero_with_traits(FT::default())
2356 }
2357 pub fn signed_zero_with_traits(sign: Sign, traits: FT) -> Self {
2359 match sign {
2360 Sign::Positive => Self::positive_zero_with_traits(traits),
2361 Sign::Negative => Self::negative_zero_with_traits(traits),
2362 }
2363 }
2364 pub fn signed_zero(sign: Sign) -> Self
2366 where
2367 FT: Default,
2368 {
2369 Self::signed_zero_with_traits(sign, FT::default())
2370 }
2371 pub fn positive_infinity_with_traits(traits: FT) -> Self {
2373 let properties = traits.properties();
2374 let mut retval = Self::positive_zero_with_traits(traits);
2375 retval.set_exponent_field(properties.exponent_inf_nan::<Bits>());
2376 retval
2377 }
2378 pub fn positive_infinity() -> Self
2380 where
2381 FT: Default,
2382 {
2383 Self::positive_infinity_with_traits(FT::default())
2384 }
2385 pub fn negative_infinity_with_traits(traits: FT) -> Self {
2387 let properties = traits.properties();
2388 let mut retval = Self::negative_zero_with_traits(traits);
2389 retval.set_exponent_field(properties.exponent_inf_nan::<Bits>());
2390 retval
2391 }
2392 pub fn negative_infinity() -> Self
2394 where
2395 FT: Default,
2396 {
2397 Self::negative_infinity_with_traits(FT::default())
2398 }
2399 pub fn signed_infinity_with_traits(sign: Sign, traits: FT) -> Self {
2401 match sign {
2402 Sign::Positive => Self::positive_infinity_with_traits(traits),
2403 Sign::Negative => Self::negative_infinity_with_traits(traits),
2404 }
2405 }
2406 pub fn signed_infinity(sign: Sign) -> Self
2408 where
2409 FT: Default,
2410 {
2411 Self::signed_infinity_with_traits(sign, FT::default())
2412 }
2413 pub fn quiet_nan_with_traits(traits: FT) -> Self {
2415 let properties = traits.properties();
2416 let mut retval = Self::positive_zero_with_traits(traits);
2417 retval.set_exponent_field(properties.exponent_inf_nan::<Bits>());
2418 match properties.quiet_nan_format() {
2419 QuietNaNFormat::Standard => retval.set_mantissa_field_msb(true),
2420 QuietNaNFormat::MIPSLegacy => {
2421 retval.set_mantissa_field(properties.mantissa_field_max());
2422 retval.set_mantissa_field_msb(false);
2423 }
2424 }
2425 retval
2426 }
2427 pub fn quiet_nan() -> Self
2429 where
2430 FT: Default,
2431 {
2432 Self::quiet_nan_with_traits(FT::default())
2433 }
2434 pub fn signaling_nan_with_traits(traits: FT) -> Self {
2436 let properties = traits.properties();
2437 let mut retval = Self::positive_zero_with_traits(traits);
2438 retval.set_exponent_field(properties.exponent_inf_nan::<Bits>());
2439 match properties.quiet_nan_format() {
2440 QuietNaNFormat::Standard => retval.set_mantissa_field(Bits::one()),
2441 QuietNaNFormat::MIPSLegacy => retval.set_mantissa_field_msb(true),
2442 }
2443 retval
2444 }
2445 pub fn signaling_nan() -> Self
2447 where
2448 FT: Default,
2449 {
2450 Self::signaling_nan_with_traits(FT::default())
2451 }
2452 pub fn into_quiet_nan(mut self) -> Self {
2454 let properties = self.properties();
2455 self.set_exponent_field(properties.exponent_inf_nan::<Bits>());
2456 match properties.quiet_nan_format() {
2458 QuietNaNFormat::Standard => self.set_mantissa_field_msb(true),
2459 QuietNaNFormat::MIPSLegacy => return Self::quiet_nan_with_traits(self.traits),
2460 }
2461 self
2462 }
2463 pub fn to_quiet_nan(&self) -> Self {
2465 self.clone().into_quiet_nan()
2466 }
2467 pub fn signed_max_normal_with_traits(sign: Sign, traits: FT) -> Self {
2469 let properties = traits.properties();
2470 let mut retval = Self::signed_zero_with_traits(sign, traits);
2471 retval.set_mantissa_field(properties.mantissa_field_max());
2472 retval.set_exponent_field(properties.exponent_max_normal());
2473 retval
2474 }
2475 pub fn signed_max_normal(sign: Sign) -> Self
2477 where
2478 FT: Default,
2479 {
2480 Self::signed_max_normal_with_traits(sign, FT::default())
2481 }
2482 pub fn signed_min_subnormal_with_traits(sign: Sign, traits: FT) -> Self {
2484 let properties = traits.properties();
2485 let mut retval = Self::signed_zero_with_traits(sign, traits);
2486 retval.set_mantissa_field(Bits::one());
2487 retval.set_exponent_field(properties.exponent_zero_subnormal());
2488 retval
2489 }
2490 pub fn signed_min_subnormal(sign: Sign) -> Self
2492 where
2493 FT: Default,
2494 {
2495 Self::signed_min_subnormal_with_traits(sign, FT::default())
2496 }
2497 pub fn from_real_algebraic_number_with_traits(
2499 value: &RealAlgebraicNumber,
2500 rounding_mode: Option<RoundingMode>,
2501 fp_state: Option<&mut FPState>,
2502 traits: FT,
2503 ) -> Self {
2504 let mut default_fp_state = FPState::default();
2505 let fp_state = fp_state.unwrap_or(&mut default_fp_state);
2506 let rounding_mode = rounding_mode.unwrap_or(fp_state.rounding_mode);
2507 let properties = traits.properties();
2508 let sign = if value.is_positive() {
2509 Sign::Positive
2510 } else if !properties.has_sign_bit() {
2511 if !value.is_zero() {
2512 fp_state.status_flags |= StatusFlags::INEXACT | StatusFlags::UNDERFLOW;
2513 }
2514 return Self::positive_zero_with_traits(traits);
2515 } else {
2516 Sign::Negative
2517 };
2518 let value = value.abs();
2519 let exponent = if let Some(v) = value.checked_floor_log2() {
2520 v
2521 } else {
2522 return Self::positive_zero_with_traits(traits);
2523 };
2524 let exponent_bias = properties.exponent_bias::<Bits>();
2525 let exponent_bias_i64 = exponent_bias
2526 .to_i64()
2527 .expect("exponent_bias doesn't fit in i64");
2528 let exponent_max = properties
2529 .exponent_max_normal::<Bits>()
2530 .to_i64()
2531 .expect("exponent_max_normal doesn't fit in i64")
2532 - exponent_bias_i64;
2533 if exponent > exponent_max {
2534 fp_state.status_flags |= StatusFlags::INEXACT | StatusFlags::OVERFLOW;
2535 match (rounding_mode, sign) {
2536 (RoundingMode::TowardNegative, Sign::Positive)
2537 | (RoundingMode::TowardPositive, Sign::Negative)
2538 | (RoundingMode::TowardZero, _) => {
2539 return Self::signed_max_normal_with_traits(sign, traits);
2540 }
2541 (RoundingMode::TowardNegative, Sign::Negative)
2542 | (RoundingMode::TowardPositive, Sign::Positive)
2543 | (RoundingMode::TiesToEven, _)
2544 | (RoundingMode::TiesToAway, _) => {
2545 return Self::signed_infinity_with_traits(sign, traits);
2546 }
2547 }
2548 }
2549 let exponent_min = properties
2550 .exponent_min_normal::<Bits>()
2551 .to_i64()
2552 .expect("exponent_min_normal doesn't fit in i64")
2553 - exponent_bias_i64;
2554 let min_normal_mantissa = BigInt::one() << properties.fraction_width();
2555 let mut max_mantissa: BigInt = properties.mantissa_field_max::<BigUint>().into();
2556 max_mantissa |= &min_normal_mantissa;
2557 let RoundedMantissa {
2558 inexact,
2559 exponent: retval_exponent,
2560 mantissa: mut retval_mantissa,
2561 } = RoundedMantissa::new(
2562 &value,
2563 exponent.max(exponent_min),
2564 sign,
2565 rounding_mode,
2566 properties,
2567 &max_mantissa,
2568 );
2569 let check_for_underflow = match fp_state.exception_handling_mode {
2570 ExceptionHandlingMode::IgnoreExactUnderflow => inexact,
2571 ExceptionHandlingMode::SignalExactUnderflow => true,
2572 };
2573 if exponent < exponent_min && check_for_underflow {
2574 let tiny = match fp_state.tininess_detection_mode {
2575 TininessDetectionMode::BeforeRounding => true,
2576 TininessDetectionMode::AfterRounding => {
2577 if retval_mantissa < min_normal_mantissa {
2578 true
2579 } else {
2580 RoundedMantissa::new(
2581 &value,
2582 exponent_min - 1,
2583 sign,
2584 rounding_mode,
2585 properties,
2586 &max_mantissa,
2587 )
2588 .exponent
2589 < exponent_min
2590 }
2591 }
2592 };
2593 if tiny {
2594 fp_state.status_flags |= StatusFlags::UNDERFLOW;
2595 }
2596 }
2597 if inexact {
2598 fp_state.status_flags |= StatusFlags::INEXACT;
2599 }
2600 if retval_exponent > exponent_max {
2601 fp_state.status_flags |= StatusFlags::OVERFLOW;
2602 return Self::signed_infinity_with_traits(sign, traits);
2603 }
2604 let mut retval = Self::signed_zero_with_traits(sign, traits);
2605 if retval_mantissa < min_normal_mantissa {
2606 assert_eq!(retval_exponent, exponent_min);
2607 retval.set_exponent_field(properties.exponent_zero_subnormal());
2608 retval.set_mantissa_field(
2609 Bits::from_bigint(&retval_mantissa).expect("retval_mantissa doesn't fit in Bits"),
2610 );
2611 } else {
2612 if properties.has_implicit_leading_bit() {
2613 retval_mantissa &= !&min_normal_mantissa;
2614 assert!(retval_mantissa < min_normal_mantissa);
2615 }
2616 let exponent_field = Bits::from_i64(retval_exponent + exponent_bias_i64)
2617 .expect("exponent doesn't fit in Bits");
2618 retval.set_exponent_field(exponent_field);
2619 retval.set_mantissa_field(
2620 Bits::from_bigint(&retval_mantissa).expect("retval_mantissa doesn't fit in Bits"),
2621 );
2622 }
2623 retval
2624 }
2625 pub fn from_real_algebraic_number(
2627 value: &RealAlgebraicNumber,
2628 rounding_mode: Option<RoundingMode>,
2629 fp_state: Option<&mut FPState>,
2630 ) -> Self
2631 where
2632 FT: Default,
2633 {
2634 Self::from_real_algebraic_number_with_traits(value, rounding_mode, fp_state, FT::default())
2635 }
2636 fn add_or_sub(
2637 &self,
2638 rhs: &Self,
2639 rounding_mode: Option<RoundingMode>,
2640 fp_state: Option<&mut FPState>,
2641 is_sub: bool,
2642 ) -> Self {
2643 assert_eq!(self.traits, rhs.traits);
2644 let properties = self.properties();
2645 let mut default_fp_state = FPState::default();
2646 let fp_state = fp_state.unwrap_or(&mut default_fp_state);
2647 let rounding_mode = rounding_mode.unwrap_or(fp_state.rounding_mode);
2648 let self_class = self.class();
2649 let mut rhs_class = rhs.class();
2650 if is_sub {
2651 rhs_class = -rhs_class;
2652 }
2653 match (self_class, rhs_class) {
2654 (FloatClass::SignalingNaN, _)
2655 | (FloatClass::QuietNaN, _)
2656 | (_, FloatClass::SignalingNaN)
2657 | (_, FloatClass::QuietNaN) => {
2658 if self_class.is_signaling_nan() || rhs_class.is_signaling_nan() {
2659 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
2660 }
2661 match properties
2662 .platform_properties
2663 .std_bin_ops_nan_propagation_mode
2664 .calculate_propagation_results(self_class, rhs_class)
2665 {
2666 BinaryNaNPropagationResults::First => self.to_quiet_nan(),
2667 BinaryNaNPropagationResults::Second => rhs.to_quiet_nan(),
2668 BinaryNaNPropagationResults::Canonical => {
2669 Self::quiet_nan_with_traits(self.traits.clone())
2670 }
2671 }
2672 }
2673 (FloatClass::NegativeInfinity, FloatClass::PositiveInfinity)
2674 | (FloatClass::PositiveInfinity, FloatClass::NegativeInfinity) => {
2675 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
2676 Self::quiet_nan_with_traits(self.traits.clone())
2677 }
2678 (FloatClass::PositiveInfinity, _) | (_, FloatClass::PositiveInfinity) => {
2679 Self::positive_infinity_with_traits(self.traits.clone())
2680 }
2681 (FloatClass::NegativeInfinity, _) | (_, FloatClass::NegativeInfinity) => {
2682 Self::negative_infinity_with_traits(self.traits.clone())
2683 }
2684 (FloatClass::PositiveZero, FloatClass::PositiveZero) => {
2685 Self::positive_zero_with_traits(self.traits.clone())
2686 }
2687 (FloatClass::NegativeZero, FloatClass::NegativeZero) => {
2688 Self::negative_zero_with_traits(self.traits.clone())
2689 }
2690 _ => {
2691 let lhs_value = self.to_real_algebraic_number().expect("known to be finite");
2692 let rhs_value = rhs.to_real_algebraic_number().expect("known to be finite");
2693 let result = if is_sub {
2694 lhs_value - rhs_value
2695 } else {
2696 lhs_value + rhs_value
2697 };
2698 if result.is_zero() {
2699 match rounding_mode {
2700 RoundingMode::TiesToEven
2701 | RoundingMode::TiesToAway
2702 | RoundingMode::TowardPositive
2703 | RoundingMode::TowardZero => {
2704 Self::positive_zero_with_traits(self.traits.clone())
2705 }
2706 RoundingMode::TowardNegative => {
2707 Self::negative_zero_with_traits(self.traits.clone())
2708 }
2709 }
2710 } else {
2711 Self::from_real_algebraic_number_with_traits(
2712 &result,
2713 Some(rounding_mode),
2714 Some(fp_state),
2715 self.traits.clone(),
2716 )
2717 }
2718 }
2719 }
2720 }
2721 pub fn add(
2723 &self,
2724 rhs: &Self,
2725 rounding_mode: Option<RoundingMode>,
2726 fp_state: Option<&mut FPState>,
2727 ) -> Self {
2728 self.add_or_sub(rhs, rounding_mode, fp_state, false)
2729 }
2730 pub fn sub(
2732 &self,
2733 rhs: &Self,
2734 rounding_mode: Option<RoundingMode>,
2735 fp_state: Option<&mut FPState>,
2736 ) -> Self {
2737 self.add_or_sub(rhs, rounding_mode, fp_state, true)
2738 }
2739 pub fn mul(
2741 &self,
2742 rhs: &Self,
2743 rounding_mode: Option<RoundingMode>,
2744 fp_state: Option<&mut FPState>,
2745 ) -> Self {
2746 assert_eq!(self.traits, rhs.traits);
2747 let properties = self.properties();
2748 let mut default_fp_state = FPState::default();
2749 let fp_state = fp_state.unwrap_or(&mut default_fp_state);
2750 let rounding_mode = rounding_mode.unwrap_or(fp_state.rounding_mode);
2751 let self_class = self.class();
2752 let rhs_class = rhs.class();
2753 let result_sign = self.sign() * rhs.sign();
2754 if self_class.is_nan() || rhs_class.is_nan() {
2755 if self_class.is_signaling_nan() || rhs_class.is_signaling_nan() {
2756 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
2757 }
2758 match properties
2759 .platform_properties
2760 .std_bin_ops_nan_propagation_mode
2761 .calculate_propagation_results(self_class, rhs_class)
2762 {
2763 BinaryNaNPropagationResults::First => self.to_quiet_nan(),
2764 BinaryNaNPropagationResults::Second => rhs.to_quiet_nan(),
2765 BinaryNaNPropagationResults::Canonical => {
2766 Self::quiet_nan_with_traits(self.traits.clone())
2767 }
2768 }
2769 } else if (self_class.is_infinity() && rhs_class.is_zero())
2770 || (self_class.is_zero() && rhs_class.is_infinity())
2771 {
2772 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
2773 Self::quiet_nan_with_traits(self.traits.clone())
2774 } else if self_class.is_zero() || rhs_class.is_zero() {
2775 Self::signed_zero_with_traits(result_sign, self.traits.clone())
2776 } else if self_class.is_infinity() || rhs_class.is_infinity() {
2777 Self::signed_infinity_with_traits(result_sign, self.traits.clone())
2778 } else {
2779 let lhs_value = self.to_real_algebraic_number().expect("known to be finite");
2780 let rhs_value = rhs.to_real_algebraic_number().expect("known to be finite");
2781 Self::from_real_algebraic_number_with_traits(
2782 &(lhs_value * rhs_value),
2783 Some(rounding_mode),
2784 Some(fp_state),
2785 self.traits.clone(),
2786 )
2787 }
2788 }
2789 pub fn div(
2791 &self,
2792 rhs: &Self,
2793 rounding_mode: Option<RoundingMode>,
2794 fp_state: Option<&mut FPState>,
2795 ) -> Self {
2796 assert_eq!(self.traits, rhs.traits);
2797 let properties = self.properties();
2798 let mut default_fp_state = FPState::default();
2799 let fp_state = fp_state.unwrap_or(&mut default_fp_state);
2800 let rounding_mode = rounding_mode.unwrap_or(fp_state.rounding_mode);
2801 let self_class = self.class();
2802 let rhs_class = rhs.class();
2803 let result_sign = self.sign() * rhs.sign();
2804 if self_class.is_nan() || rhs_class.is_nan() {
2805 if self_class.is_signaling_nan() || rhs_class.is_signaling_nan() {
2806 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
2807 }
2808 match properties
2809 .platform_properties
2810 .std_bin_ops_nan_propagation_mode
2811 .calculate_propagation_results(self_class, rhs_class)
2812 {
2813 BinaryNaNPropagationResults::First => self.to_quiet_nan(),
2814 BinaryNaNPropagationResults::Second => rhs.to_quiet_nan(),
2815 BinaryNaNPropagationResults::Canonical => {
2816 Self::quiet_nan_with_traits(self.traits.clone())
2817 }
2818 }
2819 } else if (self_class.is_infinity() && rhs_class.is_infinity())
2820 || (self_class.is_zero() && rhs_class.is_zero())
2821 {
2822 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
2823 Self::quiet_nan_with_traits(self.traits.clone())
2824 } else if self_class.is_zero() || rhs_class.is_infinity() {
2825 Self::signed_zero_with_traits(result_sign, self.traits.clone())
2826 } else if self_class.is_infinity() {
2827 Self::signed_infinity_with_traits(result_sign, self.traits.clone())
2828 } else if rhs_class.is_zero() {
2829 fp_state.status_flags |= StatusFlags::DIVISION_BY_ZERO;
2830 Self::signed_infinity_with_traits(result_sign, self.traits.clone())
2831 } else {
2832 let lhs_value = self.to_real_algebraic_number().expect("known to be finite");
2833 let rhs_value = rhs.to_real_algebraic_number().expect("known to be finite");
2834 Self::from_real_algebraic_number_with_traits(
2835 &(lhs_value / rhs_value),
2836 Some(rounding_mode),
2837 Some(fp_state),
2838 self.traits.clone(),
2839 )
2840 }
2841 }
2842 pub fn ieee754_remainder(
2844 &self,
2845 rhs: &Self,
2846 rounding_mode: Option<RoundingMode>,
2847 fp_state: Option<&mut FPState>,
2848 ) -> Self {
2849 assert_eq!(self.traits, rhs.traits);
2850 let properties = self.properties();
2851 let mut default_fp_state = FPState::default();
2852 let fp_state = fp_state.unwrap_or(&mut default_fp_state);
2853 let rounding_mode = rounding_mode.unwrap_or(fp_state.rounding_mode);
2854 let self_class = self.class();
2855 let rhs_class = rhs.class();
2856 if self_class.is_nan() || rhs_class.is_nan() {
2857 if self_class.is_signaling_nan() || rhs_class.is_signaling_nan() {
2858 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
2859 }
2860 match properties
2861 .platform_properties
2862 .std_bin_ops_nan_propagation_mode
2863 .calculate_propagation_results(self_class, rhs_class)
2864 {
2865 BinaryNaNPropagationResults::First => self.to_quiet_nan(),
2866 BinaryNaNPropagationResults::Second => rhs.to_quiet_nan(),
2867 BinaryNaNPropagationResults::Canonical => {
2868 Self::quiet_nan_with_traits(self.traits.clone())
2869 }
2870 }
2871 } else if self_class.is_infinity() || rhs_class.is_zero() {
2872 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
2873 Self::quiet_nan_with_traits(self.traits.clone())
2874 } else if rhs_class.is_infinity() {
2875 if self_class.is_zero() {
2876 Self::signed_zero_with_traits(self.sign(), self.traits.clone())
2877 } else {
2878 Self::from_real_algebraic_number_with_traits(
2879 &self.to_real_algebraic_number().expect("known to be finite"),
2880 Some(rounding_mode),
2881 Some(fp_state),
2882 self.traits.clone(),
2883 )
2884 }
2885 } else {
2886 let lhs_value = self.to_real_algebraic_number().expect("known to be finite");
2887 let rhs_value = rhs.to_real_algebraic_number().expect("known to be finite");
2888 let quotient = &lhs_value / &rhs_value;
2889 let floor_quotient = quotient.to_integer_floor();
2890 let fract_quotient = quotient - RealAlgebraicNumber::from(floor_quotient.clone());
2891 let selected_quotient = match fract_quotient.cmp(&Ratio::new(1, 2).into()) {
2892 Ordering::Less => floor_quotient,
2893 Ordering::Greater => floor_quotient + 1,
2894 Ordering::Equal => {
2895 if floor_quotient.is_even() {
2896 floor_quotient
2897 } else {
2898 floor_quotient + 1
2899 }
2900 }
2901 };
2902 let remainder = lhs_value - rhs_value * RealAlgebraicNumber::from(selected_quotient);
2903 if remainder.is_zero() {
2904 Self::signed_zero_with_traits(self.sign(), self.traits.clone())
2905 } else {
2906 Self::from_real_algebraic_number_with_traits(
2907 &remainder,
2908 Some(rounding_mode),
2909 Some(fp_state),
2910 self.traits.clone(),
2911 )
2912 }
2913 }
2914 }
2915 pub fn fused_mul_add(
2917 &self,
2918 factor: &Self,
2919 term: &Self,
2920 rounding_mode: Option<RoundingMode>,
2921 fp_state: Option<&mut FPState>,
2922 ) -> Self {
2923 assert_eq!(self.traits, factor.traits);
2924 assert_eq!(self.traits, term.traits);
2925 let properties = self.properties();
2926 let mut default_fp_state = FPState::default();
2927 let fp_state = fp_state.unwrap_or(&mut default_fp_state);
2928 let rounding_mode = rounding_mode.unwrap_or(fp_state.rounding_mode);
2929 let self_class = self.class();
2930 let factor_class = factor.class();
2931 let term_class = term.class();
2932 let product_sign = self.sign() * factor.sign();
2933 let is_infinity_times_zero = (self_class.is_infinity() && factor_class.is_zero())
2934 || (self_class.is_zero() && factor_class.is_infinity());
2935 if self_class.is_nan() || factor_class.is_nan() || term_class.is_nan() {
2936 if self_class.is_signaling_nan()
2937 || factor_class.is_signaling_nan()
2938 || term_class.is_signaling_nan()
2939 {
2940 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
2941 }
2942 if is_infinity_times_zero && term_class.is_quiet_nan() {
2943 match properties.platform_properties.fma_inf_zero_qnan_result {
2944 FMAInfZeroQNaNResult::CanonicalAndGenerateInvalid => {
2945 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
2946 return Self::quiet_nan_with_traits(self.traits.clone());
2947 }
2948 FMAInfZeroQNaNResult::PropagateAndGenerateInvalid => {
2949 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
2950 return term.clone();
2951 }
2952 FMAInfZeroQNaNResult::FollowNaNPropagationMode => {}
2953 }
2954 }
2955 match properties
2956 .platform_properties
2957 .fma_nan_propagation_mode
2958 .calculate_propagation_results(self_class, factor_class, term_class)
2959 {
2960 TernaryNaNPropagationResults::First => self.to_quiet_nan(),
2961 TernaryNaNPropagationResults::Second => factor.to_quiet_nan(),
2962 TernaryNaNPropagationResults::Third => term.to_quiet_nan(),
2963 TernaryNaNPropagationResults::Canonical => {
2964 Self::quiet_nan_with_traits(self.traits.clone())
2965 }
2966 }
2967 } else if is_infinity_times_zero
2968 || ((self_class.is_infinity() || factor_class.is_infinity())
2969 && term_class.is_infinity()
2970 && product_sign != term.sign())
2971 {
2972 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
2973 Self::quiet_nan_with_traits(self.traits.clone())
2974 } else if (self_class.is_zero() || factor_class.is_zero())
2975 && term_class.is_zero()
2976 && product_sign == term.sign()
2977 {
2978 Self::signed_zero_with_traits(product_sign, self.traits.clone())
2979 } else if term_class.is_infinity() {
2980 Self::signed_infinity_with_traits(term.sign(), self.traits.clone())
2981 } else if self_class.is_infinity() || factor_class.is_infinity() {
2982 Self::signed_infinity_with_traits(product_sign, self.traits.clone())
2983 } else {
2984 let self_value = self.to_real_algebraic_number().expect("known to be finite");
2985 let factor_value = factor
2986 .to_real_algebraic_number()
2987 .expect("known to be finite");
2988 let term_value = term.to_real_algebraic_number().expect("known to be finite");
2989 let result = self_value * factor_value + term_value;
2990 if result.is_zero() {
2991 match rounding_mode {
2992 RoundingMode::TiesToEven
2993 | RoundingMode::TiesToAway
2994 | RoundingMode::TowardPositive
2995 | RoundingMode::TowardZero => {
2996 Self::positive_zero_with_traits(self.traits.clone())
2997 }
2998 RoundingMode::TowardNegative => {
2999 Self::negative_zero_with_traits(self.traits.clone())
3000 }
3001 }
3002 } else {
3003 Self::from_real_algebraic_number_with_traits(
3004 &result,
3005 Some(rounding_mode),
3006 Some(fp_state),
3007 self.traits.clone(),
3008 )
3009 }
3010 }
3011 }
3012 pub fn round_to_integer(
3014 &self,
3015 exact: bool,
3016 rounding_mode: Option<RoundingMode>,
3017 fp_state: Option<&mut FPState>,
3018 ) -> Option<BigInt> {
3019 let mut default_fp_state = FPState::default();
3020 let fp_state = fp_state.unwrap_or(&mut default_fp_state);
3021 let rounding_mode = rounding_mode.unwrap_or(fp_state.rounding_mode);
3022 match self.class() {
3023 FloatClass::SignalingNaN => {
3024 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
3025 return None;
3026 }
3027 class if !class.is_finite() => {
3028 return None;
3029 }
3030 _ => {}
3031 }
3032 let value = self.to_real_algebraic_number().expect("known to be finite");
3033 let lower_value = value.to_integer_floor();
3034 let remainder = value - RealAlgebraicNumber::from(lower_value.clone());
3035 if remainder.is_zero() {
3036 return Some(lower_value);
3037 }
3038 if exact {
3039 fp_state.status_flags |= StatusFlags::INEXACT;
3040 }
3041 let upper_value = &lower_value + 1;
3042 match rounding_mode {
3043 RoundingMode::TiesToAway | RoundingMode::TiesToEven => {
3044 match remainder.cmp(&Ratio::new(1, 2).into()) {
3045 Ordering::Less => Some(lower_value),
3046 Ordering::Equal => {
3047 if rounding_mode == RoundingMode::TiesToEven {
3048 if lower_value.is_even() {
3049 Some(lower_value)
3050 } else {
3051 Some(upper_value)
3052 }
3053 } else {
3054 assert_eq!(rounding_mode, RoundingMode::TiesToAway);
3055 if lower_value.is_negative() {
3056 Some(lower_value)
3057 } else {
3058 Some(upper_value)
3059 }
3060 }
3061 }
3062 Ordering::Greater => Some(upper_value),
3063 }
3064 }
3065 RoundingMode::TowardPositive => Some(upper_value),
3066 RoundingMode::TowardNegative => Some(lower_value),
3067 RoundingMode::TowardZero => {
3068 if lower_value.is_negative() {
3069 Some(upper_value)
3070 } else {
3071 Some(lower_value)
3072 }
3073 }
3074 }
3075 }
3076 pub fn round_to_integral(
3078 &self,
3079 exact: bool,
3080 rounding_mode: Option<RoundingMode>,
3081 fp_state: Option<&mut FPState>,
3082 ) -> Self {
3083 let properties = self.properties();
3084 let mut default_fp_state = FPState::default();
3085 let fp_state = fp_state.unwrap_or(&mut default_fp_state);
3086 let rounding_mode = rounding_mode.unwrap_or(fp_state.rounding_mode);
3087 let class = self.class();
3088 if class.is_nan() {
3089 if class.is_signaling_nan() {
3090 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
3091 }
3092 match properties
3093 .platform_properties()
3094 .round_to_integral_nan_propagation_mode
3095 .calculate_propagation_results(class)
3096 {
3097 UnaryNaNPropagationResults::Canonical => {
3098 Self::quiet_nan_with_traits(self.traits.clone())
3099 }
3100 UnaryNaNPropagationResults::First => self.to_quiet_nan(),
3101 }
3102 } else if class.is_infinity() {
3103 Self::signed_infinity_with_traits(self.sign(), self.traits.clone())
3104 } else {
3105 let value = self
3106 .round_to_integer(exact, Some(rounding_mode), Some(fp_state))
3107 .expect("known to be finite");
3108 if value.is_zero() {
3109 Self::signed_zero_with_traits(self.sign(), self.traits.clone())
3110 } else {
3111 Self::from_real_algebraic_number_with_traits(
3112 &value.into(),
3113 Some(rounding_mode),
3114 Some(fp_state),
3115 self.traits.clone(),
3116 )
3117 }
3118 }
3119 }
3120 pub fn normalize(&mut self) {
3125 let properties = self.properties();
3126 if properties.has_implicit_leading_bit() {
3127 return;
3128 }
3129 let mut exponent_field = self.exponent_field();
3130 let exponent_zero_subnormal = properties.exponent_zero_subnormal();
3131 if exponent_field == properties.exponent_inf_nan()
3132 || exponent_field == exponent_zero_subnormal
3133 {
3134 return;
3135 }
3136 let mut mantissa_field = self.mantissa_field();
3137 if mantissa_field.is_zero() {
3138 self.set_exponent_field(exponent_zero_subnormal);
3139 return;
3140 }
3141 let mantissa_field_msb = Bits::one() << properties.fraction_width();
3142 while (mantissa_field.clone() & &mantissa_field_msb).is_zero() {
3143 if exponent_field == exponent_zero_subnormal {
3144 break;
3145 }
3146 exponent_field -= Bits::one();
3147 mantissa_field <<= 1;
3148 }
3149 self.set_exponent_field(exponent_field);
3150 self.set_mantissa_field(mantissa_field);
3151 }
3152 pub fn next_up_or_down(&self, up_or_down: UpOrDown, fp_state: Option<&mut FPState>) -> Self {
3154 let properties = self.properties();
3155 let mut default_fp_state = FPState::default();
3156 let fp_state = fp_state.unwrap_or(&mut default_fp_state);
3157 match (self.class(), up_or_down) {
3158 (class, _) if class.is_nan() => {
3159 if class.is_signaling_nan() {
3160 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
3161 }
3162 match properties
3163 .platform_properties()
3164 .next_up_or_down_nan_propagation_mode
3165 .calculate_propagation_results(class)
3166 {
3167 UnaryNaNPropagationResults::Canonical => {
3168 Self::quiet_nan_with_traits(self.traits.clone())
3169 }
3170 UnaryNaNPropagationResults::First => self.to_quiet_nan(),
3171 }
3172 }
3173 (FloatClass::NegativeInfinity, UpOrDown::Up)
3174 | (FloatClass::PositiveInfinity, UpOrDown::Down) => {
3175 Self::signed_max_normal_with_traits(self.sign(), self.traits.clone())
3176 }
3177 (FloatClass::NegativeInfinity, UpOrDown::Down)
3178 | (FloatClass::PositiveInfinity, UpOrDown::Up) => self.clone(),
3179 (class, _) if class.is_zero() => {
3180 Self::signed_min_subnormal_with_traits(up_or_down.into(), self.traits.clone())
3181 }
3182 _ => {
3183 let mut retval = self.clone();
3184 retval.normalize();
3185 let mantissa = self.mantissa_field();
3186 let is_larger_magnitude = Sign::from(up_or_down) == self.sign();
3187 if is_larger_magnitude {
3188 if mantissa == properties.mantissa_field_max() {
3189 let exponent = self.exponent_field();
3190 if exponent == properties.exponent_max_normal() {
3191 Self::signed_infinity_with_traits(self.sign(), self.traits.clone())
3192 } else {
3193 let mut retval = self.clone();
3194 retval.set_mantissa_field(properties.mantissa_field_normal_min());
3195 retval.set_exponent_field(exponent + Bits::one());
3196 retval
3197 }
3198 } else {
3199 let mut retval = self.clone();
3200 retval.set_mantissa_field(mantissa + Bits::one());
3201 retval
3202 }
3203 } else if mantissa <= properties.mantissa_field_normal_min() {
3204 let exponent = self.exponent_field();
3205 if exponent == properties.exponent_zero_subnormal() {
3206 assert!(!mantissa.is_zero());
3207 let mut retval = self.clone();
3208 retval.set_mantissa_field(mantissa - Bits::one());
3209 retval
3210 } else {
3211 let mut retval = self.clone();
3212 retval.set_mantissa_field(properties.mantissa_field_max());
3213 retval.set_exponent_field(exponent - Bits::one());
3214 retval
3215 }
3216 } else {
3217 let mut retval = self.clone();
3218 retval.set_mantissa_field(mantissa - Bits::one());
3219 retval
3220 }
3221 }
3222 }
3223 }
3224 pub fn next_up(&self, fp_state: Option<&mut FPState>) -> Self {
3226 self.next_up_or_down(UpOrDown::Up, fp_state)
3227 }
3228 pub fn next_down(&self, fp_state: Option<&mut FPState>) -> Self {
3230 self.next_up_or_down(UpOrDown::Down, fp_state)
3231 }
3232 pub fn log_b(&self, fp_state: Option<&mut FPState>) -> Option<BigInt> {
3234 let mut default_fp_state = FPState::default();
3235 let fp_state = fp_state.unwrap_or(&mut default_fp_state);
3236 let properties = self.properties();
3237 let class = self.class();
3238 if !class.is_finite() || class.is_zero() {
3239 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
3240 return None;
3241 }
3242 let exponent_field: BigInt = self.exponent_field().into();
3243 let exponent_bias: BigInt = properties.exponent_bias::<Bits>().into();
3244 let exponent_zero_subnormal: BigInt = properties.exponent_zero_subnormal::<Bits>().into();
3245 let mut exponent =
3246 if properties.has_implicit_leading_bit() && exponent_field != exponent_zero_subnormal {
3247 return Some(exponent_field - exponent_bias);
3248 } else if exponent_field == exponent_zero_subnormal {
3249 properties.exponent_min_normal::<Bits>().into() - exponent_bias
3250 } else {
3251 exponent_field - exponent_bias
3252 };
3253 let mut mantissa = self.mantissa_field();
3254 while (mantissa.clone() >> properties.fraction_width()).is_zero() {
3255 mantissa <<= 1;
3256 exponent -= 1;
3257 }
3258 Some(exponent)
3259 }
3260 pub fn scale_b(
3262 &self,
3263 mut scale: BigInt,
3264 rounding_mode: Option<RoundingMode>,
3265 fp_state: Option<&mut FPState>,
3266 ) -> Self {
3267 let mut default_fp_state = FPState::default();
3268 let fp_state = fp_state.unwrap_or(&mut default_fp_state);
3269 let rounding_mode = rounding_mode.unwrap_or(fp_state.rounding_mode);
3270 let properties = self.properties();
3271 let class = self.class();
3272 if class.is_nan() {
3273 if class.is_signaling_nan() {
3274 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
3275 }
3276 match properties
3277 .platform_properties()
3278 .scale_b_nan_propagation_mode
3279 .calculate_propagation_results(class)
3280 {
3281 UnaryNaNPropagationResults::Canonical => {
3282 Self::quiet_nan_with_traits(self.traits.clone())
3283 }
3284 UnaryNaNPropagationResults::First => self.to_quiet_nan(),
3285 }
3286 } else if class.is_infinity() {
3287 Self::signed_infinity_with_traits(self.sign(), self.traits.clone())
3288 } else if class.is_zero() {
3289 Self::signed_zero_with_traits(self.sign(), self.traits.clone())
3290 } else {
3291 let exponent_max_normal: BigInt = properties.exponent_max_normal::<Bits>().into();
3292 let exponent_min_normal: BigInt = properties.exponent_min_normal::<Bits>().into();
3293 let scale_limit: BigInt =
3294 (exponent_max_normal - exponent_min_normal + properties.fraction_width() + 1) * 2;
3295 scale = scale.max(-&scale_limit);
3296 scale = scale.min(scale_limit);
3297 let mut value = self.to_real_algebraic_number().expect("known to be finite");
3298 if scale.is_positive() {
3299 value *= RealAlgebraicNumber::from(
3300 BigInt::one() << scale.to_usize().expect("rhs won't fit in usize"),
3301 );
3302 } else {
3303 value /= RealAlgebraicNumber::from(
3304 BigInt::one() << (-scale).to_usize().expect("-rhs won't fit in usize"),
3305 );
3306 }
3307 Self::from_real_algebraic_number_with_traits(
3308 &value,
3309 Some(rounding_mode),
3310 Some(fp_state),
3311 self.traits.clone(),
3312 )
3313 }
3314 }
3315 pub fn sqrt(
3317 &self,
3318 rounding_mode: Option<RoundingMode>,
3319 fp_state: Option<&mut FPState>,
3320 ) -> Self {
3321 let properties = self.properties();
3322 let mut default_fp_state = FPState::default();
3323 let fp_state = fp_state.unwrap_or(&mut default_fp_state);
3324 let rounding_mode = rounding_mode.unwrap_or(fp_state.rounding_mode);
3325 let class = self.class();
3326 if class.is_nan() {
3327 if class.is_signaling_nan() {
3328 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
3329 }
3330 match properties
3331 .platform_properties()
3332 .sqrt_nan_propagation_mode
3333 .calculate_propagation_results(class)
3334 {
3335 UnaryNaNPropagationResults::Canonical => {
3336 Self::quiet_nan_with_traits(self.traits.clone())
3337 }
3338 UnaryNaNPropagationResults::First => self.to_quiet_nan(),
3339 }
3340 } else if class.is_zero() {
3341 Self::signed_zero_with_traits(self.sign(), self.traits.clone())
3342 } else if class.is_positive_infinity() {
3343 Self::positive_infinity_with_traits(self.traits.clone())
3344 } else if self.sign() == Sign::Negative {
3345 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
3346 Self::quiet_nan_with_traits(self.traits.clone())
3347 } else {
3348 let value = self.to_real_algebraic_number().expect("known to be finite");
3349 Self::from_real_algebraic_number_with_traits(
3350 &value.pow((1, 2)),
3351 Some(rounding_mode),
3352 Some(fp_state),
3353 self.traits.clone(),
3354 )
3355 }
3356 }
3357 pub fn convert_from_float_with_traits<SrcFT: FloatTraits>(
3359 src: &Float<SrcFT>,
3360 rounding_mode: Option<RoundingMode>,
3361 fp_state: Option<&mut FPState>,
3362 traits: FT,
3363 ) -> Self {
3364 let src_properties = src.properties();
3365 let dest_properties = traits.properties();
3366 let mut default_fp_state = FPState::default();
3367 let fp_state = fp_state.unwrap_or(&mut default_fp_state);
3368 let rounding_mode = rounding_mode.unwrap_or(fp_state.rounding_mode);
3369 let class = src.class();
3370 if class.is_nan() {
3371 if class.is_signaling_nan() {
3372 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
3373 }
3374 let mut retval = Self::quiet_nan_with_traits(traits);
3375 match dest_properties
3376 .platform_properties
3377 .float_to_float_conversion_nan_propagation_mode
3378 {
3379 FloatToFloatConversionNaNPropagationMode::AlwaysCanonical => retval,
3380 FloatToFloatConversionNaNPropagationMode::RetainMostSignificantBits => {
3381 let mut mantissa: BigInt = src.mantissa_field().into();
3382 let retained_bits = src_properties
3383 .mantissa_width()
3384 .min(dest_properties.mantissa_width());
3385 mantissa >>= src_properties.mantissa_width() - retained_bits;
3386 mantissa <<= dest_properties.mantissa_width() - retained_bits;
3387 retval.set_mantissa_field(
3388 Bits::from_bigint(&mantissa).expect("mantissa doesn't fit"),
3389 );
3390 retval.to_quiet_nan()
3391 }
3392 }
3393 } else if class.is_infinity() {
3394 Self::signed_infinity_with_traits(src.sign(), traits)
3395 } else if class.is_zero() {
3396 Self::signed_zero_with_traits(src.sign(), traits)
3397 } else {
3398 let value = src.to_real_algebraic_number().expect("known to be finite");
3399 Self::from_real_algebraic_number_with_traits(
3400 &value,
3401 Some(rounding_mode),
3402 Some(fp_state),
3403 traits,
3404 )
3405 }
3406 }
3407 pub fn convert_from_float<SrcFT: FloatTraits>(
3409 src: &Float<SrcFT>,
3410 rounding_mode: Option<RoundingMode>,
3411 fp_state: Option<&mut FPState>,
3412 ) -> Self
3413 where
3414 FT: Default,
3415 {
3416 Self::convert_from_float_with_traits(src, rounding_mode, fp_state, FT::default())
3417 }
3418 pub fn convert_to_float_with_traits<DestFT: FloatTraits>(
3420 &self,
3421 rounding_mode: Option<RoundingMode>,
3422 fp_state: Option<&mut FPState>,
3423 traits: DestFT,
3424 ) -> Float<DestFT> {
3425 Float::convert_from_float_with_traits(self, rounding_mode, fp_state, traits)
3426 }
3427 pub fn convert_to_float<DestFT: FloatTraits + Default>(
3429 &self,
3430 rounding_mode: Option<RoundingMode>,
3431 fp_state: Option<&mut FPState>,
3432 ) -> Float<DestFT> {
3433 Float::convert_from_float(self, rounding_mode, fp_state)
3434 }
3435 pub fn neg_assign(&mut self) {
3438 self.toggle_sign();
3439 }
3440 pub fn neg(&self) -> Self {
3442 let mut retval = self.clone();
3443 retval.neg_assign();
3444 retval
3445 }
3446 pub fn abs_assign(&mut self) {
3449 self.set_sign(Sign::Positive);
3450 }
3451 pub fn abs(&self) -> Self {
3453 let mut retval = self.clone();
3454 retval.abs_assign();
3455 retval
3456 }
3457 pub fn copy_sign_assign<FT2: FloatTraits>(&mut self, sign_src: &Float<FT2>) {
3459 self.set_sign(sign_src.sign());
3460 }
3461 pub fn copy_sign<FT2: FloatTraits>(&self, sign_src: &Float<FT2>) -> Self {
3463 let mut retval = self.clone();
3464 retval.set_sign(sign_src.sign());
3465 retval
3466 }
3467 pub fn compare(
3469 &self,
3470 rhs: &Self,
3471 quiet: bool,
3472 fp_state: Option<&mut FPState>,
3473 ) -> Option<Ordering> {
3474 let self_class = self.class();
3475 let rhs_class = rhs.class();
3476 if self_class.is_nan() || rhs_class.is_nan() {
3477 if !quiet || self_class.is_signaling_nan() || rhs_class.is_signaling_nan() {
3478 if let Some(fp_state) = fp_state {
3479 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
3480 }
3481 }
3482 None
3483 } else if self_class.is_infinity() || rhs_class.is_infinity() {
3484 if self_class == rhs_class {
3485 Some(Ordering::Equal)
3486 } else if self_class.is_positive_infinity() || rhs_class.is_negative_infinity() {
3487 Some(Ordering::Greater)
3488 } else {
3489 Some(Ordering::Less)
3490 }
3491 } else {
3492 Some(
3493 self.to_ratio()
3494 .expect("known to be finite")
3495 .cmp(&rhs.to_ratio().expect("known to be finite")),
3496 )
3497 }
3498 }
3499 pub fn compare_quiet(&self, rhs: &Self, fp_state: Option<&mut FPState>) -> Option<Ordering> {
3501 self.compare(rhs, true, fp_state)
3502 }
3503 pub fn compare_signaling(
3505 &self,
3506 rhs: &Self,
3507 fp_state: Option<&mut FPState>,
3508 ) -> Option<Ordering> {
3509 self.compare(rhs, false, fp_state)
3510 }
3511 impl_from_int_type!(from_bigint_with_traits, from_bigint, BigInt);
3512 impl_from_int_type!(from_biguint_with_traits, from_biguint, BigUint);
3513 impl_from_int_type!(from_u8_with_traits, from_u8, u8);
3514 impl_from_int_type!(from_u16_with_traits, from_u16, u16);
3515 impl_from_int_type!(from_u32_with_traits, from_u32, u32);
3516 impl_from_int_type!(from_u64_with_traits, from_u64, u64);
3517 impl_from_int_type!(from_u128_with_traits, from_u128, u128);
3518 impl_from_int_type!(from_usize_with_traits, from_usize, usize);
3519 impl_from_int_type!(from_i8_with_traits, from_i8, i8);
3520 impl_from_int_type!(from_i16_with_traits, from_i16, i16);
3521 impl_from_int_type!(from_i32_with_traits, from_i32, i32);
3522 impl_from_int_type!(from_i64_with_traits, from_i64, i64);
3523 impl_from_int_type!(from_i128_with_traits, from_i128, i128);
3524 impl_from_int_type!(from_isize_with_traits, from_isize, isize);
3525 impl_to_int_type!(to_bigint, into, BigInt);
3526 impl_to_int_type!(to_biguint, to_biguint, BigUint);
3527 impl_to_int_type!(to_u8, to_u8, u8);
3528 impl_to_int_type!(to_u16, to_u16, u16);
3529 impl_to_int_type!(to_u32, to_u32, u32);
3530 impl_to_int_type!(to_u64, to_u64, u64);
3531 impl_to_int_type!(to_u128, to_u128, u128);
3532 impl_to_int_type!(to_usize, to_usize, usize);
3533 impl_to_int_type!(to_i8, to_i8, i8);
3534 impl_to_int_type!(to_i16, to_i16, i16);
3535 impl_to_int_type!(to_i32, to_i32, i32);
3536 impl_to_int_type!(to_i64, to_i64, i64);
3537 impl_to_int_type!(to_i128, to_i128, i128);
3538 impl_to_int_type!(to_isize, to_isize, isize);
3539 pub fn rsqrt(
3541 &self,
3542 rounding_mode: Option<RoundingMode>,
3543 fp_state: Option<&mut FPState>,
3544 ) -> Self {
3545 let properties = self.properties();
3546 let mut default_fp_state = FPState::default();
3547 let fp_state = fp_state.unwrap_or(&mut default_fp_state);
3548 let rounding_mode = rounding_mode.unwrap_or(fp_state.rounding_mode);
3549 let class = self.class();
3550 if class.is_nan() {
3551 if class.is_signaling_nan() {
3552 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
3553 }
3554 match properties
3555 .platform_properties()
3556 .rsqrt_nan_propagation_mode
3557 .calculate_propagation_results(class)
3558 {
3559 UnaryNaNPropagationResults::Canonical => {
3560 Self::quiet_nan_with_traits(self.traits.clone())
3561 }
3562 UnaryNaNPropagationResults::First => self.to_quiet_nan(),
3563 }
3564 } else if class.is_zero() {
3565 fp_state.status_flags |= StatusFlags::DIVISION_BY_ZERO;
3566 Self::signed_infinity_with_traits(self.sign(), self.traits.clone())
3567 } else if class.is_positive_infinity() {
3568 Self::positive_zero_with_traits(self.traits.clone())
3569 } else if self.sign() == Sign::Negative {
3570 fp_state.status_flags |= StatusFlags::INVALID_OPERATION;
3571 Self::quiet_nan_with_traits(self.traits.clone())
3572 } else {
3573 let value = self.to_real_algebraic_number().expect("known to be finite");
3574 Self::from_real_algebraic_number_with_traits(
3575 &value.recip().pow((1, 2)),
3576 Some(rounding_mode),
3577 Some(fp_state),
3578 self.traits.clone(),
3579 )
3580 }
3581 }
3582}
3583
3584impl<Bits: FloatBitsType, FT: FloatTraits<Bits = Bits>> fmt::Debug for Float<FT> {
3585 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3586 let properties = self.properties();
3587 let mut debug_struct = f.debug_struct("Float");
3588 debug_struct.field("traits", &self.traits);
3589 debug_struct.field(
3590 "bits",
3591 &format_args!(
3592 "0x{value:0width$X}",
3593 value = self.bits(),
3594 width = (properties.width() + 3) / 4
3595 ),
3596 );
3597 if properties.has_sign_bit() {
3598 debug_struct.field("sign", &self.sign());
3599 }
3600 debug_struct.field(
3601 "exponent_field",
3602 &format_args!(
3603 "0x{value:0width$X}",
3604 value = self.exponent_field(),
3605 width = (properties.exponent_width() + 3) / 4
3606 ),
3607 );
3608 debug_struct.field(
3609 "mantissa_field",
3610 &format_args!(
3611 "0x{value:0width$X}",
3612 value = self.mantissa_field(),
3613 width = (properties.mantissa_width() + 3) / 4
3614 ),
3615 );
3616 debug_struct.field("class", &self.class());
3617 debug_struct.finish()
3618 }
3619}
3620
3621pub type F16 = Float<F16Traits>;
3623pub type F32 = Float<F32Traits>;
3625pub type F64 = Float<F64Traits>;
3627pub type F128 = Float<F128Traits>;
3629
3630pub type F16WithPlatformProperties = Float<F16WithPlatformPropertiesTraits>;
3632pub type F32WithPlatformProperties = Float<F32WithPlatformPropertiesTraits>;
3634pub type F64WithPlatformProperties = Float<F64WithPlatformPropertiesTraits>;
3636pub type F128WithPlatformProperties = Float<F128WithPlatformPropertiesTraits>;
3638
3639#[derive(Clone, Debug)]
3641pub struct DynamicFloat {
3642 pub fp_state: FPState,
3644 pub value: Float<FloatProperties>,
3646 _private: (),
3647}
3648
3649impl Deref for DynamicFloat {
3650 type Target = Float<FloatProperties>;
3651 fn deref(&self) -> &Float<FloatProperties> {
3653 &self.value
3654 }
3655}
3656
3657impl DerefMut for DynamicFloat {
3658 fn deref_mut(&mut self) -> &mut Float<FloatProperties> {
3660 &mut self.value
3661 }
3662}
3663
3664impl From<Float<FloatProperties>> for DynamicFloat {
3665 fn from(value: Float<FloatProperties>) -> Self {
3666 Self {
3667 fp_state: FPState::default(),
3668 value,
3669 _private: (),
3670 }
3671 }
3672}
3673
3674impl From<DynamicFloat> for Float<FloatProperties> {
3675 fn from(value: DynamicFloat) -> Self {
3676 value.value
3677 }
3678}
3679
3680macro_rules! impl_dynamic_float_fn {
3681 (
3682 $(#[doc = $doc:literal])+
3683 $fn_name:ident, $called_fn_name:ident,
3684 (&self$(, $args:ident: $arg_types:ty)*)
3685 ) => {
3686 impl DynamicFloat {
3687 $(#[doc = $doc])+
3688 pub fn $fn_name(
3689 &self,
3690 $($args: $arg_types,)*
3691 ) -> Self {
3692 let mut fp_state = self.fp_state;
3693 let value = self
3694 .value
3695 .$called_fn_name($($args,)* Some(&mut fp_state));
3696 Self {
3697 fp_state,
3698 value,
3699 _private: (),
3700 }
3701 }
3702 }
3703 };
3704 (
3705 $(#[doc = $doc:literal])+
3706 $fn_name:ident, $checked_fn_name:ident, $called_fn_name:ident,
3707 (&self$(, $before_args:ident: $before_arg_types:ty)*),
3708 ($($float_args:ident: &Self),*),
3709 ($($after_args:ident: $after_arg_types:ty),*)
3710 ) => {
3711 impl DynamicFloat {
3712 $(#[doc = $doc])+
3713 pub fn $fn_name(
3714 &self,
3715 $($before_args: $before_args_type,)*
3716 $($float_args: &Self,)*
3717 $($after_args: $after_arg_types,)*
3718 ) -> Self {
3719 let mut fp_state = self.fp_state;
3720 $(fp_state.merge_assign($float_args.fp_state);)*
3721 let value = self
3722 .value
3723 .$called_fn_name($($before_args,)* $(&$float_args.value,)* $($after_args,)* Some(&mut fp_state));
3724 Self {
3725 fp_state,
3726 value,
3727 _private: (),
3728 }
3729 }
3730 $(#[doc = $doc])+
3731 pub fn $checked_fn_name(
3732 &self,
3733 $($before_args: $before_args_type,)*
3734 $($float_args: &Self,)*
3735 $($after_args: $after_arg_types,)*
3736 ) -> Result<Self, FPStateMergeFailed> {
3737 let mut fp_state = self.fp_state;
3738 $(fp_state.checked_merge_assign($float_args.fp_state)?;)*
3739 let value = self
3740 .value
3741 .$called_fn_name($($before_args,)* $(&$float_args.value,)* $($after_args,)* Some(&mut fp_state));
3742 Ok(Self {
3743 fp_state,
3744 value,
3745 _private: (),
3746 })
3747 }
3748 }
3749 };
3750}
3751
3752macro_rules! impl_dynamic_float_from_int_type {
3753 ($from_int_with_traits:ident, $from_int:ident, $int:ident) => {
3754 impl DynamicFloat {
3755 pub fn $from_int(
3758 value: $int,
3759 rounding_mode: Option<RoundingMode>,
3760 fp_state: Option<FPState>,
3761 properties: FloatProperties,
3762 ) -> Self {
3763 let mut fp_state = fp_state.unwrap_or_default();
3764 let value = Float::$from_int_with_traits(
3765 value,
3766 rounding_mode,
3767 Some(&mut fp_state),
3768 properties,
3769 );
3770 Self {
3771 fp_state,
3772 value,
3773 _private: (),
3774 }
3775 }
3776 }
3777 };
3778}
3779
3780macro_rules! impl_dynamic_float_to_int_type {
3781 ($name:ident, $int:ident) => {
3782 impl DynamicFloat {
3783 pub fn $name(
3785 &self,
3786 exact: bool,
3787 rounding_mode: Option<RoundingMode>,
3788 ) -> (Option<$int>, FPState) {
3789 let mut fp_state = self.fp_state;
3790 let result = self.value.$name(exact, rounding_mode, Some(&mut fp_state));
3791 (result, fp_state)
3792 }
3793 }
3794 };
3795}
3796
3797impl DynamicFloat {
3798 pub fn new(properties: FloatProperties) -> Self {
3800 Self {
3801 fp_state: FPState::default(),
3802 value: Float::from_bits_and_traits(BigUint::zero(), properties),
3803 _private: (),
3804 }
3805 }
3806 pub fn from_bits(bits: BigUint, properties: FloatProperties) -> Option<Self> {
3808 if bits <= properties.overall_mask::<BigUint>() {
3809 Some(Self {
3810 fp_state: FPState::default(),
3811 value: Float::from_bits_and_traits(bits, properties),
3812 _private: (),
3813 })
3814 } else {
3815 None
3816 }
3817 }
3818 pub fn into_bits(self) -> BigUint {
3820 self.value.into_bits()
3821 }
3822 pub fn positive_zero(properties: FloatProperties) -> Self {
3824 Float::positive_zero_with_traits(properties).into()
3825 }
3826 pub fn negative_zero(properties: FloatProperties) -> Self {
3828 Float::negative_zero_with_traits(properties).into()
3829 }
3830 pub fn signed_zero(sign: Sign, properties: FloatProperties) -> Self {
3832 Float::signed_zero_with_traits(sign, properties).into()
3833 }
3834 pub fn positive_infinity(properties: FloatProperties) -> Self {
3836 Float::positive_infinity_with_traits(properties).into()
3837 }
3838 pub fn negative_infinity(properties: FloatProperties) -> Self {
3840 Float::negative_infinity_with_traits(properties).into()
3841 }
3842 pub fn signed_infinity(sign: Sign, properties: FloatProperties) -> Self {
3844 Float::signed_infinity_with_traits(sign, properties).into()
3845 }
3846 pub fn quiet_nan(properties: FloatProperties) -> Self {
3848 Float::quiet_nan_with_traits(properties).into()
3849 }
3850 pub fn signaling_nan(properties: FloatProperties) -> Self {
3852 Float::signaling_nan_with_traits(properties).into()
3853 }
3854 pub fn into_quiet_nan(self) -> Self {
3856 let Self {
3857 fp_state,
3858 value,
3859 _private: _,
3860 } = self;
3861 Self {
3862 fp_state,
3863 value: value.into_quiet_nan(),
3864 _private: (),
3865 }
3866 }
3867 pub fn to_quiet_nan(&self) -> Self {
3869 let Self {
3870 fp_state,
3871 ref value,
3872 _private: _,
3873 } = *self;
3874 Self {
3875 fp_state,
3876 value: value.to_quiet_nan(),
3877 _private: (),
3878 }
3879 }
3880 pub fn signed_max_normal(sign: Sign, properties: FloatProperties) -> Self {
3882 Float::signed_max_normal_with_traits(sign, properties).into()
3883 }
3884 pub fn signed_min_subnormal(sign: Sign, properties: FloatProperties) -> Self {
3886 Float::signed_min_subnormal_with_traits(sign, properties).into()
3887 }
3888 pub fn from_real_algebraic_number(
3891 value: &RealAlgebraicNumber,
3892 rounding_mode: Option<RoundingMode>,
3893 fp_state: Option<FPState>,
3894 properties: FloatProperties,
3895 ) -> Self {
3896 let mut fp_state = fp_state.unwrap_or_default();
3897 let value = Float::from_real_algebraic_number_with_traits(
3898 value,
3899 rounding_mode,
3900 Some(&mut fp_state),
3901 properties,
3902 );
3903 Self {
3904 fp_state,
3905 value,
3906 _private: (),
3907 }
3908 }
3909}
3910impl_dynamic_float_fn!(
3911 add_with_rounding_mode,
3913 checked_add_with_rounding_mode,
3914 add,
3915 (&self),
3916 (rhs: &Self),
3917 (rounding_mode: Option<RoundingMode>)
3918);
3919impl_dynamic_float_fn!(
3920 sub_with_rounding_mode,
3922 checked_sub_with_rounding_mode,
3923 sub,
3924 (&self),
3925 (rhs: &Self),
3926 (rounding_mode: Option<RoundingMode>)
3927);
3928impl_dynamic_float_fn!(
3929 mul_with_rounding_mode,
3931 checked_mul_with_rounding_mode,
3932 mul,
3933 (&self),
3934 (rhs: &Self),
3935 (rounding_mode: Option<RoundingMode>)
3936);
3937impl_dynamic_float_fn!(
3938 div_with_rounding_mode,
3940 checked_div_with_rounding_mode,
3941 div,
3942 (&self),
3943 (rhs: &Self),
3944 (rounding_mode: Option<RoundingMode>)
3945);
3946impl_dynamic_float_fn!(
3947 ieee754_remainder,
3949 checked_ieee754_remainder,
3950 ieee754_remainder,
3951 (&self),
3952 (rhs: &Self),
3953 (rounding_mode: Option<RoundingMode>)
3954);
3955impl_dynamic_float_fn!(
3956 fused_mul_add,
3958 checked_fused_mul_add,
3959 fused_mul_add,
3960 (&self),
3961 (factor: &Self, term: &Self),
3962 (rounding_mode: Option<RoundingMode>)
3963);
3964
3965impl DynamicFloat {
3966 pub fn round_to_integer(
3968 &self,
3969 exact: bool,
3970 rounding_mode: Option<RoundingMode>,
3971 ) -> (Option<BigInt>, FPState) {
3972 let mut fp_state = self.fp_state;
3973 let value = self
3974 .value
3975 .round_to_integer(exact, rounding_mode, Some(&mut fp_state));
3976 (value, fp_state)
3977 }
3978}
3979
3980impl_dynamic_float_fn!(
3981 round_to_integral,
3983 round_to_integral,
3984 (&self, exact: bool, rounding_mode: Option<RoundingMode>)
3985);
3986impl_dynamic_float_fn!(
3987 next_up_or_down,
3989 next_up_or_down,
3990 (&self, up_or_down: UpOrDown)
3991);
3992impl_dynamic_float_fn!(
3993 next_up,
3995 next_up,
3996 (&self)
3997);
3998impl_dynamic_float_fn!(
3999 next_down,
4001 next_down,
4002 (&self)
4003);
4004
4005impl DynamicFloat {
4006 pub fn log_b(&self) -> (Option<BigInt>, FPState) {
4008 let mut fp_state = self.fp_state;
4009 let value = self.value.log_b(Some(&mut fp_state));
4010 (value, fp_state)
4011 }
4012}
4013
4014impl_dynamic_float_fn!(
4015 scale_b,
4017 scale_b,
4018 (&self, scale: BigInt, rounding_mode: Option<RoundingMode>)
4019);
4020impl_dynamic_float_fn!(
4021 sqrt,
4023 sqrt,
4024 (&self, rounding_mode: Option<RoundingMode>)
4025);
4026
4027impl DynamicFloat {
4028 pub fn convert_from_dynamic_float(
4030 src: &Self,
4031 rounding_mode: Option<RoundingMode>,
4032 properties: FloatProperties,
4033 ) -> Self {
4034 let mut fp_state = src.fp_state;
4035 let value = Float::convert_from_float_with_traits(
4036 &src.value,
4037 rounding_mode,
4038 Some(&mut fp_state),
4039 properties,
4040 );
4041 Self {
4042 fp_state,
4043 value,
4044 _private: (),
4045 }
4046 }
4047 pub fn convert_from_float<SrcFT: FloatTraits>(
4049 src: &Float<SrcFT>,
4050 rounding_mode: Option<RoundingMode>,
4051 fp_state: Option<FPState>,
4052 properties: FloatProperties,
4053 ) -> Self {
4054 let mut fp_state = fp_state.unwrap_or_default();
4055 let value = Float::convert_from_float_with_traits(
4056 src,
4057 rounding_mode,
4058 Some(&mut fp_state),
4059 properties,
4060 );
4061 Self {
4062 fp_state,
4063 value,
4064 _private: (),
4065 }
4066 }
4067 pub fn convert_to_dynamic_float(
4069 &self,
4070 rounding_mode: Option<RoundingMode>,
4071 properties: FloatProperties,
4072 ) -> Self {
4073 Self::convert_from_dynamic_float(self, rounding_mode, properties)
4074 }
4075 pub fn abs(&self) -> Self {
4077 let mut retval = self.clone();
4078 retval.abs_assign();
4079 retval
4080 }
4081 pub fn copy_sign<FT2: FloatTraits>(&self, sign_src: &Float<FT2>) -> Self {
4083 let mut retval = self.clone();
4084 retval.set_sign(sign_src.sign());
4085 retval
4086 }
4087 pub fn compare(&self, rhs: &Self, quiet: bool) -> (Option<Ordering>, FPState) {
4089 let mut fp_state = self.fp_state;
4090 fp_state.merge_assign(rhs.fp_state);
4091 let result = self.value.compare(&rhs.value, quiet, Some(&mut fp_state));
4092 (result, fp_state)
4093 }
4094 pub fn checked_compare(
4096 &self,
4097 rhs: &Self,
4098 quiet: bool,
4099 ) -> Result<(Option<Ordering>, FPState), FPStateMergeFailed> {
4100 let mut fp_state = self.fp_state;
4101 fp_state.checked_merge_assign(rhs.fp_state)?;
4102 let result = self.value.compare(&rhs.value, quiet, Some(&mut fp_state));
4103 Ok((result, fp_state))
4104 }
4105 pub fn compare_quiet(&self, rhs: &Self) -> (Option<Ordering>, FPState) {
4107 let mut fp_state = self.fp_state;
4108 fp_state.merge_assign(rhs.fp_state);
4109 let result = self.value.compare_quiet(&rhs.value, Some(&mut fp_state));
4110 (result, fp_state)
4111 }
4112 pub fn checked_compare_quiet(
4114 &self,
4115 rhs: &Self,
4116 ) -> Result<(Option<Ordering>, FPState), FPStateMergeFailed> {
4117 let mut fp_state = self.fp_state;
4118 fp_state.checked_merge_assign(rhs.fp_state)?;
4119 let result = self.value.compare_quiet(&rhs.value, Some(&mut fp_state));
4120 Ok((result, fp_state))
4121 }
4122 pub fn compare_signaling(&self, rhs: &Self) -> (Option<Ordering>, FPState) {
4124 let mut fp_state = self.fp_state;
4125 fp_state.merge_assign(rhs.fp_state);
4126 let result = self
4127 .value
4128 .compare_signaling(&rhs.value, Some(&mut fp_state));
4129 (result, fp_state)
4130 }
4131 pub fn checked_compare_signaling(
4133 &self,
4134 rhs: &Self,
4135 ) -> Result<(Option<Ordering>, FPState), FPStateMergeFailed> {
4136 let mut fp_state = self.fp_state;
4137 fp_state.checked_merge_assign(rhs.fp_state)?;
4138 let result = self
4139 .value
4140 .compare_signaling(&rhs.value, Some(&mut fp_state));
4141 Ok((result, fp_state))
4142 }
4143}
4144
4145impl_dynamic_float_from_int_type!(from_bigint_with_traits, from_bigint, BigInt);
4146impl_dynamic_float_from_int_type!(from_biguint_with_traits, from_biguint, BigUint);
4147impl_dynamic_float_from_int_type!(from_u8_with_traits, from_u8, u8);
4148impl_dynamic_float_from_int_type!(from_u16_with_traits, from_u16, u16);
4149impl_dynamic_float_from_int_type!(from_u32_with_traits, from_u32, u32);
4150impl_dynamic_float_from_int_type!(from_u64_with_traits, from_u64, u64);
4151impl_dynamic_float_from_int_type!(from_u128_with_traits, from_u128, u128);
4152impl_dynamic_float_from_int_type!(from_usize_with_traits, from_usize, usize);
4153impl_dynamic_float_from_int_type!(from_i8_with_traits, from_i8, i8);
4154impl_dynamic_float_from_int_type!(from_i16_with_traits, from_i16, i16);
4155impl_dynamic_float_from_int_type!(from_i32_with_traits, from_i32, i32);
4156impl_dynamic_float_from_int_type!(from_i64_with_traits, from_i64, i64);
4157impl_dynamic_float_from_int_type!(from_i128_with_traits, from_i128, i128);
4158impl_dynamic_float_from_int_type!(from_isize_with_traits, from_isize, isize);
4159impl_dynamic_float_to_int_type!(to_bigint, BigInt);
4160impl_dynamic_float_to_int_type!(to_biguint, BigUint);
4161impl_dynamic_float_to_int_type!(to_u8, u8);
4162impl_dynamic_float_to_int_type!(to_u16, u16);
4163impl_dynamic_float_to_int_type!(to_u32, u32);
4164impl_dynamic_float_to_int_type!(to_u64, u64);
4165impl_dynamic_float_to_int_type!(to_u128, u128);
4166impl_dynamic_float_to_int_type!(to_usize, usize);
4167impl_dynamic_float_to_int_type!(to_i8, i8);
4168impl_dynamic_float_to_int_type!(to_i16, i16);
4169impl_dynamic_float_to_int_type!(to_i32, i32);
4170impl_dynamic_float_to_int_type!(to_i64, i64);
4171impl_dynamic_float_to_int_type!(to_i128, i128);
4172impl_dynamic_float_to_int_type!(to_isize, isize);
4173impl_dynamic_float_fn!(
4174 rsqrt,
4176 rsqrt,
4177 (&self, rounding_mode: Option<RoundingMode>)
4178);
4179
4180macro_rules! impl_dynamic_float_binary_op_trait {
4181 ($op_trait:ident, $op:ident, $op_assign_trait:ident, $op_assign:ident, $called_fn_name:ident) => {
4182 impl $op_trait for DynamicFloat {
4183 type Output = DynamicFloat;
4184 fn $op(self, rhs: DynamicFloat) -> DynamicFloat {
4185 self.$called_fn_name(&rhs, None)
4186 }
4187 }
4188
4189 impl $op_trait<&'_ DynamicFloat> for DynamicFloat {
4190 type Output = DynamicFloat;
4191 fn $op(self, rhs: &DynamicFloat) -> DynamicFloat {
4192 self.$called_fn_name(rhs, None)
4193 }
4194 }
4195 impl $op_trait<DynamicFloat> for &'_ DynamicFloat {
4196 type Output = DynamicFloat;
4197 fn $op(self, rhs: DynamicFloat) -> DynamicFloat {
4198 self.$called_fn_name(&rhs, None)
4199 }
4200 }
4201
4202 impl<'a, 'b> $op_trait<&'a DynamicFloat> for &'b DynamicFloat {
4203 type Output = DynamicFloat;
4204 fn $op(self, rhs: &DynamicFloat) -> DynamicFloat {
4205 self.$called_fn_name(rhs, None)
4206 }
4207 }
4208
4209 impl $op_assign_trait for DynamicFloat {
4210 fn $op_assign(&mut self, rhs: DynamicFloat) {
4211 *self = self.$called_fn_name(&rhs, None);
4212 }
4213 }
4214
4215 impl $op_assign_trait<&'_ DynamicFloat> for DynamicFloat {
4216 fn $op_assign(&mut self, rhs: &DynamicFloat) {
4217 *self = self.$called_fn_name(rhs, None);
4218 }
4219 }
4220 };
4221}
4222
4223impl_dynamic_float_binary_op_trait!(Add, add, AddAssign, add_assign, add_with_rounding_mode);
4224impl_dynamic_float_binary_op_trait!(Sub, sub, SubAssign, sub_assign, sub_with_rounding_mode);
4225impl_dynamic_float_binary_op_trait!(Mul, mul, MulAssign, mul_assign, mul_with_rounding_mode);
4226impl_dynamic_float_binary_op_trait!(Div, div, DivAssign, div_assign, div_with_rounding_mode);
4227
4228impl Neg for &'_ DynamicFloat {
4229 type Output = DynamicFloat;
4230 fn neg(self) -> DynamicFloat {
4231 let mut retval = self.clone();
4232 retval.neg_assign();
4233 retval
4234 }
4235}
4236
4237impl Neg for DynamicFloat {
4238 type Output = DynamicFloat;
4239 fn neg(mut self) -> DynamicFloat {
4240 self.neg_assign();
4241 self
4242 }
4243}
4244
4245#[cfg(test)]
4246mod tests {
4247 #![allow(clippy::cognitive_complexity)]
4248 use super::*;
4249
4250 #[test]
4251 fn test_debug() {
4252 assert_eq!(
4253 &format!("{:?}", F16::from_bits(0x0000)),
4254 "Float { traits: F16Traits, bits: 0x0000, sign: Positive, \
4255 exponent_field: 0x00, mantissa_field: 0x000, class: PositiveZero }",
4256 );
4257 assert_eq!(
4258 &format!("{:?}", F16::from_bits(0x8000)),
4259 "Float { traits: F16Traits, bits: 0x8000, sign: Negative, \
4260 exponent_field: 0x00, mantissa_field: 0x000, class: NegativeZero }",
4261 );
4262 assert_eq!(
4263 &format!("{:?}", F16::from_bits(0xFC00)),
4264 "Float { traits: F16Traits, bits: 0xFC00, sign: Negative, \
4265 exponent_field: 0x1F, mantissa_field: 0x000, class: NegativeInfinity }",
4266 );
4267 assert_eq!(
4268 &format!("{:?}", F16::from_bits(0xFE00)),
4269 "Float { traits: F16Traits, bits: 0xFE00, sign: Negative, \
4270 exponent_field: 0x1F, mantissa_field: 0x200, class: QuietNaN }",
4271 );
4272 assert_eq!(
4273 &format!("{:?}", F16::from_bits(0x0001)),
4274 "Float { traits: F16Traits, bits: 0x0001, sign: Positive, \
4275 exponent_field: 0x00, mantissa_field: 0x001, class: PositiveSubnormal }",
4276 );
4277 assert_eq!(
4278 &format!("{:?}", F16::from_bits(0x3C00)),
4279 "Float { traits: F16Traits, bits: 0x3C00, sign: Positive, \
4280 exponent_field: 0x0F, mantissa_field: 0x000, class: PositiveNormal }",
4281 );
4282 assert_eq!(
4283 &format!(
4284 "{:?}",
4285 F16WithPlatformProperties::from_bits_and_traits(
4286 0x1234,
4287 F16WithPlatformPropertiesTraits(PlatformProperties::RISC_V)
4288 )
4289 ),
4290 "Float { traits: F16WithPlatformPropertiesTraits(PlatformProperties::RISC_V), \
4291 bits: 0x1234, sign: Positive, exponent_field: 0x04, \
4292 mantissa_field: 0x234, class: PositiveNormal }",
4293 );
4294 assert_eq!(
4295 &format!(
4296 "{:?}",
4297 F16WithPlatformProperties::from_bits_and_traits(
4298 0x1234,
4299 F16WithPlatformPropertiesTraits(PlatformProperties::SPARC)
4300 )
4301 ),
4302 "Float { traits: F16WithPlatformPropertiesTraits(PlatformProperties::SPARC), \
4303 bits: 0x1234, sign: Positive, exponent_field: 0x04, \
4304 mantissa_field: 0x234, class: PositiveNormal }",
4305 );
4306 assert_eq!(
4307 &format!(
4308 "{:?}",
4309 F16WithPlatformProperties::from_bits_and_traits(
4310 0x1234,
4311 F16WithPlatformPropertiesTraits(PlatformProperties::X86_SSE)
4312 )
4313 ),
4314 "Float { traits: F16WithPlatformPropertiesTraits(PlatformProperties::X86_SSE), \
4315 bits: 0x1234, sign: Positive, exponent_field: 0x04, \
4316 mantissa_field: 0x234, class: PositiveNormal }",
4317 );
4318 assert_eq!(
4319 &format!(
4320 "{:?}",
4321 F16WithPlatformProperties::from_bits_and_traits(
4322 0x1234,
4323 F16WithPlatformPropertiesTraits(PlatformProperties::HPPA)
4324 )
4325 ),
4326 "Float { traits: F16WithPlatformPropertiesTraits(PlatformProperties::HPPA), \
4327 bits: 0x1234, sign: Positive, exponent_field: 0x04, \
4328 mantissa_field: 0x234, class: PositiveNormal }",
4329 );
4330 assert_eq!(
4331 &format!(
4332 "{:?}",
4333 F16WithPlatformProperties::from_bits_and_traits(
4334 0x1234,
4335 F16WithPlatformPropertiesTraits(PlatformProperties::MIPS_LEGACY)
4336 )
4337 ),
4338 "Float { traits: F16WithPlatformPropertiesTraits(PlatformProperties::MIPS_LEGACY), \
4339 bits: 0x1234, sign: Positive, exponent_field: 0x04, \
4340 mantissa_field: 0x234, class: PositiveNormal }",
4341 );
4342 assert_eq!(
4343 &format!(
4344 "{:?}",
4345 F16WithPlatformProperties::from_bits_and_traits(
4346 0x1234,
4347 F16WithPlatformPropertiesTraits(PlatformProperties {
4348 canonical_nan_sign: Sign::Negative,
4349 ..PlatformProperties::MIPS_LEGACY
4350 })
4351 )
4352 ),
4353 "Float { traits: F16WithPlatformPropertiesTraits(PlatformProperties { \
4354 canonical_nan_sign: Negative, canonical_nan_mantissa_msb: false, \
4355 canonical_nan_mantissa_second_to_msb: true, \
4356 canonical_nan_mantissa_rest: true, \
4357 std_bin_ops_nan_propagation_mode: FirstSecondPreferringSNaN, \
4358 fma_nan_propagation_mode: FirstSecondThirdPreferringSNaN, \
4359 fma_inf_zero_qnan_result: CanonicalAndGenerateInvalid, \
4360 round_to_integral_nan_propagation_mode: First, \
4361 next_up_or_down_nan_propagation_mode: First, \
4362 scale_b_nan_propagation_mode: First, \
4363 sqrt_nan_propagation_mode: First, \
4364 float_to_float_conversion_nan_propagation_mode: RetainMostSignificantBits, \
4365 rsqrt_nan_propagation_mode: First, \
4366 quiet_nan_format: MIPSLegacy }), \
4367 bits: 0x1234, sign: Positive, exponent_field: 0x04, \
4368 mantissa_field: 0x234, class: PositiveNormal }",
4369 );
4370 }
4371
4372 #[test]
4373 fn test_class() {
4374 use FloatClass::*;
4375 assert_eq!(F16::from_bits(0x0000).class(), PositiveZero);
4376 assert_eq!(F16::from_bits(0x0001).class(), PositiveSubnormal);
4377 assert_eq!(F16::from_bits(0x03FF).class(), PositiveSubnormal);
4378 assert_eq!(F16::from_bits(0x0400).class(), PositiveNormal);
4379 assert_eq!(F16::from_bits(0x3C00).class(), PositiveNormal);
4380 assert_eq!(F16::from_bits(0x7BFF).class(), PositiveNormal);
4381 assert_eq!(F16::from_bits(0x7C00).class(), PositiveInfinity);
4382 assert_eq!(F16::from_bits(0x7C01).class(), SignalingNaN);
4383 assert_eq!(F16::from_bits(0x7DFF).class(), SignalingNaN);
4384 assert_eq!(F16::from_bits(0x7E00).class(), QuietNaN);
4385 assert_eq!(F16::from_bits(0x7FFF).class(), QuietNaN);
4386 assert_eq!(F16::from_bits(0x8000).class(), NegativeZero);
4387 assert_eq!(F16::from_bits(0x8001).class(), NegativeSubnormal);
4388 assert_eq!(F16::from_bits(0x83FF).class(), NegativeSubnormal);
4389 assert_eq!(F16::from_bits(0x8400).class(), NegativeNormal);
4390 assert_eq!(F16::from_bits(0xBC00).class(), NegativeNormal);
4391 assert_eq!(F16::from_bits(0xFBFF).class(), NegativeNormal);
4392 assert_eq!(F16::from_bits(0xFC00).class(), NegativeInfinity);
4393 assert_eq!(F16::from_bits(0xFC01).class(), SignalingNaN);
4394 assert_eq!(F16::from_bits(0xFDFF).class(), SignalingNaN);
4395 assert_eq!(F16::from_bits(0xFE00).class(), QuietNaN);
4396 assert_eq!(F16::from_bits(0xFFFF).class(), QuietNaN);
4397 assert_eq!(
4398 Float::from_bits_and_traits(
4399 0x7C01,
4400 F16WithPlatformPropertiesTraits(PlatformProperties::MIPS_LEGACY)
4401 )
4402 .class(),
4403 QuietNaN
4404 );
4405 assert_eq!(
4406 Float::from_bits_and_traits(
4407 0x7DFF,
4408 F16WithPlatformPropertiesTraits(PlatformProperties::MIPS_LEGACY)
4409 )
4410 .class(),
4411 QuietNaN
4412 );
4413 assert_eq!(
4414 Float::from_bits_and_traits(
4415 0x7E00,
4416 F16WithPlatformPropertiesTraits(PlatformProperties::MIPS_LEGACY)
4417 )
4418 .class(),
4419 SignalingNaN
4420 );
4421 assert_eq!(
4422 Float::from_bits_and_traits(
4423 0x7FFF,
4424 F16WithPlatformPropertiesTraits(PlatformProperties::MIPS_LEGACY)
4425 )
4426 .class(),
4427 SignalingNaN
4428 );
4429 assert_eq!(
4430 Float::from_bits_and_traits(
4431 0xFC01,
4432 F16WithPlatformPropertiesTraits(PlatformProperties::MIPS_LEGACY)
4433 )
4434 .class(),
4435 QuietNaN
4436 );
4437 assert_eq!(
4438 Float::from_bits_and_traits(
4439 0xFDFF,
4440 F16WithPlatformPropertiesTraits(PlatformProperties::MIPS_LEGACY)
4441 )
4442 .class(),
4443 QuietNaN
4444 );
4445 assert_eq!(
4446 Float::from_bits_and_traits(
4447 0xFE00,
4448 F16WithPlatformPropertiesTraits(PlatformProperties::MIPS_LEGACY)
4449 )
4450 .class(),
4451 SignalingNaN
4452 );
4453 assert_eq!(
4454 Float::from_bits_and_traits(
4455 0xFFFF,
4456 F16WithPlatformPropertiesTraits(PlatformProperties::MIPS_LEGACY)
4457 )
4458 .class(),
4459 SignalingNaN
4460 );
4461 }
4462
4463 #[test]
4464 fn test_to_ratio() {
4465 macro_rules! test_case {
4466 ($value:expr, $expected_ratio:expr) => {
4467 let value: F16 = $value;
4468 let expected_ratio: Option<Ratio<i128>> = $expected_ratio;
4469 println!("value: {:?}", value);
4470 println!("expected_ratio: {:?}", expected_ratio);
4471 let ratio = value.to_ratio();
4472 println!("ratio: {:?}", ratio.as_ref().map(ToString::to_string));
4473 let expected_ratio = expected_ratio.map(|v| {
4474 let (n, d) = v.into();
4475 Ratio::new(n.into(), d.into())
4476 });
4477 assert!(ratio == expected_ratio);
4478 };
4479 }
4480
4481 let r = |n, d| Some(Ratio::new(n, d));
4482
4483 test_case!(F16::from_bits(0x0000), r(0, 1));
4484 test_case!(F16::from_bits(0x0001), r(1, 1 << 24));
4485 test_case!(F16::from_bits(0x03FF), r(1023, 1 << 24));
4486 test_case!(F16::from_bits(0x0400), r(1, 1 << 14));
4487 test_case!(F16::from_bits(0x3C00), r(1, 1));
4488 test_case!(F16::from_bits(0x7BFF), r(65504, 1));
4489 test_case!(F16::from_bits(0x7C00), None);
4490 test_case!(F16::from_bits(0x7C01), None);
4491 test_case!(F16::from_bits(0x7DFF), None);
4492 test_case!(F16::from_bits(0x7E00), None);
4493 test_case!(F16::from_bits(0x7FFF), None);
4494 test_case!(F16::from_bits(0x8000), r(0, 1));
4495 test_case!(F16::from_bits(0x8001), r(-1, 1 << 24));
4496 test_case!(F16::from_bits(0x83FF), r(-1023, 1 << 24));
4497 test_case!(F16::from_bits(0x8400), r(-1, 1 << 14));
4498 test_case!(F16::from_bits(0xBC00), r(-1, 1));
4499 test_case!(F16::from_bits(0xFBFF), r(-65504, 1));
4500 test_case!(F16::from_bits(0xFC00), None);
4501 test_case!(F16::from_bits(0xFC01), None);
4502 test_case!(F16::from_bits(0xFDFF), None);
4503 test_case!(F16::from_bits(0xFE00), None);
4504 test_case!(F16::from_bits(0xFFFF), None);
4505 }
4506
4507 #[test]
4508 fn test_log_b() {
4509 macro_rules! test_case {
4510 ($value:expr, $expected_result:expr) => {
4511 let value: F16 = $value;
4512 let expected_result: Option<i32> = $expected_result;
4513 let expected_status_flags: StatusFlags = if expected_result.is_some() {
4514 StatusFlags::empty()
4515 } else {
4516 StatusFlags::INVALID_OPERATION
4517 };
4518 println!("value: {:?}", value);
4519 println!("expected_result: {:?}", expected_result);
4520 println!("expected_status_flags: {:?}", expected_status_flags);
4521 let mut fp_state = FPState::default();
4522 let result = value.log_b(Some(&mut fp_state));
4523 println!("result: {:?}", result.as_ref().map(ToString::to_string));
4524 let expected_result: Option<BigInt> = expected_result.map(Into::into);
4525 println!("status_flags: {:?}", fp_state.status_flags);
4526 assert!(result == expected_result);
4527 assert!(fp_state.status_flags == expected_status_flags);
4528 };
4529 }
4530
4531 test_case!(F16::from_bits(0x0000), None);
4532 test_case!(F16::from_bits(0x0001), Some(-24));
4533 test_case!(F16::from_bits(0x0002), Some(-23));
4534 test_case!(F16::from_bits(0x03FF), Some(-15));
4535 test_case!(F16::from_bits(0x0400), Some(-14));
4536 test_case!(F16::from_bits(0x3C00), Some(0));
4537 test_case!(F16::from_bits(0x7BFF), Some(15));
4538 test_case!(F16::from_bits(0x7C00), None);
4539 test_case!(F16::from_bits(0x7C01), None);
4540 test_case!(F16::from_bits(0x7DFF), None);
4541 test_case!(F16::from_bits(0x7E00), None);
4542 test_case!(F16::from_bits(0x7FFF), None);
4543 test_case!(F16::from_bits(0x8000), None);
4544 test_case!(F16::from_bits(0x8001), Some(-24));
4545 test_case!(F16::from_bits(0x8002), Some(-23));
4546 test_case!(F16::from_bits(0x83FF), Some(-15));
4547 test_case!(F16::from_bits(0x8400), Some(-14));
4548 test_case!(F16::from_bits(0xBC00), Some(0));
4549 test_case!(F16::from_bits(0xFBFF), Some(15));
4550 test_case!(F16::from_bits(0xFC00), None);
4551 test_case!(F16::from_bits(0xFC01), None);
4552 test_case!(F16::from_bits(0xFDFF), None);
4553 test_case!(F16::from_bits(0xFE00), None);
4554 test_case!(F16::from_bits(0xFFFF), None);
4555 }
4556
4557 }
4559
4560macro_rules! doctest {
4561 ($x:expr) => {
4562 #[doc = $x]
4563 extern {}
4564 };
4565}
4566
4567doctest!(include_str!("../README.md"));