1 //===-- lib/Evaluate/real.cpp ---------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "flang/Evaluate/real.h"
10 #include "int-power.h"
11 #include "flang/Common/idioms.h"
12 #include "flang/Decimal/decimal.h"
13 #include "flang/Parser/characters.h"
14 #include "llvm/Support/raw_ostream.h"
17 namespace Fortran::evaluate::value
{
19 template <typename W
, int P
> Relation Real
<W
, P
>::Compare(const Real
&y
) const {
20 if (IsNotANumber() || y
.IsNotANumber()) { // NaN vs x, x vs NaN
21 return Relation::Unordered
;
22 } else if (IsInfinite()) {
24 if (IsNegative()) { // -Inf vs +/-Inf
25 return y
.IsNegative() ? Relation::Equal
: Relation::Less
;
26 } else { // +Inf vs +/-Inf
27 return y
.IsNegative() ? Relation::Greater
: Relation::Equal
;
29 } else { // +/-Inf vs finite
30 return IsNegative() ? Relation::Less
: Relation::Greater
;
32 } else if (y
.IsInfinite()) { // finite vs +/-Inf
33 return y
.IsNegative() ? Relation::Greater
: Relation::Less
;
34 } else { // two finite numbers
35 bool isNegative
{IsNegative()};
36 if (isNegative
!= y
.IsNegative()) {
37 if (word_
.IOR(y
.word_
).IBCLR(bits
- 1).IsZero()) {
38 return Relation::Equal
; // +/-0.0 == -/+0.0
40 return isNegative
? Relation::Less
: Relation::Greater
;
44 Ordering order
{evaluate::Compare(Exponent(), y
.Exponent())};
45 if (order
== Ordering::Equal
) {
46 order
= GetSignificand().CompareUnsigned(y
.GetSignificand());
49 order
= Reverse(order
);
51 return RelationFromOrdering(order
);
56 template <typename W
, int P
>
57 ValueWithRealFlags
<Real
<W
, P
>> Real
<W
, P
>::Add(
58 const Real
&y
, Rounding rounding
) const {
59 ValueWithRealFlags
<Real
> result
;
60 if (IsNotANumber() || y
.IsNotANumber()) {
61 result
.value
= NotANumber(); // NaN + x -> NaN
62 if (IsSignalingNaN() || y
.IsSignalingNaN()) {
63 result
.flags
.set(RealFlag::InvalidArgument
);
67 bool isNegative
{IsNegative()};
68 bool yIsNegative
{y
.IsNegative()};
71 if (isNegative
== yIsNegative
) {
72 result
.value
= *this; // +/-Inf + +/-Inf -> +/-Inf
74 result
.value
= NotANumber(); // +/-Inf + -/+Inf -> NaN
75 result
.flags
.set(RealFlag::InvalidArgument
);
78 result
.value
= *this; // +/-Inf + x -> +/-Inf
83 result
.value
= y
; // x + +/-Inf -> +/-Inf
86 int exponent
{Exponent()};
87 int yExponent
{y
.Exponent()};
88 if (exponent
< yExponent
) {
89 // y is larger in magnitude; simplify by reversing operands
90 return y
.Add(*this, rounding
);
92 if (exponent
== yExponent
&& isNegative
!= yIsNegative
) {
93 Ordering order
{GetSignificand().CompareUnsigned(y
.GetSignificand())};
94 if (order
== Ordering::Less
) {
95 // Same exponent, opposite signs, and y is larger in magnitude
96 return y
.Add(*this, rounding
);
98 if (order
== Ordering::Equal
) {
99 // x + (-x) -> +0.0 unless rounding is directed downwards
100 if (rounding
.mode
== common::RoundingMode::Down
) {
101 result
.value
= NegativeZero();
106 // Our exponent is greater than y's, or the exponents match and y is not
107 // of the opposite sign and greater magnitude. So (x+y) will have the
109 Fraction fraction
{GetFraction()};
110 Fraction yFraction
{y
.GetFraction()};
111 int rshift
= exponent
- yExponent
;
112 if (exponent
> 0 && yExponent
== 0) {
113 --rshift
; // correct overshift when only y is subnormal
115 RoundingBits roundingBits
{yFraction
, rshift
};
116 yFraction
= yFraction
.SHIFTR(rshift
);
118 if (isNegative
!= yIsNegative
) {
119 // Opposite signs: subtract via addition of two's complement of y and
120 // the rounding bits.
121 yFraction
= yFraction
.NOT();
122 carry
= roundingBits
.Negate();
124 auto sum
{fraction
.AddUnsigned(yFraction
, carry
)};
125 fraction
= sum
.value
;
126 if (isNegative
== yIsNegative
&& sum
.carry
) {
127 roundingBits
.ShiftRight(sum
.value
.BTEST(0));
128 fraction
= fraction
.SHIFTR(1).IBSET(fraction
.bits
- 1);
132 result
, isNegative
, exponent
, fraction
, rounding
, roundingBits
);
136 template <typename W
, int P
>
137 ValueWithRealFlags
<Real
<W
, P
>> Real
<W
, P
>::Multiply(
138 const Real
&y
, Rounding rounding
) const {
139 ValueWithRealFlags
<Real
> result
;
140 if (IsNotANumber() || y
.IsNotANumber()) {
141 result
.value
= NotANumber(); // NaN * x -> NaN
142 if (IsSignalingNaN() || y
.IsSignalingNaN()) {
143 result
.flags
.set(RealFlag::InvalidArgument
);
146 bool isNegative
{IsNegative() != y
.IsNegative()};
147 if (IsInfinite() || y
.IsInfinite()) {
148 if (IsZero() || y
.IsZero()) {
149 result
.value
= NotANumber(); // 0 * Inf -> NaN
150 result
.flags
.set(RealFlag::InvalidArgument
);
152 result
.value
= Infinity(isNegative
);
155 auto product
{GetFraction().MultiplyUnsigned(y
.GetFraction())};
156 std::int64_t exponent
{CombineExponents(y
, false)};
158 int rshift
= 1 - exponent
;
161 if (rshift
>= product
.upper
.bits
+ product
.lower
.bits
) {
162 sticky
= !product
.lower
.IsZero() || !product
.upper
.IsZero();
163 } else if (rshift
>= product
.lower
.bits
) {
164 sticky
= !product
.lower
.IsZero() ||
166 .IAND(product
.upper
.MASKR(rshift
- product
.lower
.bits
))
169 sticky
= !product
.lower
.IAND(product
.lower
.MASKR(rshift
)).IsZero();
171 product
.lower
= product
.lower
.SHIFTRWithFill(product
.upper
, rshift
);
172 product
.upper
= product
.upper
.SHIFTR(rshift
);
174 product
.lower
= product
.lower
.IBSET(0);
177 int leadz
{product
.upper
.LEADZ()};
178 if (leadz
>= product
.upper
.bits
) {
179 leadz
+= product
.lower
.LEADZ();
182 if (lshift
> exponent
- 1) {
183 lshift
= exponent
- 1;
186 product
.upper
= product
.upper
.SHIFTLWithFill(product
.lower
, lshift
);
187 product
.lower
= product
.lower
.SHIFTL(lshift
);
188 RoundingBits roundingBits
{product
.lower
, product
.lower
.bits
};
189 NormalizeAndRound(result
, isNegative
, exponent
, product
.upper
, rounding
,
190 roundingBits
, true /*multiply*/);
196 template <typename W
, int P
>
197 ValueWithRealFlags
<Real
<W
, P
>> Real
<W
, P
>::Divide(
198 const Real
&y
, Rounding rounding
) const {
199 ValueWithRealFlags
<Real
> result
;
200 if (IsNotANumber() || y
.IsNotANumber()) {
201 result
.value
= NotANumber(); // NaN / x -> NaN, x / NaN -> NaN
202 if (IsSignalingNaN() || y
.IsSignalingNaN()) {
203 result
.flags
.set(RealFlag::InvalidArgument
);
206 bool isNegative
{IsNegative() != y
.IsNegative()};
208 if (y
.IsInfinite()) {
209 result
.value
= NotANumber(); // Inf/Inf -> NaN
210 result
.flags
.set(RealFlag::InvalidArgument
);
211 } else { // Inf/x -> Inf, Inf/0 -> Inf
212 result
.value
= Infinity(isNegative
);
214 } else if (y
.IsZero()) {
215 if (IsZero()) { // 0/0 -> NaN
216 result
.value
= NotANumber();
217 result
.flags
.set(RealFlag::InvalidArgument
);
218 } else { // x/0 -> Inf, Inf/0 -> Inf
219 result
.value
= Infinity(isNegative
);
220 result
.flags
.set(RealFlag::DivideByZero
);
222 } else if (IsZero() || y
.IsInfinite()) { // 0/x, x/Inf -> 0
224 result
.value
= NegativeZero();
227 // dividend and divisor are both finite and nonzero numbers
228 Fraction top
{GetFraction()}, divisor
{y
.GetFraction()};
229 std::int64_t exponent
{CombineExponents(y
, true)};
232 if (!top
.BTEST(top
.bits
- 1) || !divisor
.BTEST(divisor
.bits
- 1)) {
233 // One or two subnormals
234 int topLshift
{top
.LEADZ()};
235 top
= top
.SHIFTL(topLshift
);
236 int divisorLshift
{divisor
.LEADZ()};
237 divisor
= divisor
.SHIFTL(divisorLshift
);
238 exponent
+= divisorLshift
- topLshift
;
240 for (int j
{1}; j
<= quotient
.bits
; ++j
) {
241 if (NextQuotientBit(top
, msb
, divisor
)) {
242 quotient
= quotient
.IBSET(quotient
.bits
- j
);
245 bool guard
{NextQuotientBit(top
, msb
, divisor
)};
246 bool round
{NextQuotientBit(top
, msb
, divisor
)};
247 bool sticky
{msb
|| !top
.IsZero()};
248 RoundingBits roundingBits
{guard
, round
, sticky
};
250 std::int64_t rshift
{1 - exponent
};
251 for (; rshift
> 0; --rshift
) {
252 roundingBits
.ShiftRight(quotient
.BTEST(0));
253 quotient
= quotient
.SHIFTR(1);
258 result
, isNegative
, exponent
, quotient
, rounding
, roundingBits
);
264 template <typename W
, int P
>
265 ValueWithRealFlags
<Real
<W
, P
>> Real
<W
, P
>::SQRT(Rounding rounding
) const {
266 ValueWithRealFlags
<Real
> result
;
267 if (IsNotANumber()) {
268 result
.value
= NotANumber();
269 if (IsSignalingNaN()) {
270 result
.flags
.set(RealFlag::InvalidArgument
);
272 } else if (IsNegative()) {
274 // SQRT(-0) == -0 in IEEE-754.
275 result
.value
= NegativeZero();
277 result
.flags
.set(RealFlag::InvalidArgument
);
278 result
.value
= NotANumber();
280 } else if (IsInfinite()) {
281 // SQRT(+Inf) == +Inf
282 result
.value
= Infinity(false);
283 } else if (IsZero()) {
284 result
.value
= PositiveZero();
286 int expo
{UnbiasedExponent()};
287 if (expo
< -1 || expo
> 1) {
288 // Reduce the range to [0.5 .. 4.0) by dividing by an integral power
289 // of four to avoid trouble with very large and very small values
290 // (esp. truncation of subnormals).
291 // SQRT(2**(2a) * x) = SQRT(2**(2a)) * SQRT(x) = 2**a * SQRT(x)
293 int adjust
{expo
/ 2};
294 scaled
.Normalize(false, expo
- 2 * adjust
+ exponentBias
, GetFraction());
295 result
= scaled
.SQRT(rounding
);
296 result
.value
.Normalize(false,
297 result
.value
.UnbiasedExponent() + adjust
+ exponentBias
,
298 result
.value
.GetFraction());
301 // (-1) <= expo <= 1; use it as a shift to set the desired square.
302 using Extended
= typename
value::Integer
<(binaryPrecision
+ 2)>;
304 Extended::ConvertUnsigned(GetFraction()).value
.SHIFTL(expo
+ 1)};
305 // Calculate the exact square root by maximizing a value whose square
306 // does not exceed the goal. Use two extra bits of precision for
310 for (int bit
{Extended::bits
- 1}; bit
>= 0; --bit
) {
311 Extended next
{extFrac
.IBSET(bit
)};
312 auto squared
{next
.MultiplyUnsigned(next
)};
313 auto cmp
{squared
.upper
.CompareUnsigned(goal
)};
314 if (cmp
== Ordering::Less
) {
316 } else if (cmp
== Ordering::Equal
&& squared
.lower
.IsZero()) {
319 break; // exact result
322 RoundingBits roundingBits
{extFrac
.BTEST(1), extFrac
.BTEST(0), sticky
};
323 NormalizeAndRound(result
, false, exponentBias
,
324 Fraction::ConvertUnsigned(extFrac
.SHIFTR(2)).value
, rounding
,
330 template <typename W
, int P
>
331 ValueWithRealFlags
<Real
<W
, P
>> Real
<W
, P
>::NEAREST(bool upward
) const {
332 ValueWithRealFlags
<Real
> result
;
333 bool isNegative
{IsNegative()};
335 Fraction fraction
{GetFraction()};
336 int expo
{Exponent()};
339 if (upward
!= isNegative
) { // upward in magnitude
340 auto next
{fraction
.AddUnsigned(one
)};
343 nearest
= Fraction::Least(); // MSB only
345 nearest
= next
.value
;
347 } else { // downward in magnitude
349 nearest
= 1; // smallest magnitude negative subnormal
350 isNegative
= !isNegative
;
352 auto sub1
{fraction
.SubtractSigned(one
)};
353 if (sub1
.overflow
&& expo
> 1) {
354 nearest
= Fraction
{0}.NOT();
357 nearest
= sub1
.value
;
361 result
.value
.Normalize(isNegative
, expo
, nearest
);
362 } else if (IsInfinite()) {
363 if (upward
== isNegative
) {
365 isNegative
? HUGE().Negate() : HUGE(); // largest mag finite
367 result
.value
= *this;
370 result
.flags
.set(RealFlag::InvalidArgument
);
371 result
.value
= *this;
376 // HYPOT(x,y) = SQRT(x**2 + y**2) by definition, but those squared intermediate
377 // values are susceptible to over/underflow when computed naively.
378 // Assuming that x>=y, calculate instead:
379 // HYPOT(x,y) = SQRT(x**2 * (1+(y/x)**2))
380 // = ABS(x) * SQRT(1+(y/x)**2)
381 template <typename W
, int P
>
382 ValueWithRealFlags
<Real
<W
, P
>> Real
<W
, P
>::HYPOT(
383 const Real
&y
, Rounding rounding
) const {
384 ValueWithRealFlags
<Real
> result
;
385 if (IsNotANumber() || y
.IsNotANumber()) {
386 result
.flags
.set(RealFlag::InvalidArgument
);
387 result
.value
= NotANumber();
388 } else if (ABS().Compare(y
.ABS()) == Relation::Less
) {
389 return y
.HYPOT(*this);
390 } else if (IsZero()) {
391 return result
; // x==y==0
393 auto yOverX
{y
.Divide(*this, rounding
)}; // y/x
394 bool inexact
{yOverX
.flags
.test(RealFlag::Inexact
)};
395 auto squared
{yOverX
.value
.Multiply(yOverX
.value
, rounding
)}; // (y/x)**2
396 inexact
|= squared
.flags
.test(RealFlag::Inexact
);
398 one
.Normalize(false, exponentBias
, Fraction::MASKL(1)); // 1.0
399 auto sum
{squared
.value
.Add(one
, rounding
)}; // 1.0 + (y/x)**2
400 inexact
|= sum
.flags
.test(RealFlag::Inexact
);
401 auto sqrt
{sum
.value
.SQRT()};
402 inexact
|= sqrt
.flags
.test(RealFlag::Inexact
);
403 result
= sqrt
.value
.Multiply(ABS(), rounding
);
405 result
.flags
.set(RealFlag::Inexact
);
411 // MOD(x,y) = x - AINT(x/y)*y in the standard; unfortunately, this definition
412 // can be pretty inaccurate when x is much larger than y in magnitude due to
413 // cancellation. Implement instead with (essentially) arbitrary precision
414 // long division, discarding the quotient and returning the remainder.
415 // See runtime/numeric.cpp for more details.
416 template <typename W
, int P
>
417 ValueWithRealFlags
<Real
<W
, P
>> Real
<W
, P
>::MOD(
418 const Real
&p
, Rounding rounding
) const {
419 ValueWithRealFlags
<Real
> result
;
420 if (IsNotANumber() || p
.IsNotANumber() || IsInfinite()) {
421 result
.flags
.set(RealFlag::InvalidArgument
);
422 result
.value
= NotANumber();
423 } else if (p
.IsZero()) {
424 result
.flags
.set(RealFlag::DivideByZero
);
425 result
.value
= NotANumber();
426 } else if (p
.IsInfinite()) {
427 result
.value
= *this;
429 result
.value
= ABS();
432 half
.Normalize(false, exponentBias
- 1, Fraction::MASKL(1)); // 0.5
433 for (adj
.Normalize(false, Exponent(), pAbs
.GetFraction());
434 result
.value
.Compare(pAbs
) != Relation::Less
;
435 adj
= adj
.Multiply(half
).value
) {
436 if (result
.value
.Compare(adj
) != Relation::Less
) {
438 result
.value
.Subtract(adj
, rounding
).AccumulateFlags(result
.flags
);
439 if (result
.value
.IsZero()) {
445 result
.value
= result
.value
.Negate();
451 // MODULO(x,y) = x - FLOOR(x/y)*y in the standard; here, it is defined
452 // in terms of MOD() with adjustment of the result.
453 template <typename W
, int P
>
454 ValueWithRealFlags
<Real
<W
, P
>> Real
<W
, P
>::MODULO(
455 const Real
&p
, Rounding rounding
) const {
456 ValueWithRealFlags
<Real
> result
{MOD(p
, rounding
)};
457 if (IsNegative() != p
.IsNegative()) {
458 if (result
.value
.IsZero()) {
459 result
.value
= result
.value
.Negate();
462 result
.value
.Add(p
, rounding
).AccumulateFlags(result
.flags
);
468 template <typename W
, int P
>
469 ValueWithRealFlags
<Real
<W
, P
>> Real
<W
, P
>::DIM(
470 const Real
&y
, Rounding rounding
) const {
471 ValueWithRealFlags
<Real
> result
;
472 if (IsNotANumber() || y
.IsNotANumber()) {
473 result
.flags
.set(RealFlag::InvalidArgument
);
474 result
.value
= NotANumber();
475 } else if (Compare(y
) == Relation::Greater
) {
476 result
= Subtract(y
, rounding
);
478 // result is already zero
483 template <typename W
, int P
>
484 ValueWithRealFlags
<Real
<W
, P
>> Real
<W
, P
>::ToWholeNumber(
485 common::RoundingMode mode
) const {
486 ValueWithRealFlags
<Real
> result
{*this};
487 if (IsNotANumber()) {
488 result
.flags
.set(RealFlag::InvalidArgument
);
489 result
.value
= NotANumber();
490 } else if (IsInfinite()) {
491 result
.flags
.set(RealFlag::Overflow
);
493 constexpr int noClipExponent
{exponentBias
+ binaryPrecision
- 1};
494 if (Exponent() < noClipExponent
) {
495 Real adjust
; // ABS(EPSILON(adjust)) == 0.5
496 adjust
.Normalize(IsSignBitSet(), noClipExponent
, Fraction::MASKL(1));
497 // Compute ival=(*this + adjust), losing any fractional bits; keep flags
498 result
= Add(adjust
, Rounding
{mode
});
499 result
.flags
.reset(RealFlag::Inexact
); // result *is* exact
500 // Return (ival-adjust) with original sign in case we've generated a zero.
502 result
.value
.Subtract(adjust
, Rounding
{common::RoundingMode::ToZero
})
509 template <typename W
, int P
>
510 RealFlags Real
<W
, P
>::Normalize(bool negative
, int exponent
,
511 const Fraction
&fraction
, Rounding rounding
, RoundingBits
*roundingBits
) {
512 int lshift
{fraction
.LEADZ()};
513 if (lshift
== fraction
.bits
/* fraction is zero */ &&
514 (!roundingBits
|| roundingBits
->empty())) {
515 // No fraction, no rounding bits -> +/-0.0
516 exponent
= lshift
= 0;
517 } else if (lshift
< exponent
) {
519 } else if (exponent
> 0) {
520 lshift
= exponent
- 1;
522 } else if (lshift
== 0) {
527 if (exponent
>= maxExponent
) {
528 // Infinity or overflow
529 if (rounding
.mode
== common::RoundingMode::TiesToEven
||
530 rounding
.mode
== common::RoundingMode::TiesAwayFromZero
||
531 (rounding
.mode
== common::RoundingMode::Up
&& !negative
) ||
532 (rounding
.mode
== common::RoundingMode::Down
&& negative
)) {
533 word_
= Word
{maxExponent
}.SHIFTL(significandBits
); // Inf
534 if constexpr (!isImplicitMSB
) {
535 word_
= word_
.IBSET(significandBits
- 1);
538 // directed rounding: round to largest finite value rather than infinity
539 // (x86 does this, not sure whether it's standard behavior)
540 word_
= Word
{word_
.MASKR(word_
.bits
- 1)};
541 if constexpr (isImplicitMSB
) {
542 word_
= word_
.IBCLR(significandBits
);
546 word_
= word_
.IBSET(bits
- 1);
548 RealFlags flags
{RealFlag::Overflow
};
549 if (!fraction
.IsZero()) {
550 flags
.set(RealFlag::Inexact
);
554 word_
= Word::ConvertUnsigned(fraction
).value
;
556 word_
= word_
.SHIFTL(lshift
);
558 for (; lshift
> 0; --lshift
) {
559 if (roundingBits
->ShiftLeft()) {
560 word_
= word_
.IBSET(lshift
- 1);
565 if constexpr (isImplicitMSB
) {
566 word_
= word_
.IBCLR(significandBits
);
568 word_
= word_
.IOR(Word
{exponent
}.SHIFTL(significandBits
));
570 word_
= word_
.IBSET(bits
- 1);
575 template <typename W
, int P
>
576 RealFlags Real
<W
, P
>::Round(
577 Rounding rounding
, const RoundingBits
&bits
, bool multiply
) {
578 int origExponent
{Exponent()};
580 bool inexact
{!bits
.empty()};
582 flags
.set(RealFlag::Inexact
);
584 if (origExponent
< maxExponent
&&
585 bits
.MustRound(rounding
, IsNegative(), word_
.BTEST(0) /* is odd */)) {
586 typename
Fraction::ValueWithCarry sum
{
587 GetFraction().AddUnsigned(Fraction
{}, true)};
588 int newExponent
{origExponent
};
590 // The fraction was all ones before rounding; sum.value is now zero
591 sum
.value
= sum
.value
.IBSET(binaryPrecision
- 1);
592 if (++newExponent
>= maxExponent
) {
593 flags
.set(RealFlag::Overflow
); // rounded away to an infinity
596 flags
|= Normalize(IsNegative(), newExponent
, sum
.value
);
598 if (inexact
&& origExponent
== 0) {
599 // inexact subnormal input: signal Underflow unless in an x86-specific
601 if (rounding
.x86CompatibleBehavior
&& Exponent() != 0 && multiply
&&
604 (rounding
.mode
!= common::RoundingMode::Up
&&
605 rounding
.mode
!= common::RoundingMode::Down
))) {
606 // x86 edge case in which Underflow fails to signal when a subnormal
607 // inexact multiplication product rounds to a normal result when
608 // the guard bit is set or we're not using directed rounding
610 flags
.set(RealFlag::Underflow
);
616 template <typename W
, int P
>
617 void Real
<W
, P
>::NormalizeAndRound(ValueWithRealFlags
<Real
> &result
,
618 bool isNegative
, int exponent
, const Fraction
&fraction
, Rounding rounding
,
619 RoundingBits roundingBits
, bool multiply
) {
620 result
.flags
|= result
.value
.Normalize(
621 isNegative
, exponent
, fraction
, rounding
, &roundingBits
);
622 result
.flags
|= result
.value
.Round(rounding
, roundingBits
, multiply
);
625 inline enum decimal::FortranRounding
MapRoundingMode(
626 common::RoundingMode rounding
) {
628 case common::RoundingMode::TiesToEven
:
630 case common::RoundingMode::ToZero
:
631 return decimal::RoundToZero
;
632 case common::RoundingMode::Down
:
633 return decimal::RoundDown
;
634 case common::RoundingMode::Up
:
635 return decimal::RoundUp
;
636 case common::RoundingMode::TiesAwayFromZero
:
637 return decimal::RoundCompatible
;
639 return decimal::RoundNearest
; // dodge gcc warning about lack of result
642 inline RealFlags
MapFlags(decimal::ConversionResultFlags flags
) {
644 if (flags
& decimal::Overflow
) {
645 result
.set(RealFlag::Overflow
);
647 if (flags
& decimal::Inexact
) {
648 result
.set(RealFlag::Inexact
);
650 if (flags
& decimal::Invalid
) {
651 result
.set(RealFlag::InvalidArgument
);
656 template <typename W
, int P
>
657 ValueWithRealFlags
<Real
<W
, P
>> Real
<W
, P
>::Read(
658 const char *&p
, Rounding rounding
) {
660 decimal::ConvertToBinary
<P
>(p
, MapRoundingMode(rounding
.mode
))};
661 const auto *value
{reinterpret_cast<Real
<W
, P
> *>(&converted
.binary
)};
662 return {*value
, MapFlags(converted
.flags
)};
665 template <typename W
, int P
> std::string Real
<W
, P
>::DumpHexadecimal() const {
666 if (IsNotANumber()) {
667 return "NaN0x"s
+ word_
.Hexadecimal();
668 } else if (IsNegative()) {
669 return "-"s
+ Negate().DumpHexadecimal();
670 } else if (IsInfinite()) {
672 } else if (IsZero()) {
675 Fraction frac
{GetFraction()};
676 std::string result
{"0x"};
677 char intPart
= '0' + frac
.BTEST(frac
.bits
- 1);
680 int trailz
{frac
.TRAILZ()};
681 if (trailz
>= frac
.bits
- 1) {
684 int remainingBits
{frac
.bits
- 1 - trailz
};
685 int wholeNybbles
{remainingBits
/ 4};
686 int lostBits
{remainingBits
- 4 * wholeNybbles
};
687 if (wholeNybbles
> 0) {
688 std::string fracHex
{frac
.SHIFTR(trailz
+ lostBits
)
689 .IAND(frac
.MASKR(4 * wholeNybbles
))
691 std::size_t field
= wholeNybbles
;
692 if (fracHex
.size() < field
) {
693 result
+= std::string(field
- fracHex
.size(), '0');
698 result
+= frac
.SHIFTR(trailz
)
699 .IAND(frac
.MASKR(lostBits
))
700 .SHIFTL(4 - lostBits
)
705 int exponent
= Exponent() - exponentBias
;
706 if (intPart
== '0') {
709 result
+= Integer
<32>{exponent
}.SignedDecimal();
714 template <typename W
, int P
>
715 llvm::raw_ostream
&Real
<W
, P
>::AsFortran(
716 llvm::raw_ostream
&o
, int kind
, bool minimal
) const {
717 if (IsNotANumber()) {
718 o
<< "(0._" << kind
<< "/0.)";
719 } else if (IsInfinite()) {
721 o
<< "(-1._" << kind
<< "/0.)";
723 o
<< "(1._" << kind
<< "/0.)";
726 using B
= decimal::BinaryFloatingPointNumber
<P
>;
727 B value
{word_
.template ToUInt
<typename
B::RawType
>()};
728 char buffer
[common::MaxDecimalConversionDigits(P
) +
729 EXTRA_DECIMAL_CONVERSION_SPACE
];
730 decimal::DecimalConversionFlags flags
{}; // default: exact representation
732 flags
= decimal::Minimize
;
734 auto result
{decimal::ConvertToDecimal
<P
>(buffer
, sizeof buffer
, flags
,
735 static_cast<int>(sizeof buffer
), decimal::RoundNearest
, value
)};
736 const char *p
{result
.str
};
737 if (DEREF(p
) == '-' || *p
== '+') {
740 int expo
{result
.decimalExponent
};
744 o
<< *p
<< '.' << (p
+ 1);
754 template <typename W
, int P
> Real
<W
, P
> Real
<W
, P
>::RRSPACING() const {
755 if (IsNotANumber()) {
757 } else if (IsInfinite()) {
761 result
.Normalize(false, binaryPrecision
+ exponentBias
- 1, GetFraction());
767 template <typename W
, int P
> Real
<W
, P
> Real
<W
, P
>::SPACING() const {
768 if (IsNotANumber()) {
770 } else if (IsInfinite()) {
772 } else if (IsZero() || IsSubnormal()) {
773 return TINY(); // standard & 100% portable
776 result
.Normalize(false, Exponent(), Fraction::MASKR(1));
777 // Can the result be less than TINY()? No, with five commonly
778 // used compilers; yes, with two less commonly used ones.
779 return result
.IsZero() || result
.IsSubnormal() ? TINY() : result
;
784 template <typename W
, int P
>
785 Real
<W
, P
> Real
<W
, P
>::SET_EXPONENT(std::int64_t expo
) const {
786 if (IsNotANumber()) {
788 } else if (IsInfinite()) {
790 } else if (IsZero()) {
793 return SCALE(Integer
<64>(expo
- UnbiasedExponent() - 1)).value
;
798 template <typename W
, int P
> Real
<W
, P
> Real
<W
, P
>::FRACTION() const {
799 return SET_EXPONENT(0);
802 template class Real
<Integer
<16>, 11>;
803 template class Real
<Integer
<16>, 8>;
804 template class Real
<Integer
<32>, 24>;
805 template class Real
<Integer
<64>, 53>;
806 template class Real
<X87IntegerContainer
, 64>;
807 template class Real
<Integer
<128>, 113>;
808 } // namespace Fortran::evaluate::value