Skip to content

Commit 213c498

Browse files
authored
[reland][libc][NFC] Implement FPBits in terms of FloatProperties to reduce clutter (#75196) (#75318)
Also make type naming consistent by using `UIntType` instead of `intU_t`. This patch is a reland of #75196 but does not include the "use `FPBits` instead of `FPBits_t`, `FPB`" part. This needs more work.
1 parent bdbc2db commit 213c498

File tree

13 files changed

+106
-109
lines changed

13 files changed

+106
-109
lines changed

libc/src/__support/FPUtil/FPBits.h

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -36,71 +36,74 @@ template <typename T> struct ExponentWidth {
3636
// floating numbers. On x86 platforms however, the 'long double' type maps to
3737
// an x87 floating point format. This format is an IEEE 754 extension format.
3838
// It is handled as an explicit specialization of this class.
39-
template <typename T> struct FPBits {
39+
template <typename T> struct FPBits : private FloatProperties<T> {
4040
static_assert(cpp::is_floating_point_v<T>,
4141
"FPBits instantiated with invalid type.");
42+
using typename FloatProperties<T>::UIntType;
43+
using FloatProperties<T>::BIT_WIDTH;
44+
using FloatProperties<T>::EXP_MANT_MASK;
45+
using FloatProperties<T>::EXPONENT_MASK;
46+
using FloatProperties<T>::EXPONENT_BIAS;
47+
using FloatProperties<T>::EXPONENT_WIDTH;
48+
using FloatProperties<T>::MANTISSA_MASK;
49+
using FloatProperties<T>::MANTISSA_WIDTH;
50+
using FloatProperties<T>::QUIET_NAN_MASK;
51+
using FloatProperties<T>::SIGN_MASK;
4252

4353
// Reinterpreting bits as an integer value and interpreting the bits of an
4454
// integer value as a floating point value is used in tests. So, a convenient
4555
// type is provided for such reinterpretations.
46-
using FloatProp = FloatProperties<T>;
47-
using UIntType = typename FloatProp::UIntType;
48-
4956
UIntType bits;
5057

5158
LIBC_INLINE constexpr void set_mantissa(UIntType mantVal) {
52-
mantVal &= (FloatProp::MANTISSA_MASK);
53-
bits &= ~(FloatProp::MANTISSA_MASK);
59+
mantVal &= MANTISSA_MASK;
60+
bits &= ~MANTISSA_MASK;
5461
bits |= mantVal;
5562
}
5663

5764
LIBC_INLINE constexpr UIntType get_mantissa() const {
58-
return bits & FloatProp::MANTISSA_MASK;
65+
return bits & MANTISSA_MASK;
5966
}
6067

6168
LIBC_INLINE constexpr void set_biased_exponent(UIntType expVal) {
62-
expVal = (expVal << (FloatProp::MANTISSA_WIDTH)) & FloatProp::EXPONENT_MASK;
63-
bits &= ~(FloatProp::EXPONENT_MASK);
69+
expVal = (expVal << MANTISSA_WIDTH) & EXPONENT_MASK;
70+
bits &= ~EXPONENT_MASK;
6471
bits |= expVal;
6572
}
6673

6774
LIBC_INLINE constexpr uint16_t get_biased_exponent() const {
68-
return uint16_t((bits & FloatProp::EXPONENT_MASK) >>
69-
(FloatProp::MANTISSA_WIDTH));
75+
return uint16_t((bits & EXPONENT_MASK) >> MANTISSA_WIDTH);
7076
}
7177

7278
// The function return mantissa with the implicit bit set iff the current
7379
// value is a valid normal number.
7480
LIBC_INLINE constexpr UIntType get_explicit_mantissa() {
7581
return ((get_biased_exponent() > 0 && !is_inf_or_nan())
76-
? (FloatProp::MANTISSA_MASK + 1)
82+
? (MANTISSA_MASK + 1)
7783
: 0) |
78-
(FloatProp::MANTISSA_MASK & bits);
84+
(MANTISSA_MASK & bits);
7985
}
8086

8187
LIBC_INLINE constexpr void set_sign(bool signVal) {
82-
bits |= FloatProp::SIGN_MASK;
88+
bits |= SIGN_MASK;
8389
if (!signVal)
84-
bits -= FloatProp::SIGN_MASK;
90+
bits -= SIGN_MASK;
8591
}
8692

8793
LIBC_INLINE constexpr bool get_sign() const {
88-
return (bits & FloatProp::SIGN_MASK) != 0;
94+
return (bits & SIGN_MASK) != 0;
8995
}
9096

9197
static_assert(sizeof(T) == sizeof(UIntType),
9298
"Data type and integral representation have different sizes.");
9399

94-
static constexpr int EXPONENT_BIAS = (1 << (ExponentWidth<T>::VALUE - 1)) - 1;
95-
static constexpr int MAX_EXPONENT = (1 << ExponentWidth<T>::VALUE) - 1;
100+
static constexpr int MAX_EXPONENT = (1 << EXPONENT_WIDTH) - 1;
96101

97102
static constexpr UIntType MIN_SUBNORMAL = UIntType(1);
98-
static constexpr UIntType MAX_SUBNORMAL =
99-
(UIntType(1) << MantissaWidth<T>::VALUE) - 1;
100-
static constexpr UIntType MIN_NORMAL =
101-
(UIntType(1) << MantissaWidth<T>::VALUE);
103+
static constexpr UIntType MAX_SUBNORMAL = (UIntType(1) << MANTISSA_WIDTH) - 1;
104+
static constexpr UIntType MIN_NORMAL = (UIntType(1) << MANTISSA_WIDTH);
102105
static constexpr UIntType MAX_NORMAL =
103-
((UIntType(MAX_EXPONENT) - 1) << MantissaWidth<T>::VALUE) | MAX_SUBNORMAL;
106+
((UIntType(MAX_EXPONENT) - 1) << MANTISSA_WIDTH) | MAX_SUBNORMAL;
104107

105108
// We don't want accidental type promotions/conversions, so we require exact
106109
// type match.
@@ -151,32 +154,29 @@ template <typename T> struct FPBits {
151154
}
152155

153156
LIBC_INLINE constexpr bool is_inf() const {
154-
return (bits & FloatProp::EXP_MANT_MASK) == FloatProp::EXPONENT_MASK;
157+
return (bits & EXP_MANT_MASK) == EXPONENT_MASK;
155158
}
156159

157160
LIBC_INLINE constexpr bool is_nan() const {
158-
return (bits & FloatProp::EXP_MANT_MASK) > FloatProp::EXPONENT_MASK;
161+
return (bits & EXP_MANT_MASK) > EXPONENT_MASK;
159162
}
160163

161164
LIBC_INLINE constexpr bool is_quiet_nan() const {
162-
return (bits & FloatProp::EXP_MANT_MASK) ==
163-
(FloatProp::EXPONENT_MASK | FloatProp::QUIET_NAN_MASK);
165+
return (bits & EXP_MANT_MASK) == (EXPONENT_MASK | QUIET_NAN_MASK);
164166
}
165167

166168
LIBC_INLINE constexpr bool is_inf_or_nan() const {
167-
return (bits & FloatProp::EXPONENT_MASK) == FloatProp::EXPONENT_MASK;
169+
return (bits & EXPONENT_MASK) == EXPONENT_MASK;
168170
}
169171

170172
LIBC_INLINE static constexpr T zero(bool sign = false) {
171-
return FPBits(sign ? FloatProp::SIGN_MASK : UIntType(0)).get_val();
173+
return FPBits(sign ? SIGN_MASK : UIntType(0)).get_val();
172174
}
173175

174176
LIBC_INLINE static constexpr T neg_zero() { return zero(true); }
175177

176178
LIBC_INLINE static constexpr T inf(bool sign = false) {
177-
return FPBits((sign ? FloatProp::SIGN_MASK : UIntType(0)) |
178-
FloatProp::EXPONENT_MASK)
179-
.get_val();
179+
return FPBits((sign ? SIGN_MASK : UIntType(0)) | EXPONENT_MASK).get_val();
180180
}
181181

182182
LIBC_INLINE static constexpr T neg_inf() { return inf(true); }
@@ -204,7 +204,7 @@ template <typename T> struct FPBits {
204204
}
205205

206206
LIBC_INLINE static constexpr T build_quiet_nan(UIntType v) {
207-
return build_nan(FloatProp::QUIET_NAN_MASK | v);
207+
return build_nan(QUIET_NAN_MASK | v);
208208
}
209209

210210
// The function convert integer number and unbiased exponent to proper float
@@ -220,7 +220,7 @@ template <typename T> struct FPBits {
220220
LIBC_INLINE static constexpr FPBits<T> make_value(UIntType number, int ep) {
221221
FPBits<T> result;
222222
// offset: +1 for sign, but -1 for implicit first bit
223-
int lz = cpp::countl_zero(number) - FloatProp::EXPONENT_WIDTH;
223+
int lz = cpp::countl_zero(number) - EXPONENT_WIDTH;
224224
number <<= lz;
225225
ep -= lz;
226226

libc/src/__support/FPUtil/generic/FMod.h

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,11 @@ template <typename T> struct FModFastMathWrapper {
167167

168168
template <typename T> class FModDivisionSimpleHelper {
169169
private:
170-
using intU_t = typename FPBits<T>::UIntType;
170+
using UIntType = typename FPBits<T>::UIntType;
171171

172172
public:
173-
LIBC_INLINE constexpr static intU_t
174-
execute(int exp_diff, int sides_zeroes_count, intU_t m_x, intU_t m_y) {
173+
LIBC_INLINE constexpr static UIntType
174+
execute(int exp_diff, int sides_zeroes_count, UIntType m_x, UIntType m_y) {
175175
while (exp_diff > sides_zeroes_count) {
176176
exp_diff -= sides_zeroes_count;
177177
m_x <<= sides_zeroes_count;
@@ -186,23 +186,22 @@ template <typename T> class FModDivisionSimpleHelper {
186186
template <typename T> class FModDivisionInvMultHelper {
187187
private:
188188
using FPB = FPBits<T>;
189-
using intU_t = typename FPB::UIntType;
189+
using UIntType = typename FPB::UIntType;
190190

191191
public:
192-
LIBC_INLINE constexpr static intU_t
193-
execute(int exp_diff, int sides_zeroes_count, intU_t m_x, intU_t m_y) {
192+
LIBC_INLINE constexpr static UIntType
193+
execute(int exp_diff, int sides_zeroes_count, UIntType m_x, UIntType m_y) {
194194
if (exp_diff > sides_zeroes_count) {
195-
intU_t inv_hy = (cpp::numeric_limits<intU_t>::max() / m_y);
195+
UIntType inv_hy = (cpp::numeric_limits<UIntType>::max() / m_y);
196196
while (exp_diff > sides_zeroes_count) {
197197
exp_diff -= sides_zeroes_count;
198-
intU_t hd =
199-
(m_x * inv_hy) >> (FPB::FloatProp::BIT_WIDTH - sides_zeroes_count);
198+
UIntType hd = (m_x * inv_hy) >> (FPB::BIT_WIDTH - sides_zeroes_count);
200199
m_x <<= sides_zeroes_count;
201200
m_x -= hd * m_y;
202201
while (LIBC_UNLIKELY(m_x > m_y))
203202
m_x -= m_y;
204203
}
205-
intU_t hd = (m_x * inv_hy) >> (FPB::FloatProp::BIT_WIDTH - exp_diff);
204+
UIntType hd = (m_x * inv_hy) >> (FPB::BIT_WIDTH - exp_diff);
206205
m_x <<= exp_diff;
207206
m_x -= hd * m_y;
208207
while (LIBC_UNLIKELY(m_x > m_y))
@@ -223,7 +222,7 @@ class FMod {
223222

224223
private:
225224
using FPB = FPBits<T>;
226-
using intU_t = typename FPB::UIntType;
225+
using UIntType = typename FPB::UIntType;
227226

228227
LIBC_INLINE static constexpr FPB eval_internal(FPB sx, FPB sy) {
229228

@@ -237,11 +236,11 @@ class FMod {
237236
int e_y = sy.get_biased_exponent();
238237

239238
// Most common case where |y| is "very normal" and |x/y| < 2^EXPONENT_WIDTH
240-
if (LIBC_LIKELY(e_y > int(FPB::FloatProp::MANTISSA_WIDTH) &&
241-
e_x - e_y <= int(FPB::FloatProp::EXPONENT_WIDTH))) {
242-
intU_t m_x = sx.get_explicit_mantissa();
243-
intU_t m_y = sy.get_explicit_mantissa();
244-
intU_t d = (e_x == e_y) ? (m_x - m_y) : (m_x << (e_x - e_y)) % m_y;
239+
if (LIBC_LIKELY(e_y > int(FPB::MANTISSA_WIDTH) &&
240+
e_x - e_y <= int(FPB::EXPONENT_WIDTH))) {
241+
UIntType m_x = sx.get_explicit_mantissa();
242+
UIntType m_y = sy.get_explicit_mantissa();
243+
UIntType d = (e_x == e_y) ? (m_x - m_y) : (m_x << (e_x - e_y)) % m_y;
245244
if (d == 0)
246245
return FPB(FPB::zero());
247246
// iy - 1 because of "zero power" for number with power 1
@@ -255,11 +254,11 @@ class FMod {
255254
}
256255

257256
// Note that hx is not subnormal by conditions above.
258-
intU_t m_x = sx.get_explicit_mantissa();
257+
UIntType m_x = sx.get_explicit_mantissa();
259258
e_x--;
260259

261-
intU_t m_y = sy.get_explicit_mantissa();
262-
int lead_zeros_m_y = FPB::FloatProp::EXPONENT_WIDTH;
260+
UIntType m_y = sy.get_explicit_mantissa();
261+
int lead_zeros_m_y = FPB::EXPONENT_WIDTH;
263262
if (LIBC_LIKELY(e_y > 0)) {
264263
e_y--;
265264
} else {
@@ -282,9 +281,8 @@ class FMod {
282281

283282
{
284283
// Shift hx left until the end or n = 0
285-
int left_shift = exp_diff < int(FPB::FloatProp::EXPONENT_WIDTH)
286-
? exp_diff
287-
: FPB::FloatProp::EXPONENT_WIDTH;
284+
int left_shift =
285+
exp_diff < int(FPB::EXPONENT_WIDTH) ? exp_diff : FPB::EXPONENT_WIDTH;
288286
m_x <<= left_shift;
289287
exp_diff -= left_shift;
290288
}

libc/src/__support/FPUtil/x86_64/LongDoubleBits.h

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,18 @@
2626
namespace LIBC_NAMESPACE {
2727
namespace fputil {
2828

29-
template <> struct FPBits<long double> {
30-
using UIntType = UInt128;
29+
template <> struct FPBits<long double> : private FloatProperties<long double> {
30+
using typename FloatProperties<long double>::UIntType;
31+
using FloatProperties<long double>::BIT_WIDTH;
32+
using FloatProperties<long double>::EXP_MANT_MASK;
33+
using FloatProperties<long double>::EXPONENT_MASK;
34+
using FloatProperties<long double>::EXPONENT_BIAS;
35+
using FloatProperties<long double>::EXPONENT_WIDTH;
36+
using FloatProperties<long double>::MANTISSA_MASK;
37+
using FloatProperties<long double>::MANTISSA_WIDTH;
38+
using FloatProperties<long double>::QUIET_NAN_MASK;
39+
using FloatProperties<long double>::SIGN_MASK;
3140

32-
static constexpr int EXPONENT_BIAS = 0x3FFF;
3341
static constexpr int MAX_EXPONENT = 0x7FFF;
3442
static constexpr UIntType MIN_SUBNORMAL = UIntType(1);
3543
// Subnormal numbers include the implicit bit in x86 long double formats.
@@ -41,59 +49,52 @@ template <> struct FPBits<long double> {
4149
(UIntType(MAX_EXPONENT - 1) << (MantissaWidth<long double>::VALUE + 1)) |
4250
(UIntType(1) << MantissaWidth<long double>::VALUE) | MAX_SUBNORMAL;
4351

44-
using FloatProp = FloatProperties<long double>;
45-
4652
UIntType bits;
4753

4854
LIBC_INLINE constexpr void set_mantissa(UIntType mantVal) {
49-
mantVal &= (FloatProp::MANTISSA_MASK);
50-
bits &= ~(FloatProp::MANTISSA_MASK);
55+
mantVal &= MANTISSA_MASK;
56+
bits &= ~MANTISSA_MASK;
5157
bits |= mantVal;
5258
}
5359

5460
LIBC_INLINE constexpr UIntType get_mantissa() const {
55-
return bits & FloatProp::MANTISSA_MASK;
61+
return bits & MANTISSA_MASK;
5662
}
5763

5864
LIBC_INLINE constexpr UIntType get_explicit_mantissa() const {
5965
// The x86 80 bit float represents the leading digit of the mantissa
6066
// explicitly. This is the mask for that bit.
61-
constexpr UIntType EXPLICIT_BIT_MASK =
62-
(UIntType(1) << FloatProp::MANTISSA_WIDTH);
63-
return bits & (FloatProp::MANTISSA_MASK | EXPLICIT_BIT_MASK);
67+
constexpr UIntType EXPLICIT_BIT_MASK = UIntType(1) << MANTISSA_WIDTH;
68+
return bits & (MANTISSA_MASK | EXPLICIT_BIT_MASK);
6469
}
6570

6671
LIBC_INLINE constexpr void set_biased_exponent(UIntType expVal) {
67-
expVal =
68-
(expVal << (FloatProp::BIT_WIDTH - 1 - FloatProp::EXPONENT_WIDTH)) &
69-
FloatProp::EXPONENT_MASK;
70-
bits &= ~(FloatProp::EXPONENT_MASK);
72+
expVal = (expVal << (BIT_WIDTH - 1 - EXPONENT_WIDTH)) & EXPONENT_MASK;
73+
bits &= ~EXPONENT_MASK;
7174
bits |= expVal;
7275
}
7376

7477
LIBC_INLINE constexpr uint16_t get_biased_exponent() const {
75-
return uint16_t((bits & FloatProp::EXPONENT_MASK) >>
76-
(FloatProp::BIT_WIDTH - 1 - FloatProp::EXPONENT_WIDTH));
78+
return uint16_t((bits & EXPONENT_MASK) >> (BIT_WIDTH - 1 - EXPONENT_WIDTH));
7779
}
7880

7981
LIBC_INLINE constexpr void set_implicit_bit(bool implicitVal) {
80-
bits &= ~(UIntType(1) << FloatProp::MANTISSA_WIDTH);
81-
bits |= (UIntType(implicitVal) << FloatProp::MANTISSA_WIDTH);
82+
bits &= ~(UIntType(1) << MANTISSA_WIDTH);
83+
bits |= (UIntType(implicitVal) << MANTISSA_WIDTH);
8284
}
8385

8486
LIBC_INLINE constexpr bool get_implicit_bit() const {
85-
return bool((bits & (UIntType(1) << FloatProp::MANTISSA_WIDTH)) >>
86-
FloatProp::MANTISSA_WIDTH);
87+
return bool((bits & (UIntType(1) << MANTISSA_WIDTH)) >> MANTISSA_WIDTH);
8788
}
8889

8990
LIBC_INLINE constexpr void set_sign(bool signVal) {
90-
bits &= ~(FloatProp::SIGN_MASK);
91-
UIntType sign1 = UIntType(signVal) << (FloatProp::BIT_WIDTH - 1);
91+
bits &= ~SIGN_MASK;
92+
UIntType sign1 = UIntType(signVal) << (BIT_WIDTH - 1);
9293
bits |= sign1;
9394
}
9495

9596
LIBC_INLINE constexpr bool get_sign() const {
96-
return bool((bits & FloatProp::SIGN_MASK) >> (FloatProp::BIT_WIDTH - 1));
97+
return bool((bits & SIGN_MASK) >> (BIT_WIDTH - 1));
9798
}
9899

99100
LIBC_INLINE constexpr FPBits() : bits(0) {}
@@ -117,7 +118,7 @@ template <> struct FPBits<long double> {
117118

118119
LIBC_INLINE constexpr UIntType uintval() {
119120
// We zero the padding bits as they can contain garbage.
120-
return bits & FloatProp::FP_MASK;
121+
return bits & FP_MASK;
121122
}
122123

123124
LIBC_INLINE constexpr long double get_val() const {
@@ -196,7 +197,7 @@ template <> struct FPBits<long double> {
196197
}
197198

198199
LIBC_INLINE static constexpr long double build_quiet_nan(UIntType v) {
199-
return build_nan(FloatProp::QUIET_NAN_MASK | v);
200+
return build_nan(QUIET_NAN_MASK | v);
200201
}
201202

202203
LIBC_INLINE static constexpr long double min_normal() {

0 commit comments

Comments
 (0)