1 //===-- Properties of floating point numbers --------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIBC_SRC_SUPPORT_FPUTIL_FLOAT_PROPERTIES_H
10 #define LLVM_LIBC_SRC_SUPPORT_FPUTIL_FLOAT_PROPERTIES_H
12 #include "PlatformDefs.h"
14 #include "src/__support/UInt128.h"
18 namespace __llvm_libc
{
21 template <typename T
> struct FloatProperties
{};
23 template <> struct FloatProperties
<float> {
24 typedef uint32_t BitsType
;
25 static_assert(sizeof(BitsType
) == sizeof(float),
26 "Unexpected size of 'float' type.");
28 static constexpr uint32_t BIT_WIDTH
= sizeof(BitsType
) * 8;
30 static constexpr uint32_t MANTISSA_WIDTH
= 23;
31 // The mantissa precision includes the implicit bit.
32 static constexpr uint32_t MANTISSA_PRECISION
= MANTISSA_WIDTH
+ 1;
33 static constexpr uint32_t EXPONENT_WIDTH
= 8;
34 static constexpr BitsType MANTISSA_MASK
= (BitsType(1) << MANTISSA_WIDTH
) - 1;
35 static constexpr BitsType SIGN_MASK
= BitsType(1)
36 << (EXPONENT_WIDTH
+ MANTISSA_WIDTH
);
37 static constexpr BitsType EXPONENT_MASK
= ~(SIGN_MASK
| MANTISSA_MASK
);
38 static constexpr uint32_t EXPONENT_BIAS
= 127;
40 static constexpr BitsType EXP_MANT_MASK
= MANTISSA_MASK
+ EXPONENT_MASK
;
41 static_assert(EXP_MANT_MASK
== ~SIGN_MASK
,
42 "Exponent and mantissa masks are not as expected.");
44 // If a number x is a NAN, then it is a quiet NAN if:
45 // QuietNaNMask & bits(x) != 0
46 // Else, it is a signalling NAN.
47 static constexpr BitsType QUIET_NAN_MASK
= 0x00400000U
;
50 template <> struct FloatProperties
<double> {
51 typedef uint64_t BitsType
;
52 static_assert(sizeof(BitsType
) == sizeof(double),
53 "Unexpected size of 'double' type.");
55 static constexpr uint32_t BIT_WIDTH
= sizeof(BitsType
) * 8;
57 static constexpr uint32_t MANTISSA_WIDTH
= 52;
58 static constexpr uint32_t MANTISSA_PRECISION
= MANTISSA_WIDTH
+ 1;
59 static constexpr uint32_t EXPONENT_WIDTH
= 11;
60 static constexpr BitsType MANTISSA_MASK
= (BitsType(1) << MANTISSA_WIDTH
) - 1;
61 static constexpr BitsType SIGN_MASK
= BitsType(1)
62 << (EXPONENT_WIDTH
+ MANTISSA_WIDTH
);
63 static constexpr BitsType EXPONENT_MASK
= ~(SIGN_MASK
| MANTISSA_MASK
);
64 static constexpr uint32_t EXPONENT_BIAS
= 1023;
66 static constexpr BitsType EXP_MANT_MASK
= MANTISSA_MASK
+ EXPONENT_MASK
;
67 static_assert(EXP_MANT_MASK
== ~SIGN_MASK
,
68 "Exponent and mantissa masks are not as expected.");
70 // If a number x is a NAN, then it is a quiet NAN if:
71 // QuietNaNMask & bits(x) != 0
72 // Else, it is a signalling NAN.
73 static constexpr BitsType QUIET_NAN_MASK
= 0x0008000000000000ULL
;
76 #if defined(LONG_DOUBLE_IS_DOUBLE)
77 // Properties for numbers represented in 64 bits long double on Windows
79 template <> struct FloatProperties
<long double> {
80 typedef uint64_t BitsType
;
81 static_assert(sizeof(BitsType
) == sizeof(double),
82 "Unexpected size of 'double' type.");
84 static constexpr uint32_t BIT_WIDTH
= FloatProperties
<double>::BIT_WIDTH
;
86 static constexpr uint32_t MANTISSA_WIDTH
=
87 FloatProperties
<double>::MANTISSA_WIDTH
;
88 static constexpr uint32_t MANTISSA_PRECISION
= MANTISSA_WIDTH
+ 1;
89 static constexpr uint32_t EXPONENT_WIDTH
=
90 FloatProperties
<double>::EXPONENT_WIDTH
;
91 static constexpr BitsType MANTISSA_MASK
=
92 FloatProperties
<double>::MANTISSA_MASK
;
93 static constexpr BitsType SIGN_MASK
= FloatProperties
<double>::SIGN_MASK
;
94 static constexpr BitsType EXPONENT_MASK
=
95 FloatProperties
<double>::EXPONENT_MASK
;
96 static constexpr uint32_t EXPONENT_BIAS
=
97 FloatProperties
<double>::EXPONENT_BIAS
;
99 static constexpr BitsType EXP_MANT_MASK
=
100 FloatProperties
<double>::EXP_MANT_MASK
;
101 static_assert(EXP_MANT_MASK
== ~SIGN_MASK
,
102 "Exponent and mantissa masks are not as expected.");
104 // If a number x is a NAN, then it is a quiet NAN if:
105 // QuietNaNMask & bits(x) != 0
106 // Else, it is a signalling NAN.
107 static constexpr BitsType QUIET_NAN_MASK
=
108 FloatProperties
<double>::QUIET_NAN_MASK
;
110 #elif defined(SPECIAL_X86_LONG_DOUBLE)
111 // Properties for numbers represented in 80 bits long double on non-Windows x86
113 template <> struct FloatProperties
<long double> {
114 typedef UInt128 BitsType
;
115 static_assert(sizeof(BitsType
) == sizeof(long double),
116 "Unexpected size of 'long double' type.");
118 static constexpr uint32_t BIT_WIDTH
= (sizeof(BitsType
) * 8) - 48;
119 static constexpr BitsType FULL_WIDTH_MASK
= ((BitsType(1) << BIT_WIDTH
) - 1);
121 static constexpr uint32_t MANTISSA_WIDTH
= 63;
122 static constexpr uint32_t MANTISSA_PRECISION
= MANTISSA_WIDTH
+ 1;
123 static constexpr uint32_t EXPONENT_WIDTH
= 15;
124 static constexpr BitsType MANTISSA_MASK
= (BitsType(1) << MANTISSA_WIDTH
) - 1;
126 // The x86 80 bit float represents the leading digit of the mantissa
127 // explicitly. This is the mask for that bit.
128 static constexpr BitsType EXPLICIT_BIT_MASK
= (BitsType(1) << MANTISSA_WIDTH
);
130 static constexpr BitsType SIGN_MASK
=
131 BitsType(1) << (EXPONENT_WIDTH
+ MANTISSA_WIDTH
+ 1);
132 static constexpr BitsType EXPONENT_MASK
=
133 ((BitsType(1) << EXPONENT_WIDTH
) - 1) << (MANTISSA_WIDTH
+ 1);
134 static constexpr uint32_t EXPONENT_BIAS
= 16383;
136 static constexpr BitsType EXP_MANT_MASK
=
137 MANTISSA_MASK
| EXPLICIT_BIT_MASK
| EXPONENT_MASK
;
138 static_assert(EXP_MANT_MASK
== (~SIGN_MASK
& FULL_WIDTH_MASK
),
139 "Exponent and mantissa masks are not as expected.");
141 // If a number x is a NAN, then it is a quiet NAN if:
142 // QuietNaNMask & bits(x) != 0
143 // Else, it is a signalling NAN.
144 static constexpr BitsType QUIET_NAN_MASK
= BitsType(1)
145 << (MANTISSA_WIDTH
- 1);
148 // Properties for numbers represented in 128 bits long double on non x86
150 template <> struct FloatProperties
<long double> {
151 typedef UInt128 BitsType
;
152 static_assert(sizeof(BitsType
) == sizeof(long double),
153 "Unexpected size of 'long double' type.");
155 static constexpr uint32_t BIT_WIDTH
= sizeof(BitsType
) << 3;
157 static constexpr uint32_t MANTISSA_WIDTH
= 112;
158 static constexpr uint32_t MANTISSA_PRECISION
= MANTISSA_WIDTH
+ 1;
159 static constexpr uint32_t EXPONENT_WIDTH
= 15;
160 static constexpr BitsType MANTISSA_MASK
= (BitsType(1) << MANTISSA_WIDTH
) - 1;
161 static constexpr BitsType SIGN_MASK
= BitsType(1)
162 << (EXPONENT_WIDTH
+ MANTISSA_WIDTH
);
163 static constexpr BitsType EXPONENT_MASK
= ~(SIGN_MASK
| MANTISSA_MASK
);
164 static constexpr uint32_t EXPONENT_BIAS
= 16383;
166 static constexpr BitsType EXP_MANT_MASK
= MANTISSA_MASK
| EXPONENT_MASK
;
167 static_assert(EXP_MANT_MASK
== ~SIGN_MASK
,
168 "Exponent and mantissa masks are not as expected.");
170 // If a number x is a NAN, then it is a quiet NAN if:
171 // QuietNaNMask & bits(x) != 0
172 // Else, it is a signalling NAN.
173 static constexpr BitsType QUIET_NAN_MASK
= BitsType(1)
174 << (MANTISSA_WIDTH
- 1);
178 // Define the float type corresponding to the BitsType.
179 template <typename BitsType
> struct FloatType
;
181 template <> struct FloatType
<uint32_t> {
182 static_assert(sizeof(uint32_t) == sizeof(float),
183 "Unexpected size of 'float' type.");
187 template <> struct FloatType
<uint64_t> {
188 static_assert(sizeof(uint64_t) == sizeof(double),
189 "Unexpected size of 'double' type.");
193 template <typename BitsType
>
194 using FloatTypeT
= typename FloatType
<BitsType
>::Type
;
196 } // namespace fputil
197 } // namespace __llvm_libc
199 #endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_FLOAT_PROPERTIES_H