26 #include <type_traits> 30 template <
typename Float>
32 using NL = std::numeric_limits<Float>;
34 static constexpr
bool const is_single = (NL::digits == 24) && (NL::max_exponent) == 128;
36 static constexpr
bool const is_double = (NL::digits == 53) && (NL::max_exponent == 1024);
38 static_assert(NL::is_iec559 && (is_single || is_double),
"IEEE-754 implementation required");
40 using Uint =
typename std::conditional<is_single, uint32_t, uint64_t>::type;
42 static_assert(
sizeof(Float) ==
sizeof(Uint),
"Size mismatch");
44 static constexpr
unsigned const kPrecision = is_single ? 24 : 53;
45 static constexpr
unsigned const kSignificandLen = kPrecision - 1;
46 static constexpr
unsigned const kMaxExponent = is_single ? 0xFF : 0x7FF;
47 static constexpr
unsigned const kExponentBias = kMaxExponent / 2;
48 static constexpr Uint
const kHiddenBit = Uint{1} << kSignificandLen;
49 static constexpr Uint
const kSignMask = Uint{1} << (is_single ? 31 : 63);
51 static constexpr Uint
const kExponentMask = Uint{kMaxExponent} << kSignificandLen;
52 static constexpr Uint
const kSignificandMask = kHiddenBit - 1;
59 constexpr
explicit IEEEFloat(Float value_) : value(value_) {}
60 constexpr
explicit IEEEFloat(Uint bits_) : bits(bits_) {}
61 constexpr
IEEEFloat(Uint exponent, Uint significand)
62 : bits(exponent << kSignificandLen | (significand & kSignificandMask)) {}
64 constexpr Uint ExponentBits()
const {
return (bits & kExponentMask) >> (kPrecision - 1); }
66 constexpr Uint SignificandBits()
const {
return (bits & kSignificandMask); }
69 constexpr
bool IsNegative()
const {
return (bits & kSignMask) != 0; }
72 bool IsZero()
const {
return (bits & ~kSignMask) == 0; }
75 bool IsDenormal()
const {
return (bits & kExponentMask) == 0; }
79 return (bits & kExponentMask) == kExponentMask && (bits & kSignificandMask) != 0;
84 return (bits & kExponentMask) == kExponentMask && (bits & kSignificandMask) == 0;
88 Float Abs()
const {
return IEEEFloat(bits & ~kSignMask).value; }