Skip to content

Commit 7e761ba

Browse files
authored
[libc][NFC] Simplify FloatProperties implementation (#74481)
Factor in common properties of `FloatProperties`. This is a first patch of a series to simplify `FloatProperties` and `FPBits` implementations.
1 parent c703e65 commit 7e761ba

File tree

1 file changed

+94
-37
lines changed

1 file changed

+94
-37
lines changed

libc/src/__support/FPUtil/FloatProperties.h

Lines changed: 94 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOATPROPERTIES_H
1111

1212
#include "src/__support/UInt128.h"
13-
#include "src/__support/macros/attributes.h" // LIBC_INLINE
13+
#include "src/__support/macros/attributes.h" // LIBC_INLINE, LIBC_INLINE_VAR
1414
#include "src/__support/macros/properties/float.h" // LIBC_COMPILER_HAS_FLOAT128
1515

1616
#include <stdint.h>
@@ -27,22 +27,98 @@ enum class FPType {
2727
X86_Binary80,
2828
};
2929

30-
template <FPType> struct FPProperties {};
31-
template <> struct FPProperties<FPType::IEEE754_Binary32> {
32-
typedef uint32_t BitsType;
30+
// For now 'FPEncoding', 'FPBaseProperties' and 'FPCommonProperties' are
31+
// implementation details.
32+
namespace internal {
33+
34+
// The type of encoding for supported floating point types.
35+
enum class FPEncoding {
36+
IEEE754,
37+
X86_ExtendedPrecision,
38+
};
39+
40+
template <FPType> struct FPBaseProperties {};
41+
42+
template <> struct FPBaseProperties<FPType::IEEE754_Binary16> {
43+
using UIntType = uint16_t;
44+
LIBC_INLINE_VAR static constexpr int TOTAL_BITS = 16;
45+
LIBC_INLINE_VAR static constexpr int SIG_BITS = 10;
46+
LIBC_INLINE_VAR static constexpr int EXP_BITS = 5;
47+
LIBC_INLINE_VAR static constexpr auto ENCODING = FPEncoding::IEEE754;
48+
};
49+
50+
template <> struct FPBaseProperties<FPType::IEEE754_Binary32> {
51+
using UIntType = uint32_t;
52+
LIBC_INLINE_VAR static constexpr int TOTAL_BITS = 32;
53+
LIBC_INLINE_VAR static constexpr int SIG_BITS = 23;
54+
LIBC_INLINE_VAR static constexpr int EXP_BITS = 8;
55+
LIBC_INLINE_VAR static constexpr auto ENCODING = FPEncoding::IEEE754;
56+
};
57+
58+
template <> struct FPBaseProperties<FPType::IEEE754_Binary64> {
59+
using UIntType = uint64_t;
60+
LIBC_INLINE_VAR static constexpr int TOTAL_BITS = 64;
61+
LIBC_INLINE_VAR static constexpr int SIG_BITS = 52;
62+
LIBC_INLINE_VAR static constexpr int EXP_BITS = 11;
63+
LIBC_INLINE_VAR static constexpr auto ENCODING = FPEncoding::IEEE754;
64+
};
65+
66+
template <> struct FPBaseProperties<FPType::IEEE754_Binary128> {
67+
using UIntType = UInt128;
68+
LIBC_INLINE_VAR static constexpr int TOTAL_BITS = 128;
69+
LIBC_INLINE_VAR static constexpr int SIG_BITS = 112;
70+
LIBC_INLINE_VAR static constexpr int EXP_BITS = 15;
71+
LIBC_INLINE_VAR static constexpr auto ENCODING = FPEncoding::IEEE754;
72+
};
73+
74+
template <> struct FPBaseProperties<FPType::X86_Binary80> {
75+
using UIntType = UInt128;
76+
LIBC_INLINE_VAR static constexpr int TOTAL_BITS = 80;
77+
LIBC_INLINE_VAR static constexpr int SIG_BITS = 64;
78+
LIBC_INLINE_VAR static constexpr int EXP_BITS = 15;
79+
LIBC_INLINE_VAR static constexpr auto ENCODING =
80+
FPEncoding::X86_ExtendedPrecision;
81+
};
82+
83+
// Derives more properties from 'FPBaseProperties' above.
84+
// This class serves as a halfway point between 'FPBaseProperties' and
85+
// 'FPProperties' below.
86+
template <FPType fp_type>
87+
struct FPCommonProperties : private FPBaseProperties<fp_type> {
88+
using UP = FPBaseProperties<fp_type>;
89+
using BitsType = typename UP::UIntType;
90+
91+
LIBC_INLINE_VAR static constexpr uint32_t BIT_WIDTH = UP::TOTAL_BITS;
92+
LIBC_INLINE_VAR static constexpr uint32_t MANTISSA_WIDTH = UP::SIG_BITS;
93+
LIBC_INLINE_VAR static constexpr uint32_t EXPONENT_WIDTH = UP::EXP_BITS;
94+
95+
// The exponent bias. Always positive.
96+
LIBC_INLINE_VAR static constexpr uint32_t EXPONENT_BIAS =
97+
(1U << (UP::EXP_BITS - 1U)) - 1U;
98+
static_assert(EXPONENT_BIAS > 0);
99+
};
100+
101+
} // namespace internal
33102

34-
static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) * 8;
103+
template <FPType> struct FPProperties {};
35104

36-
static constexpr uint32_t MANTISSA_WIDTH = 23;
105+
// ----------------
106+
// Work In Progress
107+
// ----------------
108+
// The 'FPProperties' template specializations below are being slowly replaced
109+
// with properties from 'FPCommonProperties' above. Once specializations are
110+
// empty, 'FPProperties' declaration can be fully replace with
111+
// 'FPCommonProperties' implementation.
112+
113+
template <>
114+
struct FPProperties<FPType::IEEE754_Binary32>
115+
: public internal::FPCommonProperties<FPType::IEEE754_Binary32> {
37116
// The mantissa precision includes the implicit bit.
38117
static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
39-
static constexpr uint32_t EXPONENT_WIDTH = 8;
40118
static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
41119
static constexpr BitsType SIGN_MASK = BitsType(1)
42120
<< (EXPONENT_WIDTH + MANTISSA_WIDTH);
43121
static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
44-
static constexpr uint32_t EXPONENT_BIAS = 127;
45-
46122
static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK + EXPONENT_MASK;
47123
static_assert(EXP_MANT_MASK == ~SIGN_MASK,
48124
"Exponent and mantissa masks are not as expected.");
@@ -53,20 +129,14 @@ template <> struct FPProperties<FPType::IEEE754_Binary32> {
53129
static constexpr BitsType QUIET_NAN_MASK = 0x00400000U;
54130
};
55131

56-
template <> struct FPProperties<FPType::IEEE754_Binary64> {
57-
typedef uint64_t BitsType;
58-
59-
static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) * 8;
60-
61-
static constexpr uint32_t MANTISSA_WIDTH = 52;
132+
template <>
133+
struct FPProperties<FPType::IEEE754_Binary64>
134+
: public internal::FPCommonProperties<FPType::IEEE754_Binary64> {
62135
static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
63-
static constexpr uint32_t EXPONENT_WIDTH = 11;
64136
static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
65137
static constexpr BitsType SIGN_MASK = BitsType(1)
66138
<< (EXPONENT_WIDTH + MANTISSA_WIDTH);
67139
static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
68-
static constexpr uint32_t EXPONENT_BIAS = 1023;
69-
70140
static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK + EXPONENT_MASK;
71141
static_assert(EXP_MANT_MASK == ~SIGN_MASK,
72142
"Exponent and mantissa masks are not as expected.");
@@ -79,27 +149,20 @@ template <> struct FPProperties<FPType::IEEE754_Binary64> {
79149

80150
// Properties for numbers represented in 80 bits long double on non-Windows x86
81151
// platforms.
82-
template <> struct FPProperties<FPType::X86_Binary80> {
83-
typedef UInt128 BitsType;
84-
85-
static constexpr uint32_t BIT_WIDTH = (sizeof(BitsType) * 8) - 48;
152+
template <>
153+
struct FPProperties<FPType::X86_Binary80>
154+
: public internal::FPCommonProperties<FPType::X86_Binary80> {
86155
static constexpr BitsType FULL_WIDTH_MASK = ((BitsType(1) << BIT_WIDTH) - 1);
87-
88156
static constexpr uint32_t MANTISSA_WIDTH = 63;
89157
static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
90-
static constexpr uint32_t EXPONENT_WIDTH = 15;
91158
static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
92-
93159
// The x86 80 bit float represents the leading digit of the mantissa
94160
// explicitly. This is the mask for that bit.
95161
static constexpr BitsType EXPLICIT_BIT_MASK = (BitsType(1) << MANTISSA_WIDTH);
96-
97162
static constexpr BitsType SIGN_MASK =
98163
BitsType(1) << (EXPONENT_WIDTH + MANTISSA_WIDTH + 1);
99164
static constexpr BitsType EXPONENT_MASK =
100165
((BitsType(1) << EXPONENT_WIDTH) - 1) << (MANTISSA_WIDTH + 1);
101-
static constexpr uint32_t EXPONENT_BIAS = 16383;
102-
103166
static constexpr BitsType EXP_MANT_MASK =
104167
MANTISSA_MASK | EXPLICIT_BIT_MASK | EXPONENT_MASK;
105168
static_assert(EXP_MANT_MASK == (~SIGN_MASK & FULL_WIDTH_MASK),
@@ -114,20 +177,14 @@ template <> struct FPProperties<FPType::X86_Binary80> {
114177

115178
// Properties for numbers represented in 128 bits long double on non x86
116179
// platform.
117-
template <> struct FPProperties<FPType::IEEE754_Binary128> {
118-
typedef UInt128 BitsType;
119-
120-
static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3;
121-
122-
static constexpr uint32_t MANTISSA_WIDTH = 112;
180+
template <>
181+
struct FPProperties<FPType::IEEE754_Binary128>
182+
: public internal::FPCommonProperties<FPType::IEEE754_Binary128> {
123183
static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
124-
static constexpr uint32_t EXPONENT_WIDTH = 15;
125184
static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
126185
static constexpr BitsType SIGN_MASK = BitsType(1)
127186
<< (EXPONENT_WIDTH + MANTISSA_WIDTH);
128187
static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
129-
static constexpr uint32_t EXPONENT_BIAS = 16383;
130-
131188
static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK | EXPONENT_MASK;
132189
static_assert(EXP_MANT_MASK == ~SIGN_MASK,
133190
"Exponent and mantissa masks are not as expected.");

0 commit comments

Comments
 (0)