Skip to content

Commit b2676e9

Browse files
committed
Added static_assert tests for constexpr float classification and got std::signbit to work at compile time
1 parent 32965c8 commit b2676e9

File tree

3 files changed

+681
-92
lines changed

3 files changed

+681
-92
lines changed

src/libc/header_test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#include <assert.h>
33
#include <byteswap.h>
44
#include <cdefs.h>
5-
#include <complex.h>
5+
// #include <complex.h> // supress -ffast-math warnings for now
66
#include <ctype.h>
77
#include <errno.h>
88
#include <fenv.h>

src/libcxx/include/cmath

Lines changed: 121 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -13,153 +13,183 @@ using ::float_t;
1313
using ::double_t;
1414

1515
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));
16+
if (__builtin_constant_p(__x)) {
17+
return (__builtin_copysign(1.0f, __x) < 0.0f);
18+
}
19+
return static_cast<bool>(_signbitf(__x));
2020
}
2121
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));
22+
if (__builtin_constant_p(__x)) {
23+
return (__builtin_copysign(1.0, __x) < 0.0);
24+
}
25+
return static_cast<bool>(_signbitf(__x));
2626
}
2727
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));
28+
if (__builtin_constant_p(__x)) {
29+
return (__builtin_copysign(1.0L, __x) < 0.0L);
30+
}
31+
return static_cast<bool>(_signbitl(__x));
3232
}
3333
template<typename _Tp> inline constexpr
3434
__cmath_enable_if_t<__cmath_is_integral_v<_Tp>, bool>
35-
signbit(_Tp __x) { return signbit(__x); }
35+
signbit(_Tp __x) { return (__x < 0); }
3636

3737
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));
38+
if (__builtin_constant_p(__x)) {
39+
return __builtin_isinf(__x);
40+
}
41+
return static_cast<bool>(_isinff(__x));
4242
}
4343
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));
44+
if (__builtin_constant_p(__x)) {
45+
return __builtin_isinf(__x);
46+
}
47+
return static_cast<bool>(_isinff(__x));
4848
}
4949
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));
50+
if (__builtin_constant_p(__x)) {
51+
return __builtin_isinf(__x);
52+
}
53+
return static_cast<bool>(_isinfl(__x));
5454
}
5555
template<typename _Tp> inline constexpr
5656
__cmath_enable_if_t<__cmath_is_integral_v<_Tp>, bool>
57-
isinf(_Tp __x) { return isinf(__x); }
57+
isinf(_Tp __x) { return false; }
5858

5959
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));
60+
if (__builtin_constant_p(__x)) {
61+
return __builtin_isnan(__x);
62+
}
63+
return static_cast<bool>(_isnanf(__x));
6464
}
6565
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));
66+
if (__builtin_constant_p(__x)) {
67+
return __builtin_isnan(__x);
68+
}
69+
return static_cast<bool>(_isnanf(__x));
7070
}
7171
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));
72+
if (__builtin_constant_p(__x)) {
73+
return __builtin_isnan(__x);
74+
}
75+
return static_cast<bool>(_isnanl(__x));
7676
}
7777
template<typename _Tp> inline constexpr
7878
__cmath_enable_if_t<__cmath_is_integral_v<_Tp>, bool>
79-
isnan(_Tp __x) { return isnan(__x); }
79+
isnan(_Tp __x) { return false; }
8080

8181
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));
82+
if (__builtin_constant_p(__x)) {
83+
return __builtin_isnormal(__x);
84+
}
85+
return static_cast<bool>(_isnormalf(__x));
8686
}
8787
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));
88+
if (__builtin_constant_p(__x)) {
89+
return __builtin_isnormal(__x);
90+
}
91+
return static_cast<bool>(_isnormalf(__x));
9292
}
9393
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));
94+
if (__builtin_constant_p(__x)) {
95+
return __builtin_isnormal(__x);
96+
}
97+
return static_cast<bool>(_isnormall(__x));
9898
}
9999
template<typename _Tp> inline constexpr
100100
__cmath_enable_if_t<__cmath_is_integral_v<_Tp>, bool>
101-
isnormal(_Tp __x) { return isnormal(__x); }
101+
isnormal(_Tp __x) { return (__x != 0); }
102102

103103
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));
104+
if (__builtin_constant_p(__x)) {
105+
return __builtin_isfinite(__x);
106+
}
107+
return static_cast<bool>(_isfinitef(__x));
108108
}
109109
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));
110+
if (__builtin_constant_p(__x)) {
111+
return __builtin_isfinite(__x);
112+
}
113+
return static_cast<bool>(_isfinitef(__x));
114114
}
115115
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));
116+
if (__builtin_constant_p(__x)) {
117+
return __builtin_isfinite(__x);
118+
}
119+
return static_cast<bool>(_isfinitel(__x));
120120
}
121121
template<typename _Tp> inline constexpr
122122
__cmath_enable_if_t<__cmath_is_integral_v<_Tp>, bool>
123-
isfinite(_Tp __x) { return isfinite(__x); }
123+
isfinite(_Tp __x) { return true; }
124124

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
125+
inline constexpr bool iszero(float __x) {
126+
if (__builtin_constant_p(__x)) {
127+
return (__x == 0.0f);
128+
}
129+
return static_cast<bool>(_iszerof(__x));
130+
}
131+
inline constexpr bool iszero(double __x) {
132+
if (__builtin_constant_p(__x)) {
133+
return (__x == 0.0);
134+
}
135+
return static_cast<bool>(_iszerof(__x));
136+
}
137+
inline constexpr bool iszero(long double __x) {
138+
if (__builtin_constant_p(__x)) {
139+
return (__x == 0.0L);
140+
}
141+
return static_cast<bool>(_iszerol(__x));
142+
}
143+
template<typename _Tp> inline constexpr
129144
__cmath_enable_if_t<__cmath_is_integral_v<_Tp>, bool>
130-
iszero(_Tp __x) { return iszero(__x); }
145+
iszero(_Tp __x) { return (__x == 0); }
131146

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
147+
inline constexpr bool issubnormal(float __x) {
148+
if (__builtin_constant_p(__x)) {
149+
return (FP_SUBNORMAL == __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x));
150+
}
151+
return static_cast<bool>(_issubnormalf(__x));
152+
}
153+
inline constexpr bool issubnormal(double __x) {
154+
if (__builtin_constant_p(__x)) {
155+
return (FP_SUBNORMAL == __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x));
156+
}
157+
return static_cast<bool>(_issubnormalf(__x));
158+
}
159+
inline constexpr bool issubnormal(long double __x) {
160+
if (__builtin_constant_p(__x)) {
161+
return (FP_SUBNORMAL == __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x));
162+
}
163+
return static_cast<bool>(_issubnormall(__x));
164+
}
165+
template<typename _Tp> inline constexpr
136166
__cmath_enable_if_t<__cmath_is_integral_v<_Tp>, bool>
137-
issubnormal(_Tp __x) { return issubnormal(__x); }
167+
issubnormal(_Tp __x) { return false; }
138168

139169
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-
}
170+
if (__builtin_constant_p(__x)) {
171+
return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x);
172+
} else {
173+
return _fpclassifyf(__x);
174+
}
145175
}
146176
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-
}
177+
if (__builtin_constant_p(__x)) {
178+
return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x);
179+
} else {
180+
return _fpclassifyf(__x);
181+
}
152182
}
153183
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-
}
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 _fpclassifyl(__x);
188+
}
159189
}
160190
template<typename _Tp> inline constexpr
161191
__cmath_enable_if_t<__cmath_is_integral_v<_Tp>, int>
162-
fpclassify(_Tp __x) { return fpclassify(__x); }
192+
fpclassify(_Tp __x) { return (__x != 0) ? FP_NORMAL : FP_ZERO; }
163193

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

0 commit comments

Comments
 (0)