Skip to content

float classification routines can now be constant folded in C #592

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 158 additions & 27 deletions src/libc/include/math.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,64 +9,195 @@

#include <__math_def.h>

static inline __attribute__((__always_inline__))
bool __signbitf(float __x) {
if (__builtin_constant_p(__x)) {
return (__builtin_copysign(1.0f, __x) < 0.0f);
}
return _signbitf(__x);
}
static inline __attribute__((__always_inline__))
bool __signbitl(long double __x) {
if (__builtin_constant_p(__x)) {
return (__builtin_copysign(1.0L, __x) < 0.0L);
}
return _signbitl(__x);
}

static inline __attribute__((__always_inline__))
bool __issignalingf(float __x) {
return _issignalingf(__x);
}
static inline __attribute__((__always_inline__))
bool __issignalingl(long double __x) {
return _issignalingl(__x);
}

static inline __attribute__((__always_inline__))
bool __isnanf(float __x) {
if (__builtin_constant_p(__x)) {
return __builtin_isnan(__x);
}
return _isnanf(__x);
}
static inline __attribute__((__always_inline__))
bool __isnanl(long double __x) {
if (__builtin_constant_p(__x)) {
return __builtin_isnan(__x);
}
return _isnanl(__x);
}

static inline __attribute__((__always_inline__))
bool __isinff(float __x) {
if (__builtin_constant_p(__x)) {
return __builtin_isinf(__x);
}
return _isinff(__x);
}
static inline __attribute__((__always_inline__))
bool __isinfl(long double __x) {
if (__builtin_constant_p(__x)) {
return __builtin_isinf(__x);
}
return _isinfl(__x);
}

static inline __attribute__((__always_inline__))
bool __isfinitef(float __x) {
if (__builtin_constant_p(__x)) {
return __builtin_isfinite(__x);
}
return _isfinitef(__x);
}
static inline __attribute__((__always_inline__))
bool __isfinitel(long double __x) {
if (__builtin_constant_p(__x)) {
return __builtin_isfinite(__x);
}
return _isfinitel(__x);
}

static inline __attribute__((__always_inline__))
bool __isnormalf(float __x) {
if (__builtin_constant_p(__x)) {
return __builtin_isnormal(__x);
}
return _isnormalf(__x);
}
static inline __attribute__((__always_inline__))
bool __isnormall(long double __x) {
if (__builtin_constant_p(__x)) {
return __builtin_isnormal(__x);
}
return _isnormall(__x);
}

static inline __attribute__((__always_inline__))
bool __issubnormalf(float __x) {
if (__builtin_constant_p(__x)) {
return (FP_SUBNORMAL == __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x));
}
return _issubnormalf(__x);
}
static inline __attribute__((__always_inline__))
bool __issubnormall(long double __x) {
if (__builtin_constant_p(__x)) {
return (FP_SUBNORMAL == __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x));
}
return _issubnormall(__x);
}

static inline __attribute__((__always_inline__))
bool __iszerof(float __x) {
if (__builtin_constant_p(__x)) {
return (__x == 0.0f);
}
return _iszerof(__x);
}
static inline __attribute__((__always_inline__))
bool __iszerol(long double __x) {
if (__builtin_constant_p(__x)) {
return (__x == 0.0L);
}
return _iszerol(__x);
}

static inline __attribute__((__always_inline__))
int __fpclassifyf(float __x) {
if (__builtin_constant_p(__x)) {
return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x);
} else {
return _fpclassifyf(__x);
}
}
static inline __attribute__((__always_inline__))
int __fpclassifyl(long double __x) {
if (__builtin_constant_p(__x)) {
return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x);
} else {
return _fpclassifyl(__x);
}
}

#define __math_promote(x) _Generic((x), \
float: ((float)0.f), \
default: ((double)0.), \
long double: ((long double)0.L) \
)

#define signbit(x) ((int)_Generic(__math_promote(x), \
long double: _signbitl, \
default: _signbitf, \
float: _signbitf \
long double: __signbitl, \
default: __signbitf, \
float: __signbitf \
)(x))

#define issignaling(x) ((int)_Generic(__math_promote(x), \
long double: _issignalingl, \
default: _issignalingf, \
float: _issignalingf \
long double: __issignalingl, \
default: __issignalingf, \
float: __issignalingf \
)(x))

#define isnan(x) ((int)_Generic(__math_promote(x), \
long double: _isnanl, \
default: _isnanf, \
float: _isnanf \
long double: __isnanl, \
default: __isnanf, \
float: __isnanf \
)(x))

#define isinf(x) ((int)_Generic(__math_promote(x), \
long double: _isinfl, \
default: _isinff, \
float: _isinff \
long double: __isinfl, \
default: __isinff, \
float: __isinff \
)(x))

#define isfinite(x) ((int)_Generic(__math_promote(x), \
long double: _isfinitel, \
default: _isfinitef, \
float: _isfinitef \
long double: __isfinitel, \
default: __isfinitef, \
float: __isfinitef \
)(x))

#define isnormal(x) ((int)_Generic(__math_promote(x), \
long double: _isnormall, \
default: _isnormalf, \
float: _isnormalf \
long double: __isnormall, \
default: __isnormalf, \
float: __isnormalf \
)(x))

#define issubnormal(x) ((int)_Generic(__math_promote(x), \
long double: _issubnormall, \
default: _issubnormalf, \
float: _issubnormalf \
long double: __issubnormall, \
default: __issubnormalf, \
float: __issubnormalf \
)(x))

#define iszero(x) ((int)_Generic(__math_promote(x), \
long double: _iszerol, \
default: _iszerof, \
float: _iszerof \
long double: __iszerol, \
default: __iszerof, \
float: __iszerof \
)(x))

#define fpclassify(x) ((int)_Generic(__math_promote(x), \
long double: _fpclassifyl, \
default: _fpclassifyf, \
float: _fpclassifyf \
long double: __fpclassifyl, \
default: __fpclassifyf, \
float: __fpclassifyf \
)(x))

#define isgreater(x, y) __builtin_isgreater(x, y)
Expand Down
2 changes: 1 addition & 1 deletion src/libcxx/include/memory
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace std {

template <class _Tp>
inline _Tp* addressof(_Tp& __x) noexcept {
constexpr inline _Tp* addressof(_Tp& __x) noexcept {
return __builtin_addressof(__x);
}

Expand Down
136 changes: 68 additions & 68 deletions src/libcxx/math_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,23 +75,23 @@ C((!iszero (std::numeric_limits<long double>::denorm_min())));

/* MIN */

C((!signbit (std::numeric_limits<long double>::min())));
C((!issignaling(std::numeric_limits<long double>::min())));
C((!isnan (std::numeric_limits<long double>::min())));
C((!isinf (std::numeric_limits<long double>::min())));
C(( isfinite (std::numeric_limits<long double>::min())));
C(( isnormal (std::numeric_limits<long double>::min())));
C((!issubnormal(std::numeric_limits<long double>::min())));
C((!iszero (std::numeric_limits<long double>::min())));

C((!signbit (std::numeric_limits<long double>::min())));
C((!issignaling(std::numeric_limits<long double>::min())));
C((!isnan (std::numeric_limits<long double>::min())));
C((!isinf (std::numeric_limits<long double>::min())));
C(( isfinite (std::numeric_limits<long double>::min())));
C(( isnormal (std::numeric_limits<long double>::min())));
C((!issubnormal(std::numeric_limits<long double>::min())));
C((!iszero (std::numeric_limits<long double>::min())));
C((!signbit (std::numeric_limits<float>::min())));
C((!issignaling(std::numeric_limits<float>::min())));
C((!isnan (std::numeric_limits<float>::min())));
C((!isinf (std::numeric_limits<float>::min())));
C(( isfinite (std::numeric_limits<float>::min())));
C(( isnormal (std::numeric_limits<float>::min())));
C((!issubnormal(std::numeric_limits<float>::min())));
C((!iszero (std::numeric_limits<float>::min())));

C((!signbit (std::numeric_limits<double>::min())));
C((!issignaling(std::numeric_limits<double>::min())));
C((!isnan (std::numeric_limits<double>::min())));
C((!isinf (std::numeric_limits<double>::min())));
C(( isfinite (std::numeric_limits<double>::min())));
C(( isnormal (std::numeric_limits<double>::min())));
C((!issubnormal(std::numeric_limits<double>::min())));
C((!iszero (std::numeric_limits<double>::min())));

C((!signbit (std::numeric_limits<long double>::min())));
C((!issignaling(std::numeric_limits<long double>::min())));
Expand Down Expand Up @@ -191,23 +191,23 @@ C((!iszero (3.1415926535897932384626433832795L)));

/* MAX */

C((!signbit (std::numeric_limits<long double>::max())));
C((!issignaling(std::numeric_limits<long double>::max())));
C((!isnan (std::numeric_limits<long double>::max())));
C((!isinf (std::numeric_limits<long double>::max())));
C(( isfinite (std::numeric_limits<long double>::max())));
C(( isnormal (std::numeric_limits<long double>::max())));
C((!issubnormal(std::numeric_limits<long double>::max())));
C((!iszero (std::numeric_limits<long double>::max())));

C((!signbit (std::numeric_limits<long double>::max())));
C((!issignaling(std::numeric_limits<long double>::max())));
C((!isnan (std::numeric_limits<long double>::max())));
C((!isinf (std::numeric_limits<long double>::max())));
C(( isfinite (std::numeric_limits<long double>::max())));
C(( isnormal (std::numeric_limits<long double>::max())));
C((!issubnormal(std::numeric_limits<long double>::max())));
C((!iszero (std::numeric_limits<long double>::max())));
C((!signbit (std::numeric_limits<float>::max())));
C((!issignaling(std::numeric_limits<float>::max())));
C((!isnan (std::numeric_limits<float>::max())));
C((!isinf (std::numeric_limits<float>::max())));
C(( isfinite (std::numeric_limits<float>::max())));
C(( isnormal (std::numeric_limits<float>::max())));
C((!issubnormal(std::numeric_limits<float>::max())));
C((!iszero (std::numeric_limits<float>::max())));

C((!signbit (std::numeric_limits<double>::max())));
C((!issignaling(std::numeric_limits<double>::max())));
C((!isnan (std::numeric_limits<double>::max())));
C((!isinf (std::numeric_limits<double>::max())));
C(( isfinite (std::numeric_limits<double>::max())));
C(( isnormal (std::numeric_limits<double>::max())));
C((!issubnormal(std::numeric_limits<double>::max())));
C((!iszero (std::numeric_limits<double>::max())));

C((!signbit (std::numeric_limits<long double>::max())));
C((!issignaling(std::numeric_limits<long double>::max())));
Expand Down Expand Up @@ -369,23 +369,23 @@ C((!iszero (-std::numeric_limits<long double>::denorm_min())));

/* MIN */

C(( signbit (-std::numeric_limits<long double>::min())));
C((!issignaling(-std::numeric_limits<long double>::min())));
C((!isnan (-std::numeric_limits<long double>::min())));
C((!isinf (-std::numeric_limits<long double>::min())));
C(( isfinite (-std::numeric_limits<long double>::min())));
C(( isnormal (-std::numeric_limits<long double>::min())));
C((!issubnormal(-std::numeric_limits<long double>::min())));
C((!iszero (-std::numeric_limits<long double>::min())));

C(( signbit (-std::numeric_limits<long double>::min())));
C((!issignaling(-std::numeric_limits<long double>::min())));
C((!isnan (-std::numeric_limits<long double>::min())));
C((!isinf (-std::numeric_limits<long double>::min())));
C(( isfinite (-std::numeric_limits<long double>::min())));
C(( isnormal (-std::numeric_limits<long double>::min())));
C((!issubnormal(-std::numeric_limits<long double>::min())));
C((!iszero (-std::numeric_limits<long double>::min())));
C(( signbit (-std::numeric_limits<float>::min())));
C((!issignaling(-std::numeric_limits<float>::min())));
C((!isnan (-std::numeric_limits<float>::min())));
C((!isinf (-std::numeric_limits<float>::min())));
C(( isfinite (-std::numeric_limits<float>::min())));
C(( isnormal (-std::numeric_limits<float>::min())));
C((!issubnormal(-std::numeric_limits<float>::min())));
C((!iszero (-std::numeric_limits<float>::min())));

C(( signbit (-std::numeric_limits<double>::min())));
C((!issignaling(-std::numeric_limits<double>::min())));
C((!isnan (-std::numeric_limits<double>::min())));
C((!isinf (-std::numeric_limits<double>::min())));
C(( isfinite (-std::numeric_limits<double>::min())));
C(( isnormal (-std::numeric_limits<double>::min())));
C((!issubnormal(-std::numeric_limits<double>::min())));
C((!iszero (-std::numeric_limits<double>::min())));

C(( signbit (-std::numeric_limits<long double>::min())));
C((!issignaling(-std::numeric_limits<long double>::min())));
Expand Down Expand Up @@ -485,23 +485,23 @@ C((!iszero (-3.1415926535897932384626433832795L)));

/* MAX */

C(( signbit (-std::numeric_limits<long double>::max())));
C((!issignaling(-std::numeric_limits<long double>::max())));
C((!isnan (-std::numeric_limits<long double>::max())));
C((!isinf (-std::numeric_limits<long double>::max())));
C(( isfinite (-std::numeric_limits<long double>::max())));
C(( isnormal (-std::numeric_limits<long double>::max())));
C((!issubnormal(-std::numeric_limits<long double>::max())));
C((!iszero (-std::numeric_limits<long double>::max())));

C(( signbit (-std::numeric_limits<long double>::max())));
C((!issignaling(-std::numeric_limits<long double>::max())));
C((!isnan (-std::numeric_limits<long double>::max())));
C((!isinf (-std::numeric_limits<long double>::max())));
C(( isfinite (-std::numeric_limits<long double>::max())));
C(( isnormal (-std::numeric_limits<long double>::max())));
C((!issubnormal(-std::numeric_limits<long double>::max())));
C((!iszero (-std::numeric_limits<long double>::max())));
C(( signbit (-std::numeric_limits<float>::max())));
C((!issignaling(-std::numeric_limits<float>::max())));
C((!isnan (-std::numeric_limits<float>::max())));
C((!isinf (-std::numeric_limits<float>::max())));
C(( isfinite (-std::numeric_limits<float>::max())));
C(( isnormal (-std::numeric_limits<float>::max())));
C((!issubnormal(-std::numeric_limits<float>::max())));
C((!iszero (-std::numeric_limits<float>::max())));

C(( signbit (-std::numeric_limits<double>::max())));
C((!issignaling(-std::numeric_limits<double>::max())));
C((!isnan (-std::numeric_limits<double>::max())));
C((!isinf (-std::numeric_limits<double>::max())));
C(( isfinite (-std::numeric_limits<double>::max())));
C(( isnormal (-std::numeric_limits<double>::max())));
C((!issubnormal(-std::numeric_limits<double>::max())));
C((!iszero (-std::numeric_limits<double>::max())));

C(( signbit (-std::numeric_limits<long double>::max())));
C((!issignaling(-std::numeric_limits<long double>::max())));
Expand Down
Loading
Loading