compiler_builtins/float/
traits.rs

1use core::ops;
2
3use crate::int::{DInt, Int, MinInt};
4
5/// Wrapper to extract the integer type half of the float's size
6pub type HalfRep<F> = <<F as Float>::Int as DInt>::H;
7
8/// Trait for some basic operations on floats
9#[allow(dead_code)]
10pub trait Float:
11    Copy
12    + core::fmt::Debug
13    + PartialEq
14    + PartialOrd
15    + ops::AddAssign
16    + ops::MulAssign
17    + ops::Add<Output = Self>
18    + ops::Sub<Output = Self>
19    + ops::Div<Output = Self>
20    + ops::Rem<Output = Self>
21{
22    /// A uint of the same width as the float
23    type Int: Int<OtherSign = Self::SignedInt, UnsignedInt = Self::Int>;
24
25    /// A int of the same width as the float
26    type SignedInt: Int + MinInt<OtherSign = Self::Int, UnsignedInt = Self::Int>;
27
28    /// An int capable of containing the exponent bits plus a sign bit. This is signed.
29    type ExpInt: Int;
30
31    const ZERO: Self;
32    const ONE: Self;
33
34    /// The bitwidth of the float type.
35    const BITS: u32;
36
37    /// The bitwidth of the significand.
38    const SIG_BITS: u32;
39
40    /// The bitwidth of the exponent.
41    const EXP_BITS: u32 = Self::BITS - Self::SIG_BITS - 1;
42
43    /// The saturated (maximum bitpattern) value of the exponent, i.e. the infinite
44    /// representation.
45    ///
46    /// This is in the rightmost position, use `EXP_MASK` for the shifted value.
47    const EXP_SAT: u32 = (1 << Self::EXP_BITS) - 1;
48
49    /// The exponent bias value.
50    const EXP_BIAS: u32 = Self::EXP_SAT >> 1;
51
52    /// A mask for the sign bit.
53    const SIGN_MASK: Self::Int;
54
55    /// A mask for the significand.
56    const SIG_MASK: Self::Int;
57
58    /// The implicit bit of the float format.
59    const IMPLICIT_BIT: Self::Int;
60
61    /// A mask for the exponent.
62    const EXP_MASK: Self::Int;
63
64    /// Returns `self` transmuted to `Self::Int`
65    fn to_bits(self) -> Self::Int;
66
67    /// Returns `self` transmuted to `Self::SignedInt`
68    fn to_bits_signed(self) -> Self::SignedInt;
69
70    /// Checks if two floats have the same bit representation. *Except* for NaNs! NaN can be
71    /// represented in multiple different ways. This method returns `true` if two NaNs are
72    /// compared.
73    fn eq_repr(self, rhs: Self) -> bool;
74
75    /// Returns true if the sign is negative
76    fn is_sign_negative(self) -> bool;
77
78    /// Returns the exponent, not adjusting for bias.
79    fn exp(self) -> Self::ExpInt;
80
81    /// Returns the significand with no implicit bit (or the "fractional" part)
82    fn frac(self) -> Self::Int;
83
84    /// Returns the significand with implicit bit
85    fn imp_frac(self) -> Self::Int;
86
87    /// Returns a `Self::Int` transmuted back to `Self`
88    fn from_bits(a: Self::Int) -> Self;
89
90    /// Constructs a `Self` from its parts. Inputs are treated as bits and shifted into position.
91    fn from_parts(negative: bool, exponent: Self::Int, significand: Self::Int) -> Self;
92
93    fn abs(self) -> Self {
94        let abs_mask = !Self::SIGN_MASK;
95        Self::from_bits(self.to_bits() & abs_mask)
96    }
97
98    /// Returns (normalized exponent, normalized significand)
99    fn normalize(significand: Self::Int) -> (i32, Self::Int);
100
101    /// Returns if `self` is subnormal
102    fn is_subnormal(self) -> bool;
103}
104
105macro_rules! float_impl {
106    ($ty:ident, $ity:ident, $sity:ident, $expty:ident, $bits:expr, $significand_bits:expr) => {
107        impl Float for $ty {
108            type Int = $ity;
109            type SignedInt = $sity;
110            type ExpInt = $expty;
111
112            const ZERO: Self = 0.0;
113            const ONE: Self = 1.0;
114
115            const BITS: u32 = $bits;
116            const SIG_BITS: u32 = $significand_bits;
117
118            const SIGN_MASK: Self::Int = 1 << (Self::BITS - 1);
119            const SIG_MASK: Self::Int = (1 << Self::SIG_BITS) - 1;
120            const IMPLICIT_BIT: Self::Int = 1 << Self::SIG_BITS;
121            const EXP_MASK: Self::Int = !(Self::SIGN_MASK | Self::SIG_MASK);
122
123            fn to_bits(self) -> Self::Int {
124                self.to_bits()
125            }
126            fn to_bits_signed(self) -> Self::SignedInt {
127                self.to_bits() as Self::SignedInt
128            }
129            fn eq_repr(self, rhs: Self) -> bool {
130                #[cfg(feature = "mangled-names")]
131                fn is_nan(x: $ty) -> bool {
132                    // When using mangled-names, the "real" compiler-builtins might not have the
133                    // necessary builtin (__unordtf2) to test whether `f128` is NaN.
134                    // FIXME(f16_f128): Remove once the nightly toolchain has the __unordtf2 builtin
135                    // x is NaN if all the bits of the exponent are set and the significand is non-0
136                    x.to_bits() & $ty::EXP_MASK == $ty::EXP_MASK && x.to_bits() & $ty::SIG_MASK != 0
137                }
138                #[cfg(not(feature = "mangled-names"))]
139                fn is_nan(x: $ty) -> bool {
140                    x.is_nan()
141                }
142                if is_nan(self) && is_nan(rhs) {
143                    true
144                } else {
145                    self.to_bits() == rhs.to_bits()
146                }
147            }
148            fn is_sign_negative(self) -> bool {
149                self.is_sign_negative()
150            }
151            fn exp(self) -> Self::ExpInt {
152                ((self.to_bits() & Self::EXP_MASK) >> Self::SIG_BITS) as Self::ExpInt
153            }
154            fn frac(self) -> Self::Int {
155                self.to_bits() & Self::SIG_MASK
156            }
157            fn imp_frac(self) -> Self::Int {
158                self.frac() | Self::IMPLICIT_BIT
159            }
160            fn from_bits(a: Self::Int) -> Self {
161                Self::from_bits(a)
162            }
163            fn from_parts(negative: bool, exponent: Self::Int, significand: Self::Int) -> Self {
164                Self::from_bits(
165                    ((negative as Self::Int) << (Self::BITS - 1))
166                        | ((exponent << Self::SIG_BITS) & Self::EXP_MASK)
167                        | (significand & Self::SIG_MASK),
168                )
169            }
170            fn normalize(significand: Self::Int) -> (i32, Self::Int) {
171                let shift = significand.leading_zeros().wrapping_sub(Self::EXP_BITS);
172                (
173                    1i32.wrapping_sub(shift as i32),
174                    significand << shift as Self::Int,
175                )
176            }
177            fn is_subnormal(self) -> bool {
178                (self.to_bits() & Self::EXP_MASK) == Self::Int::ZERO
179            }
180        }
181    };
182}
183
184#[cfg(f16_enabled)]
185float_impl!(f16, u16, i16, i8, 16, 10);
186float_impl!(f32, u32, i32, i16, 32, 23);
187float_impl!(f64, u64, i64, i16, 64, 52);
188#[cfg(f128_enabled)]
189float_impl!(f128, u128, i128, i16, 128, 112);