In particular, it must work with NaNs as std::copysign
does. Similarly, I need a constexpr std::signbit
.
constexpr double copysign(double mag, double sgn)
{
// how?
}
constexpr bool signbit(double arg)
{
// how?
}
// produce the two types of NaNs
constexpr double nan_pos = copysign(std::numeric_limits<double>::quiet_NaN(), 1);
constexpr double nan_neg = copysign(std::numeric_limits<double>::quiet_NaN(), -1);
// must pass the checks
static_assert(signbit(nan_pos) == false);
static_assert(signbit(nan_neg) == true);
The story behind is that I need two types of NaNs at compile time, as well as ways to distinguish between them. The most straightforward way I can think of is to manipulate the sign bit of the NaNs. It does work at run time; now I just want to move some computations to compile time, and this is the last hurdle.
Notes: at the moment, I'm relying on GCC, as it has built-in versions of these functions and they are indeed constexpr
, which is nice. But I want my codebase to compile on Clang and perhaps other compilers too.
CodePudding user response:
If you can use std::bit_cast
, you can manipulate floating point types cast to integer types. The portability is limited to the representation of double
, but if you can assume the IEEE 754 double-precision binary floating-point format, cast to uint64_t and using sign bit should work.
CodePudding user response:
Use of __builtin...
is not really portable, but works in compilers that mentioned as target. __builtin_copysign
is contexpr, but __builtin_signbit
is apparently not on clang, so doing signbit
with __builtin_copysign
:
#include <limits>
constexpr double copysign(double mag, double sgn)
{
return __builtin_copysign(mag, sgn);
}
constexpr bool signbit(double arg)
{
return __builtin_copysign(1, arg) < 0;
}
// produce the two types of NaNs
constexpr double nan_pos = copysign(std::numeric_limits<double>::quiet_NaN(), 1);
constexpr double nan_neg = copysign(std::numeric_limits<double>::quiet_NaN(), -1);
// must pass the checks
static_assert(signbit(nan_pos) == false);
static_assert(signbit(nan_neg) == true);
int main() {}