34template <
int BINARY_PRECISION>
class BinaryFloatingPointNumber {
36 RT_OFFLOAD_VAR_GROUP_BEGIN
38 static constexpr int binaryPrecision{BINARY_PRECISION};
39 static constexpr int bits{realChars.bits};
40 static constexpr int isImplicitMSB{realChars.isImplicitMSB};
41 static constexpr int significandBits{realChars.significandBits};
42 static constexpr int exponentBits{realChars.exponentBits};
43 static constexpr int exponentBias{realChars.exponentBias};
44 static constexpr int maxExponent{realChars.maxExponent};
45 static constexpr int decimalPrecision{realChars.decimalPrecision};
46 static constexpr int decimalRange{realChars.decimalRange};
47 static constexpr int maxDecimalConversionDigits{
48 realChars.maxDecimalConversionDigits};
50 using RawType = common::HostUnsignedIntType<bits>;
51 static_assert(CHAR_BIT *
sizeof(RawType) >= bits);
52 static constexpr RawType significandMask{(RawType{1} << significandBits) - 1};
54 constexpr RT_API_ATTRS BinaryFloatingPointNumber() {}
55 RT_OFFLOAD_VAR_GROUP_END
56 constexpr BinaryFloatingPointNumber(
57 const BinaryFloatingPointNumber &that) =
default;
58 constexpr BinaryFloatingPointNumber(
59 BinaryFloatingPointNumber &&that) =
default;
60 constexpr BinaryFloatingPointNumber &operator=(
61 const BinaryFloatingPointNumber &that) =
default;
62 constexpr BinaryFloatingPointNumber &operator=(
63 BinaryFloatingPointNumber &&that) =
default;
64 constexpr explicit RT_API_ATTRS BinaryFloatingPointNumber(RawType raw)
67 RT_API_ATTRS RawType raw()
const {
return raw_; }
70 explicit constexpr RT_API_ATTRS BinaryFloatingPointNumber(A x) {
71 static_assert(
sizeof raw_ <=
sizeof x);
72 runtime::memcpy(
reinterpret_cast<void *
>(&raw_),
73 reinterpret_cast<const void *
>(&x),
sizeof raw_);
76 constexpr RT_API_ATTRS
int BiasedExponent()
const {
77 return static_cast<int>(
78 (raw_ >> significandBits) & ((1 << exponentBits) - 1));
80 constexpr RT_API_ATTRS
int UnbiasedExponent()
const {
81 int biased{BiasedExponent()};
82 return biased - exponentBias + (biased == 0);
84 constexpr RT_API_ATTRS RawType Significand()
const {
85 return raw_ & significandMask;
87 constexpr RT_API_ATTRS RawType Fraction()
const {
88 RawType sig{Significand()};
89 if (isImplicitMSB && BiasedExponent() > 0) {
90 sig |= RawType{1} << significandBits;
95 constexpr RT_API_ATTRS
bool IsZero()
const {
96 return (raw_ & ((RawType{1} << (bits - 1)) - 1)) == 0;
98 constexpr RT_API_ATTRS
bool IsNaN()
const {
99 auto expo{BiasedExponent()};
100 auto sig{Significand()};
101 if constexpr (bits == 80) {
102 if (expo == maxExponent) {
103 return sig != (significandMask >> 1) + 1;
105 return expo != 0 && !(sig & (RawType{1} << (significandBits - 1)));
109 return expo == maxExponent && sig != 0;
112 constexpr RT_API_ATTRS
bool IsInfinite()
const {
113 if constexpr (bits == 80) {
114 return BiasedExponent() == maxExponent &&
115 Significand() == ((significandMask >> 1) + 1);
117 return BiasedExponent() == maxExponent && Significand() == 0;
120 constexpr RT_API_ATTRS
bool IsMaximalFiniteMagnitude()
const {
121 return BiasedExponent() == maxExponent - 1 &&
122 Significand() == significandMask;
124 constexpr RT_API_ATTRS
bool IsNegative()
const {
125 return ((raw_ >> (bits - 1)) & 1) != 0;
128 constexpr RT_API_ATTRS
void Negate() { raw_ ^= RawType{1} << (bits - 1); }
131 constexpr RT_API_ATTRS
void Previous() {
136 constexpr RT_API_ATTRS
void Next() {
142 static constexpr RT_API_ATTRS BinaryFloatingPointNumber Infinity(
144 RawType result{RawType{maxExponent} << significandBits};
146 result |= RawType{1} << (bits - 1);
148 return BinaryFloatingPointNumber{result};
152 constexpr RT_API_ATTRS
bool RoundToBits(
153 int keepBits,
enum FortranRounding mode) {
154 if (IsNaN() || IsInfinite() || keepBits >= binaryPrecision) {
157 int lostBits{keepBits < binaryPrecision ? binaryPrecision - keepBits : 0};
158 RawType lostMask{
static_cast<RawType
>((RawType{1} << lostBits) - 1)};
159 if (RawType lost{
static_cast<RawType
>(raw_ & lostMask)}; lost != 0) {
160 bool increase{
false};
163 if (lost >> (lostBits - 1) != 0) {
164 if ((lost & (lostMask >> 1)) != 0) {
167 increase = ((raw_ >> lostBits) & 1) != 0;
172 increase = !IsNegative();
175 increase = IsNegative();
179 case RoundCompatible:
180 increase = lost >> (lostBits - 1) != 0;
194 constexpr RT_API_ATTRS
void RemoveExplicitMSB() {
195 if constexpr (!isImplicitMSB) {
196 raw_ = (raw_ & (significandMask >> 1)) | ((raw_ & ~significandMask) >> 1);
199 constexpr RT_API_ATTRS
void InsertExplicitMSB() {
200 if constexpr (!isImplicitMSB) {
201 constexpr RawType mask{significandMask >> 1};
202 raw_ = (raw_ & mask) | ((raw_ & ~mask) << 1);
203 if (BiasedExponent() > 0) {
204 raw_ |= RawType{1} << (significandBits - 1);