9#ifndef FORTRAN_EVALUATE_REAL_H_
10#define FORTRAN_EVALUATE_REAL_H_
12#include "formatting.h"
14#include "rounding-bits.h"
15#include "flang/Common/real.h"
16#include "flang/Evaluate/target.h"
28namespace Fortran::evaluate::value {
31static constexpr std::int64_t ScaledLogBaseTenOfTwo{301029995664};
38template <
typename WORD,
int PREC>
class Real {
41 static constexpr int binaryPrecision{PREC};
43 static constexpr int exponentBias{realChars.exponentBias};
44 static constexpr int exponentBits{realChars.exponentBits};
45 static constexpr int isImplicitMSB{realChars.isImplicitMSB};
46 static constexpr int maxExponent{realChars.maxExponent};
47 static constexpr int significandBits{realChars.significandBits};
49 static constexpr int bits{Word::bits};
50 static_assert(bits >= realChars.bits);
51 using Fraction = Integer<binaryPrecision>;
53 template <
typename W,
int P>
friend class Real;
56 constexpr Real(
const Real &) =
default;
58 constexpr Real(
const Word &bits) : word_{bits} {}
59 constexpr Real &operator=(
const Real &) =
default;
60 constexpr Real &operator=(
Real &&) =
default;
62 constexpr bool operator==(
const Real &that)
const {
63 return word_ == that.word_;
66 constexpr bool IsSignBitSet()
const {
return word_.BTEST(bits - 1); }
67 constexpr bool IsNegative()
const {
68 return !IsNotANumber() && IsSignBitSet();
70 constexpr bool IsNotANumber()
const {
71 auto expo{Exponent()};
72 auto sig{GetSignificand()};
73 if constexpr (bits == 80) {
75 if (expo == maxExponent) {
76 return sig != Significand{}.IBSET(63);
78 return expo != 0 && !sig.BTEST(63);
81 return expo == maxExponent && !sig.IsZero();
84 constexpr bool IsQuietNaN()
const {
85 auto expo{Exponent()};
86 auto sig{GetSignificand()};
87 if constexpr (bits == 80) {
88 if (expo == maxExponent) {
89 return sig.IBITS(62, 2) == 3;
91 return expo != 0 && !sig.BTEST(63);
94 return expo == maxExponent && sig.BTEST(significandBits - 1);
97 constexpr bool IsSignalingNaN()
const {
98 auto expo{Exponent()};
99 auto sig{GetSignificand()};
100 if constexpr (bits == 80) {
101 return expo == maxExponent && sig != Significand{}.IBSET(63) &&
102 sig.IBITS(62, 2) != 3;
104 return expo == maxExponent && !sig.IsZero() &&
105 !sig.BTEST(significandBits - 1);
108 constexpr bool IsInfinite()
const {
109 if constexpr (bits == 80) {
111 return Exponent() == maxExponent &&
112 GetSignificand() == Significand{}.IBSET(63);
114 return Exponent() == maxExponent && GetSignificand().IsZero();
117 constexpr bool IsFinite()
const {
118 auto expo{Exponent()};
119 if constexpr (bits == 80) {
120 return expo != maxExponent && (expo == 0 || GetSignificand().BTEST(63));
122 return expo != maxExponent;
125 constexpr bool IsZero()
const {
126 return Exponent() == 0 && GetSignificand().IsZero();
128 constexpr bool IsSubnormal()
const {
129 return Exponent() == 0 && !GetSignificand().IsZero();
131 constexpr bool IsNormal()
const {
132 return !(IsInfinite() || IsNotANumber() || IsSubnormal());
135 constexpr Real ABS()
const {
136 return {word_.IBCLR(bits - 1)};
138 constexpr Real SetSign(
bool toNegative)
const {
140 return {word_.IBSET(bits - 1)};
145 constexpr Real SIGN(
const Real &x)
const {
return SetSign(x.IsSignBitSet()); }
147 constexpr Real Negate()
const {
return {word_.IEOR(word_.MASKL(1))}; }
149 Relation Compare(
const Real &)
const;
151 Rounding rounding = TargetCharacteristics::defaultRounding)
const;
153 Rounding rounding = TargetCharacteristics::defaultRounding)
const {
154 return Add(y.Negate(), rounding);
157 Rounding rounding = TargetCharacteristics::defaultRounding)
const;
159 Rounding rounding = TargetCharacteristics::defaultRounding)
const;
162 Rounding rounding = TargetCharacteristics::defaultRounding)
const;
168 Rounding rounding = TargetCharacteristics::defaultRounding)
const;
171 Rounding rounding = TargetCharacteristics::defaultRounding)
const;
175 Rounding rounding = TargetCharacteristics::defaultRounding)
const;
177 Rounding rounding = TargetCharacteristics::defaultRounding)
const;
179 template <
typename INT>
constexpr INT EXPONENT()
const {
180 if (Exponent() == maxExponent) {
182 }
else if (IsZero()) {
185 return {UnbiasedExponent() + 1};
189 static constexpr Real EPSILON() {
192 false, exponentBias + 1 - binaryPrecision, Fraction::MASKL(1));
195 static constexpr Real HUGE() {
197 huge.Normalize(
false, maxExponent - 1, Fraction::MASKR(binaryPrecision));
200 static constexpr Real TINY() {
202 tiny.Normalize(
false, 1, Fraction::MASKL(1));
206 static constexpr int DIGITS{binaryPrecision};
207 static constexpr int PRECISION{realChars.decimalPrecision};
208 static constexpr int RANGE{realChars.decimalRange};
209 static constexpr int MAXEXPONENT{maxExponent - exponentBias};
210 static constexpr int MINEXPONENT{2 - exponentBias};
211 Real RRSPACING()
const;
212 Real SPACING()
const;
213 Real SET_EXPONENT(std::int64_t)
const;
214 Real FRACTION()
const;
217 template <
typename INT>
219 Rounding rounding = TargetCharacteristics::defaultRounding)
const {
223 constexpr auto adjust{exponentBias + binaryPrecision - 1};
224 constexpr auto maxCoeffExpo{maxExponent + binaryPrecision - 1};
225 auto expo{adjust + by.ToInt64()};
230 }
else if (expo > maxCoeffExpo) {
231 if (Exponent() < exponentBias) {
233 return SCALE(INT{exponentBias})
234 .value.SCALE(by.SubtractSigned(INT{exponentBias}).value, rounding);
238 }
else if (expo < 0) {
239 if (Exponent() > exponentBias) {
241 return SCALE(INT{-exponentBias})
242 .value.SCALE(by.AddSigned(INT{exponentBias}).value, rounding);
246 flags.set(RealFlag::Underflow);
251 twoPow.Normalize(
false,
static_cast<int>(expo), Fraction::MASKR(rMask));
253 result.flags |= flags;
257 constexpr Real FlushSubnormalToZero()
const {
265 static constexpr Real NotANumber() {
266 return {Word{maxExponent}
267 .SHIFTL(significandBits)
268 .IBSET(significandBits - 1)
269 .IBSET(significandBits - 2)};
272 static constexpr Real PositiveZero() {
return Real{}; }
274 static constexpr Real NegativeZero() {
return {Word{}.MASKL(1)}; }
276 static constexpr Real Infinity(
bool negative) {
277 Word infinity{maxExponent};
278 infinity = infinity.SHIFTL(significandBits);
280 infinity = infinity.IBSET(infinity.bits - 1);
282 if constexpr (bits == 80) {
284 infinity = infinity.IBSET(63);
289 template <
typename INT>
291 bool isUnsigned =
false,
292 Rounding rounding = TargetCharacteristics::defaultRounding) {
293 bool isNegative{!isUnsigned && n.IsNegative()};
296 absN = n.Negate().value;
298 int leadz{absN.LEADZ()};
299 if (leadz >= absN.bits) {
303 int exponent{exponentBias + absN.bits - leadz - 1};
304 int bitsNeeded{absN.bits - (leadz + isImplicitMSB)};
305 int bitsLost{bitsNeeded - significandBits};
307 Fraction fraction{Fraction::ConvertUnsigned(absN).value};
308 result.flags |= result.value.Normalize(
309 isNegative, exponent, fraction.SHIFTL(-bitsLost));
311 Fraction fraction{Fraction::ConvertUnsigned(absN.SHIFTR(bitsLost)).value};
312 result.flags |= result.value.Normalize(isNegative, exponent, fraction);
314 result.flags |= result.value.Round(rounding, roundingBits);
321 common::RoundingMode = common::RoundingMode::ToZero)
const;
324 template <
typename INT>
326 common::RoundingMode mode = common::RoundingMode::ToZero)
const {
328 if (IsNotANumber()) {
329 result.flags.set(RealFlag::InvalidArgument);
330 result.value = result.value.HUGE();
334 result.flags |= intPart.flags;
335 int exponent{intPart.value.Exponent()};
337 int shift{exponent - exponentBias - binaryPrecision + 1};
339 auto rshifted{intPart.value.GetFraction().SHIFTR(-shift)};
340 auto converted{result.value.ConvertUnsigned(rshifted)};
341 if (converted.overflow) {
342 result.flags.set(RealFlag::Overflow);
344 result.value = converted.value.SHIFTL(shift);
345 if (converted.value.CompareUnsigned(result.value.SHIFTR(shift)) !=
347 result.flags.set(RealFlag::Overflow);
349 if (IsSignBitSet()) {
350 result.value = result.value.Negate().value;
352 if (!result.value.IsZero()) {
353 if (IsSignBitSet() != result.value.IsNegative()) {
354 result.flags.set(RealFlag::Overflow);
357 if (result.flags.test(RealFlag::Overflow)) {
359 IsSignBitSet() ? result.value.MASKL(1) : result.value.HUGE();
364 template <
typename A>
366 const A &x,
Rounding rounding = TargetCharacteristics::defaultRounding) {
368 if (x.IsNotANumber()) {
369 result.flags.set(RealFlag::InvalidArgument);
370 result.value = NotANumber();
373 bool isNegative{x.IsNegative()};
374 if (x.IsInfinite()) {
375 result.value = Infinity(isNegative);
382 int exponent{exponentBias + x.UnbiasedExponent()};
383 int bitsLost{A::binaryPrecision - binaryPrecision};
385 bitsLost += 1 - exponent;
388 typename A::Fraction xFraction{x.GetFraction()};
391 Fraction::ConvertUnsigned(xFraction).value.SHIFTL(-bitsLost)};
392 result.flags |= result.value.Normalize(isNegative, exponent, fraction);
395 Fraction::ConvertUnsigned(xFraction.SHIFTR(bitsLost)).value};
396 result.flags |= result.value.Normalize(isNegative, exponent, fraction);
398 result.flags |= result.value.Round(rounding, roundingBits);
403 constexpr Word RawBits()
const {
return word_; }
406 constexpr int Exponent()
const {
407 return word_.IBITS(significandBits, exponentBits).ToUInt64();
411 constexpr Fraction GetFraction()
const {
412 Fraction result{Fraction::ConvertUnsigned(word_).value};
413 if constexpr (!isImplicitMSB) {
416 int exponent{Exponent()};
417 if (exponent > 0 && exponent < maxExponent) {
418 return result.IBSET(significandBits);
420 return result.IBCLR(significandBits);
429 constexpr int UnbiasedExponent()
const {
430 int exponent{Exponent() - exponentBias};
438 Rounding rounding = TargetCharacteristics::defaultRounding);
439 std::string DumpHexadecimal()
const;
443 llvm::raw_ostream &AsFortran(
444 llvm::raw_ostream &,
int kind,
bool minimal =
false)
const;
447 using Significand = Integer<significandBits>;
449 constexpr Significand GetSignificand()
const {
450 return Significand::ConvertUnsigned(word_).value;
453 constexpr int CombineExponents(
const Real &y,
bool forDivide)
const {
454 int exponent = Exponent(), yExponent = y.Exponent();
456 exponent += !exponent;
457 yExponent += !yExponent;
459 exponent += exponentBias - yExponent;
461 exponent += yExponent - exponentBias + 1;
466 static constexpr bool NextQuotientBit(
467 Fraction &top,
bool &msb,
const Fraction &divisor) {
468 bool greaterOrEqual{msb || top.CompareUnsigned(divisor) != Ordering::Less};
469 if (greaterOrEqual) {
470 top = top.SubtractSigned(divisor).value;
472 auto doubled{top.AddUnsigned(top)};
475 return greaterOrEqual;
482 RealFlags Normalize(
bool negative,
int exponent,
const Fraction &fraction,
483 Rounding rounding = TargetCharacteristics::defaultRounding,
491 bool multiply =
false);
Definition: rounding-bits.h:20
Definition: target-rounding.h:18
Definition: expression.h:296
Definition: expression.h:211
Definition: expression.h:317
Definition: expression.h:310
Definition: expression.h:247
Definition: expression.h:303