FLANG

real.h
1 //===-- include/flang/Evaluate/real.h ---------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef FORTRAN_EVALUATE_REAL_H_
10 #define FORTRAN_EVALUATE_REAL_H_
11
12 #include "formatting.h"
13 #include "integer.h"
14 #include "rounding-bits.h"
15 #include "flang/Common/real.h"
16 #include "flang/Evaluate/common.h"
17 #include <cinttypes>
18 #include <limits>
19 #include <string>
20
21 // Some environments, viz. clang on Darwin, allow the macro HUGE
22 // to leak out of <math.h> even when it is never directly included.
23 #undef HUGE
24
25 namespace llvm {
26 class raw_ostream;
27 }
28 namespace Fortran::evaluate::value {
29
30 // LOG10(2.)*1E12
31 static constexpr std::int64_t ScaledLogBaseTenOfTwo{301029995664};
32
33 // Models IEEE binary floating-point numbers (IEEE 754-2008,
34 // ISO/IEC/IEEE 60559.2011). The first argument to this
35 // class template must be (or look like) an instance of Integer<>;
36 // the second specifies the number of effective bits (binary precision)
37 // in the fraction.
38 template <typename WORD, int PREC>
39 class Real : public common::RealDetails<PREC> {
40 public:
41 using Word = WORD;
42 static constexpr int binaryPrecision{PREC};
43 using Details = common::RealDetails<PREC>;
44 using Details::exponentBias;
45 using Details::exponentBits;
46 using Details::isImplicitMSB;
47 using Details::maxExponent;
48 using Details::significandBits;
49
50 static constexpr int bits{Word::bits};
51 static_assert(bits >= Details::bits);
52 using Fraction = Integer<binaryPrecision>; // all bits made explicit
53
54 template <typename W, int P> friend class Real;
55
56 constexpr Real() {} // +0.0
57 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;
61
62 constexpr bool operator==(const Real &that) const {
63 return word_ == that.word_;
64 }
65
66 // TODO: DIM, MAX, MIN, DPROD, FRACTION,
67 // INT/NINT, NEAREST, OUT_OF_RANGE,
68 // RRSPACING/SPACING, SCALE, SET_EXPONENT
69
70 constexpr bool IsSignBitSet() const { return word_.BTEST(bits - 1); }
71 constexpr bool IsNegative() const {
72 return !IsNotANumber() && IsSignBitSet();
73 }
74 constexpr bool IsNotANumber() const {
75 return Exponent() == maxExponent && !GetSignificand().IsZero();
76 }
77 constexpr bool IsQuietNaN() const {
78 return Exponent() == maxExponent &&
79 GetSignificand().BTEST(significandBits - 1);
80 }
81 constexpr bool IsSignalingNaN() const {
82 return IsNotANumber() && !GetSignificand().BTEST(significandBits - 1);
83 }
84 constexpr bool IsInfinite() const {
85 return Exponent() == maxExponent && GetSignificand().IsZero();
86 }
87 constexpr bool IsZero() const {
88 return Exponent() == 0 && GetSignificand().IsZero();
89 }
90 constexpr bool IsSubnormal() const {
91 return Exponent() == 0 && !GetSignificand().IsZero();
92 }
93
94 constexpr Real ABS() const { // non-arithmetic, no flags returned
95 return {word_.IBCLR(bits - 1)};
96 }
97 constexpr Real SetSign(bool toNegative) const { // non-arithmetic
98 if (toNegative) {
99 return {word_.IBSET(bits - 1)};
100 } else {
101 return ABS();
102 }
103 }
104 constexpr Real SIGN(const Real &x) const { return SetSign(x.IsSignBitSet()); }
105
106 constexpr Real Negate() const { return {word_.IEOR(word_.MASKL(1))}; }
107
108 Relation Compare(const Real &) const;
109 ValueWithRealFlags<Real> Add(
110 const Real &, Rounding rounding = defaultRounding) const;
111 ValueWithRealFlags<Real> Subtract(
112 const Real &y, Rounding rounding = defaultRounding) const {
113 return Add(y.Negate(), rounding);
114 }
115 ValueWithRealFlags<Real> Multiply(
116 const Real &, Rounding rounding = defaultRounding) const;
117 ValueWithRealFlags<Real> Divide(
118 const Real &, Rounding rounding = defaultRounding) const;
119
120 // SQRT(x**2 + y**2) but computed so as to avoid spurious overflow
121 // TODO: needed for CABS
122 ValueWithRealFlags<Real> HYPOT(
123 const Real &, Rounding rounding = defaultRounding) const;
124
125 template <typename INT> constexpr INT EXPONENT() const {
126 if (Exponent() == maxExponent) {
127 return INT::HUGE();
128 } else {
129 return {UnbiasedExponent()};
130 }
131 }
132
133 static constexpr Real EPSILON() {
134 Real epsilon;
135 epsilon.Normalize(
136 false, exponentBias - binaryPrecision, Fraction::MASKL(1));
137 return epsilon;
138 }
139 static constexpr Real HUGE() {
140 Real huge;
141 huge.Normalize(false, maxExponent - 1, Fraction::MASKR(binaryPrecision));
142 return huge;
143 }
144 static constexpr Real TINY() {
145 Real tiny;
146 tiny.Normalize(false, 1, Fraction::MASKL(1)); // minimum *normal* number
147 return tiny;
148 }
149
150 static constexpr int DIGITS{binaryPrecision};
151 static constexpr int PRECISION{Details::decimalPrecision};
152 static constexpr int RANGE{Details::decimalRange};
153 static constexpr int MAXEXPONENT{maxExponent - 1 - exponentBias};
154 static constexpr int MINEXPONENT{1 - exponentBias};
155
156 constexpr Real FlushSubnormalToZero() const {
157 if (IsSubnormal()) {
158 return Real{};
159 }
160 return *this;
161 }
162
163 // TODO: Configurable NotANumber representations
164 static constexpr Real NotANumber() {
165 return {Word{maxExponent}
166 .SHIFTL(significandBits)
167 .IBSET(significandBits - 1)
168 .IBSET(significandBits - 2)};
169 }
170
171 static constexpr Real Infinity(bool negative) {
172 Word infinity{maxExponent};
173 infinity = infinity.SHIFTL(significandBits);
174 if (negative) {
175 infinity = infinity.IBSET(infinity.bits - 1);
176 }
177 return {infinity};
178 }
179
180 template <typename INT>
181 static ValueWithRealFlags<Real> FromInteger(
182 const INT &n, Rounding rounding = defaultRounding) {
183 bool isNegative{n.IsNegative()};
184 INT absN{n};
185 if (isNegative) {
186 absN = n.Negate().value; // overflow is safe to ignore
187 }
188 int leadz{absN.LEADZ()};
189 if (leadz >= absN.bits) {
190 return {}; // all bits zero -> +0.0
191 }
192 ValueWithRealFlags<Real> result;
193 int exponent{exponentBias + absN.bits - leadz - 1};
194 int bitsNeeded{absN.bits - (leadz + isImplicitMSB)};
195 int bitsLost{bitsNeeded - significandBits};
196 if (bitsLost <= 0) {
197 Fraction fraction{Fraction::ConvertUnsigned(absN).value};
198 result.flags |= result.value.Normalize(
199 isNegative, exponent, fraction.SHIFTL(-bitsLost));
200 } else {
201 Fraction fraction{Fraction::ConvertUnsigned(absN.SHIFTR(bitsLost)).value};
202 result.flags |= result.value.Normalize(isNegative, exponent, fraction);
203 RoundingBits roundingBits{absN, bitsLost};
204 result.flags |= result.value.Round(rounding, roundingBits);
205 }
206 return result;
207 }
208
209 // Conversion to integer in the same real format (AINT(), ANINT())
210 ValueWithRealFlags<Real> ToWholeNumber(
211 common::RoundingMode = common::RoundingMode::ToZero) const;
212
213 // Conversion to an integer (INT(), NINT(), FLOOR(), CEILING())
214 template <typename INT>
215 constexpr ValueWithRealFlags<INT> ToInteger(
216 common::RoundingMode mode = common::RoundingMode::ToZero) const {
217 ValueWithRealFlags<INT> result;
218 if (IsNotANumber()) {
219 result.flags.set(RealFlag::InvalidArgument);
220 result.value = result.value.HUGE();
221 return result;
222 }
223 ValueWithRealFlags<Real> intPart{ToWholeNumber(mode)};
224 int exponent{intPart.value.Exponent()};
225 result.flags.set(
226 RealFlag::Overflow, exponent >= exponentBias + result.value.bits);
227 result.flags |= intPart.flags;
228 int shift{
229 exponent - exponentBias - binaryPrecision + 1}; // positive -> left
230 result.value =
231 result.value.ConvertUnsigned(intPart.value.GetFraction().SHIFTR(-shift))
232 .value.SHIFTL(shift);
233 if (IsSignBitSet()) {
234 auto negated{result.value.Negate()};
235 result.value = negated.value;
236 if (negated.overflow) {
237 result.flags.set(RealFlag::Overflow);
238 }
239 }
240 if (result.flags.test(RealFlag::Overflow)) {
241 result.value =
242 IsSignBitSet() ? result.value.MASKL(1) : result.value.HUGE();
243 }
244 return result;
245 }
246
247 template <typename A>
248 static ValueWithRealFlags<Real> Convert(
249 const A &x, Rounding rounding = defaultRounding) {
250 bool isNegative{x.IsNegative()};
251 A absX{x};
252 if (isNegative) {
253 absX = x.Negate();
254 }
255 ValueWithRealFlags<Real> result;
256 int exponent{exponentBias + x.UnbiasedExponent()};
257 int bitsLost{A::binaryPrecision - binaryPrecision};
258 if (exponent < 1) {
259 bitsLost += 1 - exponent;
260 exponent = 1;
261 }
262 typename A::Fraction xFraction{x.GetFraction()};
263 if (bitsLost <= 0) {
264 Fraction fraction{
265 Fraction::ConvertUnsigned(xFraction).value.SHIFTL(-bitsLost)};
266 result.flags |= result.value.Normalize(isNegative, exponent, fraction);
267 } else {
268 Fraction fraction{
269 Fraction::ConvertUnsigned(xFraction.SHIFTR(bitsLost)).value};
270 result.flags |= result.value.Normalize(isNegative, exponent, fraction);
271 RoundingBits roundingBits{xFraction, bitsLost};
272 result.flags |= result.value.Round(rounding, roundingBits);
273 }
274 return result;
275 }
276
277 constexpr Word RawBits() const { return word_; }
278
279 // Extracts "raw" biased exponent field.
280 constexpr int Exponent() const {
281 return word_.IBITS(significandBits, exponentBits).ToUInt64();
282 }
283
284 // Extracts the fraction; any implied bit is made explicit.
285 constexpr Fraction GetFraction() const {
286 Fraction result{Fraction::ConvertUnsigned(word_).value};
287 if constexpr (!isImplicitMSB) {
288 return result;
289 } else {
290 int exponent{Exponent()};
291 if (exponent > 0 && exponent < maxExponent) {
292 return result.IBSET(significandBits);
293 } else {
294 return result.IBCLR(significandBits);
295 }
296 }
297 }
298
299 // Extracts unbiased exponent value.
300 // Corrects the exponent value of a subnormal number.
301 constexpr int UnbiasedExponent() const {
302 int exponent{Exponent() - exponentBias};
303 if (IsSubnormal()) {
304 ++exponent;
305 }
306 return exponent;
307 }
308
309 static ValueWithRealFlags<Real> Read(
310 const char *&, Rounding rounding = defaultRounding);
311 std::string DumpHexadecimal() const;
312
313 // Emits a character representation for an equivalent Fortran constant
314 // or parenthesized constant expression that produces this value.
315 llvm::raw_ostream &AsFortran(
316 llvm::raw_ostream &, int kind, bool minimal = false) const;
317
318 private:
319 using Significand = Integer<significandBits>; // no implicit bit
320
321 constexpr Significand GetSignificand() const {
322 return Significand::ConvertUnsigned(word_).value;
323 }
324
325 constexpr int CombineExponents(const Real &y, bool forDivide) const {
326 int exponent = Exponent(), yExponent = y.Exponent();
327 // A zero exponent field value has the same weight as 1.
328 exponent += !exponent;
329 yExponent += !yExponent;
330 if (forDivide) {
331 exponent += exponentBias - yExponent;
332 } else {
333 exponent += yExponent - exponentBias + 1;
334 }
335 return exponent;
336 }
337
338 static constexpr bool NextQuotientBit(
339 Fraction &top, bool &msb, const Fraction &divisor) {
340 bool greaterOrEqual{msb || top.CompareUnsigned(divisor) != Ordering::Less};
341 if (greaterOrEqual) {
342 top = top.SubtractSigned(divisor).value;
343 }
344 auto doubled{top.AddUnsigned(top)};
345 top = doubled.value;
346 msb = doubled.carry;
347 return greaterOrEqual;
348 }
349
350 // Normalizes and marshals the fields of a floating-point number in place.
351 // The value is a number, and a zero fraction means a zero value (i.e.,
352 // a maximal exponent and zero fraction doesn't signify infinity, although
353 // this member function will detect overflow and encode infinities).
354 RealFlags Normalize(bool negative, int exponent, const Fraction &fraction,
355 Rounding rounding = defaultRounding,
356 RoundingBits *roundingBits = nullptr);
357
358 // Rounds a result, if necessary, in place.
359 RealFlags Round(Rounding, const RoundingBits &, bool multiply = false);
360
361 static void NormalizeAndRound(ValueWithRealFlags<Real> &result,
362 bool isNegative, int exponent, const Fraction &, Rounding, RoundingBits,
363 bool multiply = false);
364
365 Word word_{}; // an Integer<>
366 };
367
368 extern template class Real<Integer<16>, 11>; // IEEE half format
369 extern template class Real<Integer<16>, 8>; // the "other" half format
370 extern template class Real<Integer<32>, 24>; // IEEE single
371 extern template class Real<Integer<64>, 53>; // IEEE double
372 extern template class Real<Integer<80>, 64>; // 80387 extended precision
373 extern template class Real<Integer<128>, 113>; // IEEE quad
374 // N.B. No "double-double" support.
375 } // namespace Fortran::evaluate::value
376 #endif // FORTRAN_EVALUATE_REAL_H_
Fortran::evaluate::value::RoundingBits
Definition: rounding-bits.h:18
Fortran::evaluate::Add
Definition: expression.h:278
Fortran::evaluate::Subtract
Definition: expression.h:285
Fortran::evaluate::Rounding
Definition: common.h:122
Fortran::evaluate::Divide
Definition: expression.h:299
Fortran::evaluate::Multiply
Definition: expression.h:292
Fortran::common::RealDetails
Definition: real.h:67
Fortran::evaluate::value::Real
Definition: real.h:39
Fortran::evaluate::Convert
Definition: expression.h:202
Fortran::evaluate::Negate
Definition: expression.h:229
Fortran::evaluate::ValueWithRealFlags
Definition: common.h:113