Skip to content

Commit 885ddf4

Browse files
authored
[libc] Fix constexpr FPUtils rounding_mode.h functions. (#152342)
1 parent d54aa36 commit 885ddf4

File tree

1 file changed

+59
-34
lines changed

1 file changed

+59
-34
lines changed

libc/src/__support/FPUtil/rounding_mode.h

Lines changed: 59 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -17,30 +17,24 @@
1717
namespace LIBC_NAMESPACE_DECL {
1818
namespace fputil {
1919

20+
namespace generic {
21+
2022
// Quick free-standing test whether fegetround() == FE_UPWARD.
2123
// Using the following observation:
2224
// 1.0f + 2^-25 = 1.0f for FE_TONEAREST, FE_DOWNWARD, FE_TOWARDZERO
2325
// = 0x1.000002f for FE_UPWARD.
24-
LIBC_INLINE static constexpr bool fenv_is_round_up() {
25-
if (cpp::is_constant_evaluated()) {
26-
return false;
27-
} else {
28-
volatile float x = 0x1.0p-25f;
29-
return (1.0f + x != 1.0f);
30-
}
26+
LIBC_INLINE bool fenv_is_round_up() {
27+
static volatile float x = 0x1.0p-25f;
28+
return (1.0f + x != 1.0f);
3129
}
3230

3331
// Quick free-standing test whether fegetround() == FE_DOWNWARD.
3432
// Using the following observation:
3533
// -1.0f - 2^-25 = -1.0f for FE_TONEAREST, FE_UPWARD, FE_TOWARDZERO
3634
// = -0x1.000002f for FE_DOWNWARD.
37-
LIBC_INLINE static constexpr bool fenv_is_round_down() {
38-
if (cpp::is_constant_evaluated()) {
39-
return false;
40-
} else {
41-
volatile float x = 0x1.0p-25f;
42-
return (-1.0f - x != -1.0f);
43-
}
35+
LIBC_INLINE bool fenv_is_round_down() {
36+
static volatile float x = 0x1.0p-25f;
37+
return (-1.0f - x != -1.0f);
4438
}
4539

4640
// Quick free-standing test whether fegetround() == FE_TONEAREST.
@@ -49,14 +43,10 @@ LIBC_INLINE static constexpr bool fenv_is_round_down() {
4943
// = 0x1.100002p0f for FE_UPWARD,
5044
// 1.5f - 2^-24 = 1.5f for FE_TONEAREST, FE_UPWARD
5145
// = 0x1.0ffffep-1f for FE_DOWNWARD, FE_TOWARDZERO
52-
LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() {
53-
if (cpp::is_constant_evaluated()) {
54-
return true;
55-
} else {
56-
volatile float x = 0x1.0p-24f;
57-
float y = 1.5f + x;
58-
return (y == 1.5f - x);
59-
}
46+
LIBC_INLINE bool fenv_is_round_to_nearest() {
47+
static volatile float x = 0x1.0p-24f;
48+
float y = 1.5f + x;
49+
return (y == 1.5f - x);
6050
}
6151

6252
// Quick free-standing test whether fegetround() == FE_TOWARDZERO.
@@ -69,13 +59,56 @@ LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() {
6959
// (0x1.000002p0f + 2^-24) + (-1.0f - 2^-24) = 2^-23 for FE_TOWARDZERO
7060
// = 2^-22 for FE_TONEAREST, FE_UPWARD
7161
// = 0 for FE_DOWNWARD
62+
LIBC_INLINE bool fenv_is_round_to_zero() {
63+
static volatile float x = 0x1.0p-24f;
64+
float y = x;
65+
return ((0x1.000002p0f + y) + (-1.0f - y) == 0x1.0p-23f);
66+
}
67+
68+
// Quick free standing get rounding mode based on the above observations.
69+
LIBC_INLINE int quick_get_round() {
70+
static volatile float x = 0x1.0p-24f;
71+
float y = x;
72+
float z = (0x1.000002p0f + y) + (-1.0f - y);
73+
74+
if (z == 0.0f)
75+
return FE_DOWNWARD;
76+
if (z == 0x1.0p-23f)
77+
return FE_TOWARDZERO;
78+
return (2.0f + y == 2.0f) ? FE_TONEAREST : FE_UPWARD;
79+
}
80+
81+
} // namespace generic
82+
83+
LIBC_INLINE static constexpr bool fenv_is_round_up() {
84+
if (cpp::is_constant_evaluated()) {
85+
return false;
86+
} else {
87+
return generic::fenv_is_round_up();
88+
}
89+
}
90+
91+
LIBC_INLINE static constexpr bool fenv_is_round_down() {
92+
if (cpp::is_constant_evaluated()) {
93+
return false;
94+
} else {
95+
return generic::fenv_is_round_down();
96+
}
97+
}
98+
99+
LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() {
100+
if (cpp::is_constant_evaluated()) {
101+
return true;
102+
} else {
103+
return generic::fenv_is_round_to_nearest();
104+
}
105+
}
106+
72107
LIBC_INLINE static constexpr bool fenv_is_round_to_zero() {
73108
if (cpp::is_constant_evaluated()) {
74109
return false;
75110
} else {
76-
volatile float x = 0x1.0p-24f;
77-
volatile float y = 0x1.000002p0f + x;
78-
return (y + (-1.0f - x) == 0x1.0p-23f);
111+
return generic::fenv_is_round_to_zero();
79112
}
80113
}
81114

@@ -84,15 +117,7 @@ LIBC_INLINE static constexpr int quick_get_round() {
84117
if (cpp::is_constant_evaluated()) {
85118
return FE_TONEAREST;
86119
} else {
87-
volatile float x = 0x1.0p-24f;
88-
volatile float y = 0x1.000002p0f + x;
89-
float z = y + (-1.0f - x);
90-
91-
if (z == 0.0f)
92-
return FE_DOWNWARD;
93-
if (z == 0x1.0p-23f)
94-
return FE_TOWARDZERO;
95-
return (2.0f + x == 2.0f) ? FE_TONEAREST : FE_UPWARD;
120+
return generic::quick_get_round();
96121
}
97122
}
98123

0 commit comments

Comments
 (0)