32template <
int BINARY_PRECISION>
class BinaryFloatingPointNumber {
34 RT_OFFLOAD_VAR_GROUP_BEGIN
36 static constexpr int binaryPrecision{BINARY_PRECISION};
37 static constexpr int bits{realChars.bits};
38 static constexpr int isImplicitMSB{realChars.isImplicitMSB};
39 static constexpr int significandBits{realChars.significandBits};
40 static constexpr int exponentBits{realChars.exponentBits};
41 static constexpr int exponentBias{realChars.exponentBias};
42 static constexpr int maxExponent{realChars.maxExponent};
43 static constexpr int decimalPrecision{realChars.decimalPrecision};
44 static constexpr int decimalRange{realChars.decimalRange};
45 static constexpr int maxDecimalConversionDigits{
46 realChars.maxDecimalConversionDigits};
48 using RawType = common::HostUnsignedIntType<bits>;
49 static_assert(CHAR_BIT *
sizeof(RawType) >= bits);
50 static constexpr RawType significandMask{(RawType{1} << significandBits) - 1};
52 constexpr RT_API_ATTRS BinaryFloatingPointNumber() {}
53 RT_OFFLOAD_VAR_GROUP_END
54 constexpr BinaryFloatingPointNumber(
55 const BinaryFloatingPointNumber &that) =
default;
56 constexpr BinaryFloatingPointNumber(
57 BinaryFloatingPointNumber &&that) =
default;
58 constexpr BinaryFloatingPointNumber &operator=(
59 const BinaryFloatingPointNumber &that) =
default;
60 constexpr BinaryFloatingPointNumber &operator=(
61 BinaryFloatingPointNumber &&that) =
default;
62 constexpr explicit RT_API_ATTRS BinaryFloatingPointNumber(RawType raw)
65 RT_API_ATTRS RawType raw()
const {
return raw_; }
68 explicit constexpr RT_API_ATTRS BinaryFloatingPointNumber(A x) {
69 static_assert(
sizeof raw_ <=
sizeof x);
70 runtime::memcpy(
reinterpret_cast<void *
>(&raw_),
71 reinterpret_cast<const void *
>(&x),
sizeof raw_);
74 constexpr RT_API_ATTRS
int BiasedExponent()
const {
75 return static_cast<int>(
76 (raw_ >> significandBits) & ((1 << exponentBits) - 1));
78 constexpr RT_API_ATTRS
int UnbiasedExponent()
const {
79 int biased{BiasedExponent()};
80 return biased - exponentBias + (biased == 0);
82 constexpr RT_API_ATTRS RawType Significand()
const {
83 return raw_ & significandMask;
85 constexpr RT_API_ATTRS RawType Fraction()
const {
86 RawType sig{Significand()};
87 if (isImplicitMSB && BiasedExponent() > 0) {
88 sig |= RawType{1} << significandBits;
93 constexpr RT_API_ATTRS
bool IsZero()
const {
94 return (raw_ & ((RawType{1} << (bits - 1)) - 1)) == 0;
96 constexpr RT_API_ATTRS
bool IsNaN()
const {
97 auto expo{BiasedExponent()};
98 auto sig{Significand()};
99 if constexpr (bits == 80) {
100 if (expo == maxExponent) {
101 return sig != (significandMask >> 1) + 1;
103 return expo != 0 && !(sig & (RawType{1} << (significandBits - 1)));
107 return expo == maxExponent && sig != 0;
110 constexpr RT_API_ATTRS
bool IsInfinite()
const {
111 if constexpr (bits == 80) {
112 return BiasedExponent() == maxExponent &&
113 Significand() == ((significandMask >> 1) + 1);
115 return BiasedExponent() == maxExponent && Significand() == 0;
118 constexpr RT_API_ATTRS
bool IsMaximalFiniteMagnitude()
const {
119 return BiasedExponent() == maxExponent - 1 &&
120 Significand() == significandMask;
122 constexpr RT_API_ATTRS
bool IsNegative()
const {
123 return ((raw_ >> (bits - 1)) & 1) != 0;
126 constexpr RT_API_ATTRS
void Negate() { raw_ ^= RawType{1} << (bits - 1); }
129 constexpr RT_API_ATTRS
void Previous() {
134 constexpr RT_API_ATTRS
void Next() {
140 static constexpr RT_API_ATTRS BinaryFloatingPointNumber Infinity(
142 RawType result{RawType{maxExponent} << significandBits};
144 result |= RawType{1} << (bits - 1);
146 return BinaryFloatingPointNumber{result};
150 constexpr RT_API_ATTRS
bool RoundToBits(
151 int keepBits,
enum FortranRounding mode) {
152 if (IsNaN() || IsInfinite() || keepBits >= binaryPrecision) {
155 int lostBits{keepBits < binaryPrecision ? binaryPrecision - keepBits : 0};
156 RawType lostMask{
static_cast<RawType
>((RawType{1} << lostBits) - 1)};
157 if (RawType lost{
static_cast<RawType
>(raw_ & lostMask)}; lost != 0) {
158 bool increase{
false};
161 if (lost >> (lostBits - 1) != 0) {
162 if ((lost & (lostMask >> 1)) != 0) {
165 increase = ((raw_ >> lostBits) & 1) != 0;
170 increase = !IsNegative();
173 increase = IsNegative();
177 case RoundCompatible:
178 increase = lost >> (lostBits - 1) != 0;
192 constexpr RT_API_ATTRS
void RemoveExplicitMSB() {
193 if constexpr (!isImplicitMSB) {
194 raw_ = (raw_ & (significandMask >> 1)) | ((raw_ & ~significandMask) >> 1);
197 constexpr RT_API_ATTRS
void InsertExplicitMSB() {
198 if constexpr (!isImplicitMSB) {
199 constexpr RawType mask{significandMask >> 1};
200 raw_ = (raw_ & mask) | ((raw_ & ~mask) << 1);
201 if (BiasedExponent() > 0) {
202 raw_ |= RawType{1} << (significandBits - 1);