17
17
namespace LIBC_NAMESPACE {
18
18
namespace fputil {
19
19
20
- template <typename T> struct FloatProperties {};
20
+ // The supported floating point types.
21
+ enum class FPType {
22
+ IEEE754_Binary16,
23
+ IEEE754_Binary32,
24
+ IEEE754_Binary64,
25
+ IEEE754_Binary128,
26
+ X86_Binary80,
27
+ };
21
28
22
- template <> struct FloatProperties <float > {
29
+ template <FPType> struct FPProperties {};
30
+ template <> struct FPProperties <FPType::IEEE754_Binary32> {
23
31
typedef uint32_t BitsType;
24
- static_assert (sizeof (BitsType) == sizeof (float ),
25
- " Unexpected size of 'float' type." );
26
32
27
33
static constexpr uint32_t BIT_WIDTH = sizeof (BitsType) * 8 ;
28
34
@@ -46,10 +52,8 @@ template <> struct FloatProperties<float> {
46
52
static constexpr BitsType QUIET_NAN_MASK = 0x00400000U ;
47
53
};
48
54
49
- template <> struct FloatProperties < double > {
55
+ template <> struct FPProperties <FPType::IEEE754_Binary64 > {
50
56
typedef uint64_t BitsType;
51
- static_assert (sizeof (BitsType) == sizeof (double ),
52
- " Unexpected size of 'double' type." );
53
57
54
58
static constexpr uint32_t BIT_WIDTH = sizeof (BitsType) * 8 ;
55
59
@@ -72,47 +76,10 @@ template <> struct FloatProperties<double> {
72
76
static constexpr BitsType QUIET_NAN_MASK = 0x0008000000000000ULL ;
73
77
};
74
78
75
- #if defined(LONG_DOUBLE_IS_DOUBLE)
76
- // Properties for numbers represented in 64 bits long double on Windows
77
- // platform.
78
- template <> struct FloatProperties <long double > {
79
- typedef uint64_t BitsType;
80
- static_assert (sizeof (BitsType) == sizeof (double ),
81
- " Unexpected size of 'double' type." );
82
-
83
- static constexpr uint32_t BIT_WIDTH = FloatProperties<double >::BIT_WIDTH;
84
-
85
- static constexpr uint32_t MANTISSA_WIDTH =
86
- FloatProperties<double >::MANTISSA_WIDTH;
87
- static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1 ;
88
- static constexpr uint32_t EXPONENT_WIDTH =
89
- FloatProperties<double >::EXPONENT_WIDTH;
90
- static constexpr BitsType MANTISSA_MASK =
91
- FloatProperties<double >::MANTISSA_MASK;
92
- static constexpr BitsType SIGN_MASK = FloatProperties<double >::SIGN_MASK;
93
- static constexpr BitsType EXPONENT_MASK =
94
- FloatProperties<double >::EXPONENT_MASK;
95
- static constexpr uint32_t EXPONENT_BIAS =
96
- FloatProperties<double >::EXPONENT_BIAS;
97
-
98
- static constexpr BitsType EXP_MANT_MASK =
99
- FloatProperties<double >::EXP_MANT_MASK;
100
- static_assert (EXP_MANT_MASK == ~SIGN_MASK,
101
- " Exponent and mantissa masks are not as expected." );
102
-
103
- // If a number x is a NAN, then it is a quiet NAN if:
104
- // QuietNaNMask & bits(x) != 0
105
- // Else, it is a signalling NAN.
106
- static constexpr BitsType QUIET_NAN_MASK =
107
- FloatProperties<double >::QUIET_NAN_MASK;
108
- };
109
- #elif defined(SPECIAL_X86_LONG_DOUBLE)
110
79
// Properties for numbers represented in 80 bits long double on non-Windows x86
111
80
// platforms.
112
- template <> struct FloatProperties < long double > {
81
+ template <> struct FPProperties <FPType::X86_Binary80 > {
113
82
typedef UInt128 BitsType;
114
- static_assert (sizeof (BitsType) == sizeof (long double ),
115
- " Unexpected size of 'long double' type." );
116
83
117
84
static constexpr uint32_t BIT_WIDTH = (sizeof (BitsType) * 8 ) - 48 ;
118
85
static constexpr BitsType FULL_WIDTH_MASK = ((BitsType(1 ) << BIT_WIDTH) - 1 );
@@ -143,13 +110,11 @@ template <> struct FloatProperties<long double> {
143
110
static constexpr BitsType QUIET_NAN_MASK = BitsType(1 )
144
111
<< (MANTISSA_WIDTH - 1 );
145
112
};
146
- # else
113
+
147
114
// Properties for numbers represented in 128 bits long double on non x86
148
115
// platform.
149
- template <> struct FloatProperties < long double > {
116
+ template <> struct FPProperties <FPType::IEEE754_Binary128 > {
150
117
typedef UInt128 BitsType;
151
- static_assert (sizeof (BitsType) == sizeof (long double ),
152
- " Unexpected size of 'long double' type." );
153
118
154
119
static constexpr uint32_t BIT_WIDTH = sizeof (BitsType) << 3 ;
155
120
@@ -172,39 +137,39 @@ template <> struct FloatProperties<long double> {
172
137
static constexpr BitsType QUIET_NAN_MASK = BitsType(1 )
173
138
<< (MANTISSA_WIDTH - 1 );
174
139
};
175
- #endif
176
140
177
- #if (defined(LIBC_COMPILER_HAS_FLOAT128) && \
178
- !defined(LIBC_FLOAT128_IS_LONG_DOUBLE))
179
- // Properties for numbers represented in 128 bits long double on non x86
180
- // platform.
181
- template <> struct FloatProperties <float128> {
182
- typedef UInt128 BitsType;
183
- static_assert (sizeof (BitsType) == sizeof (float128),
184
- " Unexpected size of 'float128' type." );
185
-
186
- static constexpr uint32_t BIT_WIDTH = sizeof (BitsType) << 3 ;
187
-
188
- static constexpr uint32_t MANTISSA_WIDTH = 112 ;
189
- static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1 ;
190
- static constexpr uint32_t EXPONENT_WIDTH = 15 ;
191
- static constexpr BitsType MANTISSA_MASK = (BitsType(1 ) << MANTISSA_WIDTH) - 1 ;
192
- static constexpr BitsType SIGN_MASK = BitsType(1 )
193
- << (EXPONENT_WIDTH + MANTISSA_WIDTH);
194
- static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
195
- static constexpr uint32_t EXPONENT_BIAS = 16383 ;
196
-
197
- static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK | EXPONENT_MASK;
198
- static_assert (EXP_MANT_MASK == ~SIGN_MASK,
199
- " Exponent and mantissa masks are not as expected." );
141
+ // -----------------------------------------------------------------------------
142
+ template <typename FP> static constexpr FPType get_fp_type () {
143
+ if constexpr (cpp::is_same_v<FP, float > && __FLT_MANT_DIG__ == 24 )
144
+ return FPType::IEEE754_Binary32;
145
+ else if constexpr (cpp::is_same_v<FP, double > && __DBL_MANT_DIG__ == 53 )
146
+ return FPType::IEEE754_Binary64;
147
+ else if constexpr (cpp::is_same_v<FP, long double >) {
148
+ if constexpr (__LDBL_MANT_DIG__ == 53 )
149
+ return FPType::IEEE754_Binary64;
150
+ else if constexpr (__LDBL_MANT_DIG__ == 64 )
151
+ return FPType::X86_Binary80;
152
+ else if constexpr (__LDBL_MANT_DIG__ == 113 )
153
+ return FPType::IEEE754_Binary128;
154
+ }
155
+ #if defined(LIBC_COMPILER_HAS_C23_FLOAT16)
156
+ else if constexpr (cpp::is_same_v<FP, _Float16>)
157
+ return FPType::IEEE754_Binary16;
158
+ #endif
159
+ #if defined(LIBC_COMPILER_HAS_C23_FLOAT128)
160
+ else if constexpr (cpp::is_same_v<FP, _Float128>)
161
+ return FPType::IEEE754_Binary128;
162
+ #endif
163
+ #if defined(LIBC_COMPILER_HAS_FLOAT128_EXTENSION)
164
+ else if constexpr (cpp::is_same_v<FP, __float128>)
165
+ return FPType::IEEE754_Binary128;
166
+ #endif
167
+ else
168
+ static_assert (cpp::always_false<FP>, " Unsupported type" );
169
+ }
200
170
201
- // If a number x is a NAN, then it is a quiet NAN if:
202
- // QuietNaNMask & bits(x) != 0
203
- // Else, it is a signalling NAN.
204
- static constexpr BitsType QUIET_NAN_MASK = BitsType(1 )
205
- << (MANTISSA_WIDTH - 1 );
206
- };
207
- #endif // LIBC_COMPILER_HAS_FLOAT128
171
+ template <typename FP>
172
+ struct FloatProperties : public FPProperties <get_fp_type<FP>()> {};
208
173
209
174
} // namespace fputil
210
175
} // namespace LIBC_NAMESPACE
0 commit comments