Skip to content

Commit dfed4ec

Browse files
committed
Added static_assert tests for constexpr float classification
1 parent 32965c8 commit dfed4ec

File tree

2 files changed

+699
-91
lines changed

2 files changed

+699
-91
lines changed

src/libcxx/include/cmath

Lines changed: 135 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -12,154 +12,198 @@ namespace std {
1212
using ::float_t;
1313
using ::double_t;
1414

15+
/* Clang 20.1.0 required for __builtin_signbit to work in constexpr */
16+
#if 0
17+
1518
inline constexpr bool signbit(float __x) {
16-
if (__builtin_constant_p(__x)) {
17-
return __builtin_signbitf(__x);
18-
}
19-
return static_cast<bool>(_signbitf(__x));
19+
if (__builtin_constant_p(__x)) {
20+
return __builtin_signbitf(__x);
21+
}
22+
return static_cast<bool>(_signbitf(__x));
2023
}
2124
inline constexpr bool signbit(double __x) {
22-
if (__builtin_constant_p(__x)) {
23-
return __builtin_signbit(__x);
24-
}
25-
return static_cast<bool>(_signbitf(__x));
25+
if (__builtin_constant_p(__x)) {
26+
return __builtin_signbit(__x);
27+
}
28+
return static_cast<bool>(_signbitf(__x));
2629
}
2730
inline constexpr bool signbit(long double __x) {
28-
if (__builtin_constant_p(__x)) {
29-
return __builtin_signbitl(__x);
30-
}
31-
return static_cast<bool>(_signbitl(__x));
31+
if (__builtin_constant_p(__x)) {
32+
return __builtin_signbitl(__x);
33+
}
34+
return static_cast<bool>(_signbitl(__x));
3235
}
3336
template<typename _Tp> inline constexpr
3437
__cmath_enable_if_t<__cmath_is_integral_v<_Tp>, bool>
35-
signbit(_Tp __x) { return signbit(__x); }
38+
signbit(_Tp __x) { return (__x < 0); }
39+
40+
#else
41+
42+
inline bool signbit(float __x) { return static_cast<bool>(_signbitf(__x)); }
43+
inline bool signbit(double __x) { return static_cast<bool>(_signbitf(__x)); }
44+
inline bool signbit(long double __x) { return static_cast<bool>(_signbitl(__x)); }
45+
template<typename _Tp> inline constexpr
46+
__cmath_enable_if_t<__cmath_is_integral_v<_Tp>, bool>
47+
signbit(_Tp __x) { return (__x < 0); }
48+
49+
#endif
3650

3751
inline constexpr bool isinf(float __x) {
38-
if (__builtin_constant_p(__x)) {
39-
return __builtin_isinf(__x);
40-
}
41-
return static_cast<bool>(_isinff(__x));
52+
if (__builtin_constant_p(__x)) {
53+
return __builtin_isinf(__x);
54+
}
55+
return static_cast<bool>(_isinff(__x));
4256
}
4357
inline constexpr bool isinf(double __x) {
44-
if (__builtin_constant_p(__x)) {
45-
return __builtin_isinf(__x);
46-
}
47-
return static_cast<bool>(_isinff(__x));
58+
if (__builtin_constant_p(__x)) {
59+
return __builtin_isinf(__x);
60+
}
61+
return static_cast<bool>(_isinff(__x));
4862
}
4963
inline constexpr bool isinf(long double __x) {
50-
if (__builtin_constant_p(__x)) {
51-
return __builtin_isinf(__x);
52-
}
53-
return static_cast<bool>(_isinfl(__x));
64+
if (__builtin_constant_p(__x)) {
65+
return __builtin_isinf(__x);
66+
}
67+
return static_cast<bool>(_isinfl(__x));
5468
}
5569
template<typename _Tp> inline constexpr
5670
__cmath_enable_if_t<__cmath_is_integral_v<_Tp>, bool>
57-
isinf(_Tp __x) { return isinf(__x); }
71+
isinf(_Tp __x) { return false; }
5872

5973
inline constexpr bool isnan(float __x) {
60-
if (__builtin_constant_p(__x)) {
61-
return __builtin_isnan(__x);
62-
}
63-
return static_cast<bool>(_isnanf(__x));
74+
if (__builtin_constant_p(__x)) {
75+
return __builtin_isnan(__x);
76+
}
77+
return static_cast<bool>(_isnanf(__x));
6478
}
6579
inline constexpr bool isnan(double __x) {
66-
if (__builtin_constant_p(__x)) {
67-
return __builtin_isnan(__x);
68-
}
69-
return static_cast<bool>(_isnanf(__x));
80+
if (__builtin_constant_p(__x)) {
81+
return __builtin_isnan(__x);
82+
}
83+
return static_cast<bool>(_isnanf(__x));
7084
}
7185
inline constexpr bool isnan(long double __x) {
72-
if (__builtin_constant_p(__x)) {
73-
return __builtin_isnan(__x);
74-
}
75-
return static_cast<bool>(_isnanl(__x));
86+
if (__builtin_constant_p(__x)) {
87+
return __builtin_isnan(__x);
88+
}
89+
return static_cast<bool>(_isnanl(__x));
7690
}
7791
template<typename _Tp> inline constexpr
7892
__cmath_enable_if_t<__cmath_is_integral_v<_Tp>, bool>
79-
isnan(_Tp __x) { return isnan(__x); }
93+
isnan(_Tp __x) { return false; }
8094

8195
inline constexpr bool isnormal(float __x) {
82-
if (__builtin_constant_p(__x)) {
83-
return __builtin_isnormal(__x);
84-
}
85-
return static_cast<bool>(_isnormalf(__x));
96+
if (__builtin_constant_p(__x)) {
97+
return __builtin_isnormal(__x);
98+
}
99+
return static_cast<bool>(_isnormalf(__x));
86100
}
87101
inline constexpr bool isnormal(double __x) {
88-
if (__builtin_constant_p(__x)) {
89-
return __builtin_isnormal(__x);
90-
}
91-
return static_cast<bool>(_isnormalf(__x));
102+
if (__builtin_constant_p(__x)) {
103+
return __builtin_isnormal(__x);
104+
}
105+
return static_cast<bool>(_isnormalf(__x));
92106
}
93107
inline constexpr bool isnormal(long double __x) {
94-
if (__builtin_constant_p(__x)) {
95-
return __builtin_isnormal(__x);
96-
}
97-
return static_cast<bool>(_isnormall(__x));
108+
if (__builtin_constant_p(__x)) {
109+
return __builtin_isnormal(__x);
110+
}
111+
return static_cast<bool>(_isnormall(__x));
98112
}
99113
template<typename _Tp> inline constexpr
100114
__cmath_enable_if_t<__cmath_is_integral_v<_Tp>, bool>
101-
isnormal(_Tp __x) { return isnormal(__x); }
115+
isnormal(_Tp __x) { return (__x != 0); }
102116

103117
inline constexpr bool isfinite(float __x) {
104-
if (__builtin_constant_p(__x)) {
105-
return __builtin_isfinite(__x);
106-
}
107-
return static_cast<bool>(_isfinitef(__x));
118+
if (__builtin_constant_p(__x)) {
119+
return __builtin_isfinite(__x);
120+
}
121+
return static_cast<bool>(_isfinitef(__x));
108122
}
109123
inline constexpr bool isfinite(double __x) {
110-
if (__builtin_constant_p(__x)) {
111-
return __builtin_isfinite(__x);
112-
}
113-
return static_cast<bool>(_isfinitef(__x));
124+
if (__builtin_constant_p(__x)) {
125+
return __builtin_isfinite(__x);
126+
}
127+
return static_cast<bool>(_isfinitef(__x));
114128
}
115129
inline constexpr bool isfinite(long double __x) {
116-
if (__builtin_constant_p(__x)) {
117-
return __builtin_isfinite(__x);
118-
}
119-
return static_cast<bool>(_isfinitel(__x));
130+
if (__builtin_constant_p(__x)) {
131+
return __builtin_isfinite(__x);
132+
}
133+
return static_cast<bool>(_isfinitel(__x));
120134
}
121135
template<typename _Tp> inline constexpr
122136
__cmath_enable_if_t<__cmath_is_integral_v<_Tp>, bool>
123-
isfinite(_Tp __x) { return isfinite(__x); }
137+
isfinite(_Tp __x) { return true; }
124138

125-
inline bool iszero(float __x) { return static_cast<bool>(_iszerof(__x)); }
126-
inline bool iszero(double __x) { return static_cast<bool>(_iszerof(__x)); }
127-
inline bool iszero(long double __x) { return static_cast<bool>(_iszerol(__x)); }
128-
template<typename _Tp> inline
139+
inline constexpr bool iszero(float __x) {
140+
if (__builtin_constant_p(__x)) {
141+
return (__x == 0.0f);
142+
}
143+
return static_cast<bool>(_iszerof(__x));
144+
}
145+
inline constexpr bool iszero(double __x) {
146+
if (__builtin_constant_p(__x)) {
147+
return (__x == 0.0);
148+
}
149+
return static_cast<bool>(_iszerof(__x));
150+
}
151+
inline constexpr bool iszero(long double __x) {
152+
if (__builtin_constant_p(__x)) {
153+
return (__x == 0.0L);
154+
}
155+
return static_cast<bool>(_iszerol(__x));
156+
}
157+
template<typename _Tp> inline constexpr
129158
__cmath_enable_if_t<__cmath_is_integral_v<_Tp>, bool>
130-
iszero(_Tp __x) { return iszero(__x); }
159+
iszero(_Tp __x) { return (__x == 0); }
131160

132-
inline bool issubnormal(float __x) { return static_cast<bool>(_issubnormalf(__x)); }
133-
inline bool issubnormal(double __x) { return static_cast<bool>(_issubnormalf(__x)); }
134-
inline bool issubnormal(long double __x) { return static_cast<bool>(_issubnormall(__x)); }
135-
template<typename _Tp> inline
161+
inline constexpr bool issubnormal(float __x) {
162+
if (__builtin_constant_p(__x)) {
163+
return (FP_SUBNORMAL == __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x));
164+
}
165+
return static_cast<bool>(_issubnormalf(__x));
166+
}
167+
inline constexpr bool issubnormal(double __x) {
168+
if (__builtin_constant_p(__x)) {
169+
return (FP_SUBNORMAL == __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x));
170+
}
171+
return static_cast<bool>(_issubnormalf(__x));
172+
}
173+
inline constexpr bool issubnormal(long double __x) {
174+
if (__builtin_constant_p(__x)) {
175+
return (FP_SUBNORMAL == __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x));
176+
}
177+
return static_cast<bool>(_issubnormall(__x));
178+
}
179+
template<typename _Tp> inline constexpr
136180
__cmath_enable_if_t<__cmath_is_integral_v<_Tp>, bool>
137-
issubnormal(_Tp __x) { return issubnormal(__x); }
181+
issubnormal(_Tp __x) { return false; }
138182

139183
inline constexpr int fpclassify(float __x) {
140-
if (__builtin_constant_p(__x)) {
141-
return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x);
142-
} else {
143-
return _fpclassifyf(__x);
144-
}
184+
if (__builtin_constant_p(__x)) {
185+
return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x);
186+
} else {
187+
return _fpclassifyf(__x);
188+
}
145189
}
146190
inline constexpr int fpclassify(double __x) {
147-
if (__builtin_constant_p(__x)) {
148-
return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x);
149-
} else {
150-
return _fpclassifyf(__x);
151-
}
191+
if (__builtin_constant_p(__x)) {
192+
return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x);
193+
} else {
194+
return _fpclassifyf(__x);
195+
}
152196
}
153197
inline constexpr int fpclassify(long double __x) {
154-
if (__builtin_constant_p(__x)) {
155-
return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x);
156-
} else {
157-
return _fpclassifyl(__x);
158-
}
198+
if (__builtin_constant_p(__x)) {
199+
return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x);
200+
} else {
201+
return _fpclassifyl(__x);
202+
}
159203
}
160204
template<typename _Tp> inline constexpr
161205
__cmath_enable_if_t<__cmath_is_integral_v<_Tp>, int>
162-
fpclassify(_Tp __x) { return fpclassify(__x); }
206+
fpclassify(_Tp __x) { return (__x != 0) ? FP_NORMAL : FP_ZERO; }
163207

164208
inline constexpr bool isgreater(float __x, float __y) { return __builtin_isgreater(__x, __y); }
165209
inline constexpr bool isgreater(double __x, double __y) { return __builtin_isgreater(__x, __y); }

0 commit comments

Comments
 (0)