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, Unsigned = Self::Int>;
24
25 /// A int of the same width as the float
26 type SignedInt: Int + MinInt<OtherSign = Self::Int, Unsigned = 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);
190