Skip to content

Commit d2361b2

Browse files
authored
[libc][math] Add min/max/min_denorm/max_denorm constants to FPBits and clean up its constants return types. (#71298)
1 parent ee10005 commit d2361b2

19 files changed

+484
-505
lines changed

libc/src/__support/FPUtil/FPBits.h

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ template <typename T> struct FPBits {
114114
cpp::enable_if_t<cpp::is_same_v<XType, UIntType>, int> = 0>
115115
constexpr explicit FPBits(XType x) : bits(x) {}
116116

117-
FPBits() : bits(0) {}
117+
constexpr FPBits() : bits(0) {}
118118

119119
LIBC_INLINE constexpr T get_val() const { return cpp::bit_cast<T>(bits); }
120120

@@ -169,30 +169,38 @@ template <typename T> struct FPBits {
169169
return (bits & FloatProp::EXPONENT_MASK) == FloatProp::EXPONENT_MASK;
170170
}
171171

172-
LIBC_INLINE static constexpr FPBits<T> zero(bool sign = false) {
173-
return FPBits(sign ? FloatProp::SIGN_MASK : UIntType(0));
172+
LIBC_INLINE static constexpr T zero(bool sign = false) {
173+
return FPBits(sign ? FloatProp::SIGN_MASK : UIntType(0)).get_val();
174174
}
175175

176-
LIBC_INLINE static constexpr FPBits<T> neg_zero() { return zero(true); }
176+
LIBC_INLINE static constexpr T neg_zero() { return zero(true); }
177177

178-
LIBC_INLINE static constexpr FPBits<T> inf(bool sign = false) {
179-
FPBits<T> bits(sign ? FloatProp::SIGN_MASK : UIntType(0));
180-
bits.set_unbiased_exponent(MAX_EXPONENT);
181-
return bits;
178+
LIBC_INLINE static constexpr T inf(bool sign = false) {
179+
return FPBits((sign ? FloatProp::SIGN_MASK : UIntType(0)) |
180+
FloatProp::EXPONENT_MASK)
181+
.get_val();
182182
}
183183

184-
LIBC_INLINE static constexpr FPBits<T> neg_inf() {
185-
FPBits<T> bits = inf();
186-
bits.set_sign(1);
187-
return bits;
184+
LIBC_INLINE static constexpr T neg_inf() { return inf(true); }
185+
186+
LIBC_INLINE static constexpr T min_normal() {
187+
return FPBits(MIN_NORMAL).get_val();
188+
}
189+
190+
LIBC_INLINE static constexpr T max_normal() {
191+
return FPBits(MAX_NORMAL).get_val();
192+
}
193+
194+
LIBC_INLINE static constexpr T min_denormal() {
195+
return FPBits(MIN_SUBNORMAL).get_val();
188196
}
189197

190-
LIBC_INLINE static constexpr FPBits<T> min_normal() {
191-
return FPBits<T>(MIN_NORMAL);
198+
LIBC_INLINE static constexpr T max_denormal() {
199+
return FPBits(MAX_SUBNORMAL).get_val();
192200
}
193201

194202
LIBC_INLINE static constexpr T build_nan(UIntType v) {
195-
FPBits<T> bits = inf();
203+
FPBits<T> bits(inf());
196204
bits.set_mantissa(v);
197205
return T(bits);
198206
}

libc/src/__support/FPUtil/except_value_utils.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,14 @@ template <typename T, size_t N> struct ExceptValues {
102102
// Helper functions to set results for exceptional cases.
103103
template <typename T> LIBC_INLINE T round_result_slightly_down(T value_rn) {
104104
volatile T tmp = value_rn;
105-
const T MIN_NORMAL = FPBits<T>::min_normal().get_val();
105+
const T MIN_NORMAL = FPBits<T>::min_normal();
106106
tmp = tmp - MIN_NORMAL;
107107
return tmp;
108108
}
109109

110110
template <typename T> LIBC_INLINE T round_result_slightly_up(T value_rn) {
111111
volatile T tmp = value_rn;
112-
const T MIN_NORMAL = FPBits<T>::min_normal().get_val();
112+
const T MIN_NORMAL = FPBits<T>::min_normal();
113113
tmp = tmp + MIN_NORMAL;
114114
return tmp;
115115
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ class FMod {
230230
if (LIBC_LIKELY(sx.uintval() <= sy.uintval())) {
231231
if (sx.uintval() < sy.uintval())
232232
return sx; // |x|<|y| return x
233-
return FPB::zero(); // |x|=|y| return 0.0
233+
return FPB(FPB::zero()); // |x|=|y| return 0.0
234234
}
235235

236236
int e_x = sx.get_unbiased_exponent();
@@ -243,7 +243,7 @@ class FMod {
243243
intU_t m_y = sy.get_explicit_mantissa();
244244
intU_t d = (e_x == e_y) ? (m_x - m_y) : (m_x << (e_x - e_y)) % m_y;
245245
if (d == 0)
246-
return FPB::zero();
246+
return FPB(FPB::zero());
247247
// iy - 1 because of "zero power" for number with power 1
248248
return FPB::make_value(d, e_y - 1);
249249
}
@@ -291,7 +291,7 @@ class FMod {
291291

292292
m_x %= m_y;
293293
if (LIBC_UNLIKELY(m_x == 0))
294-
return FPB::zero();
294+
return FPB(FPB::zero());
295295

296296
if (exp_diff == 0)
297297
return FPB::make_value(m_x, e_y);

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

Lines changed: 49 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -56,85 +56,85 @@ template <> struct FPBits<long double> {
5656

5757
UIntType bits;
5858

59-
LIBC_INLINE void set_mantissa(UIntType mantVal) {
59+
LIBC_INLINE constexpr void set_mantissa(UIntType mantVal) {
6060
mantVal &= (FloatProp::MANTISSA_MASK);
6161
bits &= ~(FloatProp::MANTISSA_MASK);
6262
bits |= mantVal;
6363
}
6464

65-
LIBC_INLINE UIntType get_mantissa() const {
65+
LIBC_INLINE constexpr UIntType get_mantissa() const {
6666
return bits & FloatProp::MANTISSA_MASK;
6767
}
6868

69-
LIBC_INLINE UIntType get_explicit_mantissa() const {
69+
LIBC_INLINE constexpr UIntType get_explicit_mantissa() const {
7070
return bits & (FloatProp::MANTISSA_MASK | FloatProp::EXPLICIT_BIT_MASK);
7171
}
7272

73-
LIBC_INLINE void set_unbiased_exponent(UIntType expVal) {
73+
LIBC_INLINE constexpr void set_unbiased_exponent(UIntType expVal) {
7474
expVal =
7575
(expVal << (FloatProp::BIT_WIDTH - 1 - FloatProp::EXPONENT_WIDTH)) &
7676
FloatProp::EXPONENT_MASK;
7777
bits &= ~(FloatProp::EXPONENT_MASK);
7878
bits |= expVal;
7979
}
8080

81-
LIBC_INLINE uint16_t get_unbiased_exponent() const {
81+
LIBC_INLINE constexpr uint16_t get_unbiased_exponent() const {
8282
return uint16_t((bits & FloatProp::EXPONENT_MASK) >>
8383
(FloatProp::BIT_WIDTH - 1 - FloatProp::EXPONENT_WIDTH));
8484
}
8585

86-
LIBC_INLINE void set_implicit_bit(bool implicitVal) {
86+
LIBC_INLINE constexpr void set_implicit_bit(bool implicitVal) {
8787
bits &= ~(UIntType(1) << FloatProp::MANTISSA_WIDTH);
8888
bits |= (UIntType(implicitVal) << FloatProp::MANTISSA_WIDTH);
8989
}
9090

91-
LIBC_INLINE bool get_implicit_bit() const {
91+
LIBC_INLINE constexpr bool get_implicit_bit() const {
9292
return bool((bits & (UIntType(1) << FloatProp::MANTISSA_WIDTH)) >>
9393
FloatProp::MANTISSA_WIDTH);
9494
}
9595

96-
LIBC_INLINE void set_sign(bool signVal) {
96+
LIBC_INLINE constexpr void set_sign(bool signVal) {
9797
bits &= ~(FloatProp::SIGN_MASK);
9898
UIntType sign1 = UIntType(signVal) << (FloatProp::BIT_WIDTH - 1);
9999
bits |= sign1;
100100
}
101101

102-
LIBC_INLINE bool get_sign() const {
102+
LIBC_INLINE constexpr bool get_sign() const {
103103
return bool((bits & FloatProp::SIGN_MASK) >> (FloatProp::BIT_WIDTH - 1));
104104
}
105105

106-
FPBits() : bits(0) {}
106+
constexpr FPBits() : bits(0) {}
107107

108108
template <typename XType,
109109
cpp::enable_if_t<cpp::is_same_v<long double, XType>, int> = 0>
110-
explicit FPBits(XType x) : bits(cpp::bit_cast<UIntType>(x)) {
110+
constexpr explicit FPBits(XType x) : bits(cpp::bit_cast<UIntType>(x)) {
111111
// bits starts uninitialized, and setting it to a long double only
112112
// overwrites the first 80 bits. This clears those upper bits.
113113
bits = bits & ((UIntType(1) << 80) - 1);
114114
}
115115

116116
template <typename XType,
117117
cpp::enable_if_t<cpp::is_same_v<XType, UIntType>, int> = 0>
118-
explicit FPBits(XType x) : bits(x) {}
118+
constexpr explicit FPBits(XType x) : bits(x) {}
119119

120-
LIBC_INLINE operator long double() {
120+
LIBC_INLINE constexpr operator long double() {
121121
return cpp::bit_cast<long double>(bits);
122122
}
123123

124-
LIBC_INLINE UIntType uintval() {
124+
LIBC_INLINE constexpr UIntType uintval() {
125125
// We zero the padding bits as they can contain garbage.
126-
static constexpr UIntType MASK =
126+
constexpr UIntType MASK =
127127
(UIntType(1) << (sizeof(long double) * 8 -
128128
Padding<sizeof(uintptr_t)>::VALUE)) -
129129
1;
130130
return bits & MASK;
131131
}
132132

133-
LIBC_INLINE long double get_val() const {
133+
LIBC_INLINE constexpr long double get_val() const {
134134
return cpp::bit_cast<long double>(bits);
135135
}
136136

137-
LIBC_INLINE int get_exponent() const {
137+
LIBC_INLINE constexpr int get_exponent() const {
138138
return int(get_unbiased_exponent()) - EXPONENT_BIAS;
139139
}
140140

@@ -144,7 +144,7 @@ template <> struct FPBits<long double> {
144144
// values are calculated from the exponent, since just subtracting the bias
145145
// will give a slightly incorrect result. Additionally, zero has an exponent
146146
// of zero, and that should actually be treated as zero.
147-
LIBC_INLINE int get_explicit_exponent() const {
147+
LIBC_INLINE constexpr int get_explicit_exponent() const {
148148
const int unbiased_exp = int(get_unbiased_exponent());
149149
if (is_zero()) {
150150
return 0;
@@ -155,17 +155,17 @@ template <> struct FPBits<long double> {
155155
}
156156
}
157157

158-
LIBC_INLINE bool is_zero() const {
158+
LIBC_INLINE constexpr bool is_zero() const {
159159
return get_unbiased_exponent() == 0 && get_mantissa() == 0 &&
160160
get_implicit_bit() == 0;
161161
}
162162

163-
LIBC_INLINE bool is_inf() const {
163+
LIBC_INLINE constexpr bool is_inf() const {
164164
return get_unbiased_exponent() == MAX_EXPONENT && get_mantissa() == 0 &&
165165
get_implicit_bit() == 1;
166166
}
167167

168-
LIBC_INLINE bool is_nan() const {
168+
LIBC_INLINE constexpr bool is_nan() const {
169169
if (get_unbiased_exponent() == MAX_EXPONENT) {
170170
return (get_implicit_bit() == 0) || get_mantissa() != 0;
171171
} else if (get_unbiased_exponent() != 0) {
@@ -174,51 +174,58 @@ template <> struct FPBits<long double> {
174174
return false;
175175
}
176176

177-
LIBC_INLINE bool is_inf_or_nan() const {
177+
LIBC_INLINE constexpr bool is_inf_or_nan() const {
178178
return (get_unbiased_exponent() == MAX_EXPONENT) ||
179179
(get_unbiased_exponent() != 0 && get_implicit_bit() == 0);
180180
}
181181

182182
// Methods below this are used by tests.
183183

184-
LIBC_INLINE static FPBits<long double> zero() {
185-
return FPBits<long double>(0.0l);
186-
}
184+
LIBC_INLINE static constexpr long double zero() { return 0.0l; }
187185

188-
LIBC_INLINE static FPBits<long double> neg_zero() {
189-
FPBits<long double> bits(0.0l);
190-
bits.set_sign(1);
191-
return bits;
192-
}
186+
LIBC_INLINE static constexpr long double neg_zero() { return -0.0l; }
193187

194-
LIBC_INLINE static FPBits<long double> inf() {
188+
LIBC_INLINE static constexpr long double inf(bool sign = false) {
195189
FPBits<long double> bits(0.0l);
196190
bits.set_unbiased_exponent(MAX_EXPONENT);
197191
bits.set_implicit_bit(1);
198-
return bits;
192+
if (sign) {
193+
bits.set_sign(true);
194+
}
195+
return bits.get_val();
199196
}
200197

201-
LIBC_INLINE static FPBits<long double> neg_inf() {
202-
FPBits<long double> bits(0.0l);
203-
bits.set_unbiased_exponent(MAX_EXPONENT);
204-
bits.set_implicit_bit(1);
205-
bits.set_sign(1);
206-
return bits;
207-
}
198+
LIBC_INLINE static constexpr long double neg_inf() { return inf(true); }
208199

209-
LIBC_INLINE static long double build_nan(UIntType v) {
200+
LIBC_INLINE static constexpr long double build_nan(UIntType v) {
210201
FPBits<long double> bits(0.0l);
211202
bits.set_unbiased_exponent(MAX_EXPONENT);
212203
bits.set_implicit_bit(1);
213204
bits.set_mantissa(v);
214205
return bits;
215206
}
216207

217-
LIBC_INLINE static long double build_quiet_nan(UIntType v) {
208+
LIBC_INLINE static constexpr long double build_quiet_nan(UIntType v) {
218209
return build_nan(FloatProp::QUIET_NAN_MASK | v);
219210
}
220211

221-
LIBC_INLINE static FPBits<long double>
212+
LIBC_INLINE static constexpr long double min_normal() {
213+
return FPBits(MIN_NORMAL).get_val();
214+
}
215+
216+
LIBC_INLINE static constexpr long double max_normal() {
217+
return FPBits(MAX_NORMAL).get_val();
218+
}
219+
220+
LIBC_INLINE static constexpr long double min_denormal() {
221+
return FPBits(MIN_SUBNORMAL).get_val();
222+
}
223+
224+
LIBC_INLINE static constexpr long double max_denormal() {
225+
return FPBits(MAX_SUBNORMAL).get_val();
226+
}
227+
228+
LIBC_INLINE static constexpr FPBits<long double>
222229
create_value(bool sign, UIntType unbiased_exp, UIntType mantissa) {
223230
FPBits<long double> result;
224231
result.set_sign(sign);

libc/src/__support/str_to_float.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,9 +1220,9 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
12201220
tolower(src[index + 2]) == inf_string[2]) {
12211221
seen_digit = true;
12221222
if (result.get_sign())
1223-
result = result.neg_inf();
1223+
result = fputil::FPBits<T>(result.neg_inf());
12241224
else
1225-
result = result.inf();
1225+
result = fputil::FPBits<T>(result.inf());
12261226
if (tolower(src[index + 3]) == inf_string[3] &&
12271227
tolower(src[index + 4]) == inf_string[4] &&
12281228
tolower(src[index + 5]) == inf_string[5] &&

libc/src/math/generic/atanhf.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ LLVM_LIBC_FUNCTION(float, atanhf, (float x)) {
2828
if (x_abs == 0x3F80'0000U) {
2929
fputil::set_errno_if_required(ERANGE);
3030
fputil::raise_except_if_required(FE_DIVBYZERO);
31-
return FPBits::inf(sign).get_val();
31+
return FPBits::inf(sign);
3232
} else {
3333
fputil::set_errno_if_required(EDOM);
3434
fputil::raise_except_if_required(FE_INVALID);

libc/src/math/generic/coshf.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ LLVM_LIBC_FUNCTION(float, coshf, (float x)) {
3131
}
3232

3333
if (xbits.is_inf_or_nan())
34-
return x + FPBits::inf().get_val();
34+
return x + FPBits::inf();
3535

3636
int rounding = fputil::quick_get_round();
3737
if (LIBC_UNLIKELY(rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO))
@@ -40,7 +40,7 @@ LLVM_LIBC_FUNCTION(float, coshf, (float x)) {
4040
fputil::set_errno_if_required(ERANGE);
4141
fputil::raise_except_if_required(FE_OVERFLOW);
4242

43-
return x + FPBits::inf().get_val();
43+
return x + FPBits::inf();
4444
}
4545

4646
// TODO: We should be able to reduce the latency and reciprocal throughput

libc/src/math/generic/exp10f_impl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,13 @@ LIBC_INLINE float exp10f(float x) {
5454
if (x_u < 0x7f80'0000U) {
5555
int rounding = fputil::quick_get_round();
5656
if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
57-
return static_cast<float>(FPBits(FPBits::MAX_NORMAL));
57+
return FPBits::max_normal();
5858

5959
fputil::set_errno_if_required(ERANGE);
6060
fputil::raise_except_if_required(FE_OVERFLOW);
6161
}
6262
// x is +inf or nan
63-
return x + static_cast<float>(FPBits::inf());
63+
return x + FPBits::inf();
6464
}
6565
}
6666

libc/src/math/generic/exp2f_impl.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,13 @@ LIBC_INLINE float exp2f(float x) {
7676
if (x_u < 0x7f80'0000U) {
7777
int rounding = fputil::quick_get_round();
7878
if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
79-
return static_cast<float>(FPBits(FPBits::MAX_NORMAL));
79+
return FPBits::max_normal();
8080

8181
fputil::set_errno_if_required(ERANGE);
8282
fputil::raise_except_if_required(FE_OVERFLOW);
8383
}
8484
// x is +inf or nan
85-
return x + FPBits::inf().get_val();
85+
return x + FPBits::inf();
8686
}
8787
// x <= -150
8888
if (x_u >= 0xc316'0000U) {
@@ -93,7 +93,7 @@ LIBC_INLINE float exp2f(float x) {
9393
if (xbits.is_nan())
9494
return x;
9595
if (fputil::fenv_is_round_up())
96-
return FPBits(FPBits::MIN_SUBNORMAL).get_val();
96+
return FPBits::min_denormal();
9797
if (x != 0.0f) {
9898
fputil::set_errno_if_required(ERANGE);
9999
fputil::raise_except_if_required(FE_UNDERFLOW);

0 commit comments

Comments
 (0)