1 //===-- lib/Evaluate/real.cpp ---------------------------------------------===// 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 #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 <limits> 15 16 namespace Fortran::evaluate::value { 17 18 template<typename W, int P> Relation Real<W, P>::Compare(const Real &y) const { 19 if (IsNotANumber() || y.IsNotANumber()) { // NaN vs x, x vs NaN 20 return Relation::Unordered; 21 } else if (IsInfinite()) { 22 if (y.IsInfinite()) { 23 if (IsNegative()) { // -Inf vs +/-Inf 24 return y.IsNegative() ? Relation::Equal : Relation::Less; 25 } else { // +Inf vs +/-Inf 26 return y.IsNegative() ? Relation::Greater : Relation::Equal; 27 } 28 } else { // +/-Inf vs finite 29 return IsNegative() ? Relation::Less : Relation::Greater; 30 } 31 } else if (y.IsInfinite()) { // finite vs +/-Inf 32 return y.IsNegative() ? Relation::Greater : Relation::Less; 33 } else { // two finite numbers 34 bool isNegative{IsNegative()}; 35 if (isNegative != y.IsNegative()) { 36 if (word_.IOR(y.word_).IBCLR(bits - 1).IsZero()) { 37 return Relation::Equal; // +/-0.0 == -/+0.0 38 } else { 39 return isNegative ? Relation::Less : Relation::Greater; 40 } 41 } else { 42 // same sign 43 Ordering order{evaluate::Compare(Exponent(), y.Exponent())}; 44 if (order == Ordering::Equal) { 45 order = GetSignificand().CompareUnsigned(y.GetSignificand()); 46 } 47 if (isNegative) { 48 order = Reverse(order); 49 } 50 return RelationFromOrdering(order); 51 } 52 } 53 } 54 55 template<typename W, int P> 56 ValueWithRealFlags<Real<W, P>> Real<W, P>::Add( 57 const Real &y, Rounding rounding) const { 58 ValueWithRealFlags<Real> result; 59 if (IsNotANumber() || y.IsNotANumber()) { 60 result.value = NotANumber(); // NaN + x -> NaN 61 if (IsSignalingNaN() || y.IsSignalingNaN()) { 62 result.flags.set(RealFlag::InvalidArgument); 63 } 64 return result; 65 } 66 bool isNegative{IsNegative()}; 67 bool yIsNegative{y.IsNegative()}; 68 if (IsInfinite()) { 69 if (y.IsInfinite()) { 70 if (isNegative == yIsNegative) { 71 result.value = *this; // +/-Inf + +/-Inf -> +/-Inf 72 } else { 73 result.value = NotANumber(); // +/-Inf + -/+Inf -> NaN 74 result.flags.set(RealFlag::InvalidArgument); 75 } 76 } else { 77 result.value = *this; // +/-Inf + x -> +/-Inf 78 } 79 return result; 80 } 81 if (y.IsInfinite()) { 82 result.value = y; // x + +/-Inf -> +/-Inf 83 return result; 84 } 85 int exponent{Exponent()}; 86 int yExponent{y.Exponent()}; 87 if (exponent < yExponent) { 88 // y is larger in magnitude; simplify by reversing operands 89 return y.Add(*this, rounding); 90 } 91 if (exponent == yExponent && isNegative != yIsNegative) { 92 Ordering order{GetSignificand().CompareUnsigned(y.GetSignificand())}; 93 if (order == Ordering::Less) { 94 // Same exponent, opposite signs, and y is larger in magnitude 95 return y.Add(*this, rounding); 96 } 97 if (order == Ordering::Equal) { 98 // x + (-x) -> +0.0 unless rounding is directed downwards 99 if (rounding.mode == common::RoundingMode::Down) { 100 result.value.word_ = result.value.word_.IBSET(bits - 1); // -0.0 101 } 102 return result; 103 } 104 } 105 // Our exponent is greater than y's, or the exponents match and y is not 106 // of the opposite sign and greater magnitude. So (x+y) will have the 107 // same sign as x. 108 Fraction fraction{GetFraction()}; 109 Fraction yFraction{y.GetFraction()}; 110 int rshift = exponent - yExponent; 111 if (exponent > 0 && yExponent == 0) { 112 --rshift; // correct overshift when only y is subnormal 113 } 114 RoundingBits roundingBits{yFraction, rshift}; 115 yFraction = yFraction.SHIFTR(rshift); 116 bool carry{false}; 117 if (isNegative != yIsNegative) { 118 // Opposite signs: subtract via addition of two's complement of y and 119 // the rounding bits. 120 yFraction = yFraction.NOT(); 121 carry = roundingBits.Negate(); 122 } 123 auto sum{fraction.AddUnsigned(yFraction, carry)}; 124 fraction = sum.value; 125 if (isNegative == yIsNegative && sum.carry) { 126 roundingBits.ShiftRight(sum.value.BTEST(0)); 127 fraction = fraction.SHIFTR(1).IBSET(fraction.bits - 1); 128 ++exponent; 129 } 130 NormalizeAndRound( 131 result, isNegative, exponent, fraction, rounding, roundingBits); 132 return result; 133 } 134 135 template<typename W, int P> 136 ValueWithRealFlags<Real<W, P>> Real<W, P>::Multiply( 137 const Real &y, Rounding rounding) const { 138 ValueWithRealFlags<Real> result; 139 if (IsNotANumber() || y.IsNotANumber()) { 140 result.value = NotANumber(); // NaN * x -> NaN 141 if (IsSignalingNaN() || y.IsSignalingNaN()) { 142 result.flags.set(RealFlag::InvalidArgument); 143 } 144 } else { 145 bool isNegative{IsNegative() != y.IsNegative()}; 146 if (IsInfinite() || y.IsInfinite()) { 147 if (IsZero() || y.IsZero()) { 148 result.value = NotANumber(); // 0 * Inf -> NaN 149 result.flags.set(RealFlag::InvalidArgument); 150 } else { 151 result.value = Infinity(isNegative); 152 } 153 } else { 154 auto product{GetFraction().MultiplyUnsigned(y.GetFraction())}; 155 std::int64_t exponent{CombineExponents(y, false)}; 156 if (exponent < 1) { 157 int rshift = 1 - exponent; 158 exponent = 1; 159 bool sticky{false}; 160 if (rshift >= product.upper.bits + product.lower.bits) { 161 sticky = !product.lower.IsZero() || !product.upper.IsZero(); 162 } else if (rshift >= product.lower.bits) { 163 sticky = !product.lower.IsZero() || 164 !product.upper 165 .IAND(product.upper.MASKR(rshift - product.lower.bits)) 166 .IsZero(); 167 } else { 168 sticky = !product.lower.IAND(product.lower.MASKR(rshift)).IsZero(); 169 } 170 product.lower = product.lower.SHIFTRWithFill(product.upper, rshift); 171 product.upper = product.upper.SHIFTR(rshift); 172 if (sticky) { 173 product.lower = product.lower.IBSET(0); 174 } 175 } 176 int leadz{product.upper.LEADZ()}; 177 if (leadz >= product.upper.bits) { 178 leadz += product.lower.LEADZ(); 179 } 180 int lshift{leadz}; 181 if (lshift > exponent - 1) { 182 lshift = exponent - 1; 183 } 184 exponent -= lshift; 185 product.upper = product.upper.SHIFTLWithFill(product.lower, lshift); 186 product.lower = product.lower.SHIFTL(lshift); 187 RoundingBits roundingBits{product.lower, product.lower.bits}; 188 NormalizeAndRound(result, isNegative, exponent, product.upper, rounding, 189 roundingBits, true /*multiply*/); 190 } 191 } 192 return result; 193 } 194 195 template<typename W, int P> 196 ValueWithRealFlags<Real<W, P>> Real<W, P>::Divide( 197 const Real &y, Rounding rounding) const { 198 ValueWithRealFlags<Real> result; 199 if (IsNotANumber() || y.IsNotANumber()) { 200 result.value = NotANumber(); // NaN / x -> NaN, x / NaN -> NaN 201 if (IsSignalingNaN() || y.IsSignalingNaN()) { 202 result.flags.set(RealFlag::InvalidArgument); 203 } 204 } else { 205 bool isNegative{IsNegative() != y.IsNegative()}; 206 if (IsInfinite()) { 207 if (y.IsInfinite()) { 208 result.value = NotANumber(); // Inf/Inf -> NaN 209 result.flags.set(RealFlag::InvalidArgument); 210 } else { // Inf/x -> Inf, Inf/0 -> Inf 211 result.value = Infinity(isNegative); 212 } 213 } else if (y.IsZero()) { 214 if (IsZero()) { // 0/0 -> NaN 215 result.value = NotANumber(); 216 result.flags.set(RealFlag::InvalidArgument); 217 } else { // x/0 -> Inf, Inf/0 -> Inf 218 result.value = Infinity(isNegative); 219 result.flags.set(RealFlag::DivideByZero); 220 } 221 } else if (IsZero() || y.IsInfinite()) { // 0/x, x/Inf -> 0 222 if (isNegative) { 223 result.value.word_ = result.value.word_.IBSET(bits - 1); 224 } 225 } else { 226 // dividend and divisor are both finite and nonzero numbers 227 Fraction top{GetFraction()}, divisor{y.GetFraction()}; 228 std::int64_t exponent{CombineExponents(y, true)}; 229 Fraction quotient; 230 bool msb{false}; 231 if (!top.BTEST(top.bits - 1) || !divisor.BTEST(divisor.bits - 1)) { 232 // One or two subnormals 233 int topLshift{top.LEADZ()}; 234 top = top.SHIFTL(topLshift); 235 int divisorLshift{divisor.LEADZ()}; 236 divisor = divisor.SHIFTL(divisorLshift); 237 exponent += divisorLshift - topLshift; 238 } 239 for (int j{1}; j <= quotient.bits; ++j) { 240 if (NextQuotientBit(top, msb, divisor)) { 241 quotient = quotient.IBSET(quotient.bits - j); 242 } 243 } 244 bool guard{NextQuotientBit(top, msb, divisor)}; 245 bool round{NextQuotientBit(top, msb, divisor)}; 246 bool sticky{msb || !top.IsZero()}; 247 RoundingBits roundingBits{guard, round, sticky}; 248 if (exponent < 1) { 249 std::int64_t rshift{1 - exponent}; 250 for (; rshift > 0; --rshift) { 251 roundingBits.ShiftRight(quotient.BTEST(0)); 252 quotient = quotient.SHIFTR(1); 253 } 254 exponent = 1; 255 } 256 NormalizeAndRound( 257 result, isNegative, exponent, quotient, rounding, roundingBits); 258 } 259 } 260 return result; 261 } 262 263 template<typename W, int P> 264 ValueWithRealFlags<Real<W, P>> Real<W, P>::ToWholeNumber( 265 common::RoundingMode mode) const { 266 ValueWithRealFlags<Real> result{*this}; 267 if (IsNotANumber()) { 268 result.flags.set(RealFlag::InvalidArgument); 269 result.value = NotANumber(); 270 } else if (IsInfinite()) { 271 result.flags.set(RealFlag::Overflow); 272 } else { 273 constexpr int noClipExponent{exponentBias + binaryPrecision - 1}; 274 if (Exponent() < noClipExponent) { 275 Real adjust; // ABS(EPSILON(adjust)) == 0.5 276 adjust.Normalize(IsSignBitSet(), noClipExponent, Fraction::MASKL(1)); 277 // Compute ival=(*this + adjust), losing any fractional bits; keep flags 278 result = Add(adjust, Rounding{mode}); 279 result.flags.reset(RealFlag::Inexact); // result *is* exact 280 // Return (ival-adjust) with original sign in case we've generated a zero. 281 result.value = 282 result.value.Subtract(adjust, Rounding{common::RoundingMode::ToZero}) 283 .value.SIGN(*this); 284 } 285 } 286 return result; 287 } 288 289 template<typename W, int P> 290 RealFlags Real<W, P>::Normalize(bool negative, int exponent, 291 const Fraction &fraction, Rounding rounding, RoundingBits *roundingBits) { 292 int lshift{fraction.LEADZ()}; 293 if (lshift == fraction.bits /* fraction is zero */ && 294 (!roundingBits || roundingBits->empty())) { 295 // No fraction, no rounding bits -> +/-0.0 296 exponent = lshift = 0; 297 } else if (lshift < exponent) { 298 exponent -= lshift; 299 } else if (exponent > 0) { 300 lshift = exponent - 1; 301 exponent = 0; 302 } else if (lshift == 0) { 303 exponent = 1; 304 } else { 305 lshift = 0; 306 } 307 if (exponent >= maxExponent) { 308 // Infinity or overflow 309 if (rounding.mode == common::RoundingMode::TiesToEven || 310 rounding.mode == common::RoundingMode::TiesAwayFromZero || 311 (rounding.mode == common::RoundingMode::Up && !negative) || 312 (rounding.mode == common::RoundingMode::Down && negative)) { 313 word_ = Word{maxExponent}.SHIFTL(significandBits); // Inf 314 } else { 315 // directed rounding: round to largest finite value rather than infinity 316 // (x86 does this, not sure whether it's standard behavior) 317 word_ = Word{word_.MASKR(word_.bits - 1)}.IBCLR(significandBits); 318 } 319 if (negative) { 320 word_ = word_.IBSET(bits - 1); 321 } 322 RealFlags flags{RealFlag::Overflow}; 323 if (!fraction.IsZero()) { 324 flags.set(RealFlag::Inexact); 325 } 326 return flags; 327 } 328 word_ = Word::ConvertUnsigned(fraction).value; 329 if (lshift > 0) { 330 word_ = word_.SHIFTL(lshift); 331 if (roundingBits) { 332 for (; lshift > 0; --lshift) { 333 if (roundingBits->ShiftLeft()) { 334 word_ = word_.IBSET(lshift - 1); 335 } 336 } 337 } 338 } 339 if constexpr (isImplicitMSB) { 340 word_ = word_.IBCLR(significandBits); 341 } 342 word_ = word_.IOR(Word{exponent}.SHIFTL(significandBits)); 343 if (negative) { 344 word_ = word_.IBSET(bits - 1); 345 } 346 return {}; 347 } 348 349 template<typename W, int P> 350 RealFlags Real<W, P>::Round( 351 Rounding rounding, const RoundingBits &bits, bool multiply) { 352 int origExponent{Exponent()}; 353 RealFlags flags; 354 bool inexact{!bits.empty()}; 355 if (inexact) { 356 flags.set(RealFlag::Inexact); 357 } 358 if (origExponent < maxExponent && 359 bits.MustRound(rounding, IsNegative(), word_.BTEST(0) /* is odd */)) { 360 typename Fraction::ValueWithCarry sum{ 361 GetFraction().AddUnsigned(Fraction{}, true)}; 362 int newExponent{origExponent}; 363 if (sum.carry) { 364 // The fraction was all ones before rounding; sum.value is now zero 365 sum.value = sum.value.IBSET(binaryPrecision - 1); 366 if (++newExponent >= maxExponent) { 367 flags.set(RealFlag::Overflow); // rounded away to an infinity 368 } 369 } 370 flags |= Normalize(IsNegative(), newExponent, sum.value); 371 } 372 if (inexact && origExponent == 0) { 373 // inexact subnormal input: signal Underflow unless in an x86-specific 374 // edge case 375 if (rounding.x86CompatibleBehavior && Exponent() != 0 && multiply && 376 bits.sticky() && 377 (bits.guard() || 378 (rounding.mode != common::RoundingMode::Up && 379 rounding.mode != common::RoundingMode::Down))) { 380 // x86 edge case in which Underflow fails to signal when a subnormal 381 // inexact multiplication product rounds to a normal result when 382 // the guard bit is set or we're not using directed rounding 383 } else { 384 flags.set(RealFlag::Underflow); 385 } 386 } 387 return flags; 388 } 389 390 template<typename W, int P> 391 void Real<W, P>::NormalizeAndRound(ValueWithRealFlags<Real> &result, 392 bool isNegative, int exponent, const Fraction &fraction, Rounding rounding, 393 RoundingBits roundingBits, bool multiply) { 394 result.flags |= result.value.Normalize( 395 isNegative, exponent, fraction, rounding, &roundingBits); 396 result.flags |= result.value.Round(rounding, roundingBits, multiply); 397 } 398 399 inline enum decimal::FortranRounding MapRoundingMode( 400 common::RoundingMode rounding) { 401 switch (rounding) { 402 case common::RoundingMode::TiesToEven: break; 403 case common::RoundingMode::ToZero: return decimal::RoundToZero; 404 case common::RoundingMode::Down: return decimal::RoundDown; 405 case common::RoundingMode::Up: return decimal::RoundUp; 406 case common::RoundingMode::TiesAwayFromZero: return decimal::RoundCompatible; 407 } 408 return decimal::RoundNearest; // dodge gcc warning about lack of result 409 } 410 411 inline RealFlags MapFlags(decimal::ConversionResultFlags flags) { 412 RealFlags result; 413 if (flags & decimal::Overflow) { 414 result.set(RealFlag::Overflow); 415 } 416 if (flags & decimal::Inexact) { 417 result.set(RealFlag::Inexact); 418 } 419 if (flags & decimal::Invalid) { 420 result.set(RealFlag::InvalidArgument); 421 } 422 return result; 423 } 424 425 template<typename W, int P> 426 ValueWithRealFlags<Real<W, P>> Real<W, P>::Read( 427 const char *&p, Rounding rounding) { 428 auto converted{ 429 decimal::ConvertToBinary<P>(p, MapRoundingMode(rounding.mode))}; 430 const auto *value{reinterpret_cast<Real<W, P> *>(&converted.binary)}; 431 return {*value, MapFlags(converted.flags)}; 432 } 433 434 template<typename W, int P> std::string Real<W, P>::DumpHexadecimal() const { 435 if (IsNotANumber()) { 436 return "NaN 0x"s + word_.Hexadecimal(); 437 } else if (IsNegative()) { 438 return "-"s + Negate().DumpHexadecimal(); 439 } else if (IsInfinite()) { 440 return "Inf"s; 441 } else if (IsZero()) { 442 return "0.0"s; 443 } else { 444 Fraction frac{GetFraction()}; 445 std::string result{"0x"}; 446 char intPart = '0' + frac.BTEST(frac.bits - 1); 447 result += intPart; 448 result += '.'; 449 int trailz{frac.TRAILZ()}; 450 if (trailz >= frac.bits - 1) { 451 result += '0'; 452 } else { 453 int remainingBits{frac.bits - 1 - trailz}; 454 int wholeNybbles{remainingBits / 4}; 455 int lostBits{remainingBits - 4 * wholeNybbles}; 456 if (wholeNybbles > 0) { 457 std::string fracHex{frac.SHIFTR(trailz + lostBits) 458 .IAND(frac.MASKR(4 * wholeNybbles)) 459 .Hexadecimal()}; 460 std::size_t field = wholeNybbles; 461 if (fracHex.size() < field) { 462 result += std::string(field - fracHex.size(), '0'); 463 } 464 result += fracHex; 465 } 466 if (lostBits > 0) { 467 result += frac.SHIFTR(trailz) 468 .IAND(frac.MASKR(lostBits)) 469 .SHIFTL(4 - lostBits) 470 .Hexadecimal(); 471 } 472 } 473 result += 'p'; 474 int exponent = Exponent() - exponentBias; 475 result += Integer<32>{exponent}.SignedDecimal(); 476 return result; 477 } 478 } 479 480 template<typename W, int P> 481 std::ostream &Real<W, P>::AsFortran( 482 std::ostream &o, int kind, bool minimal) const { 483 if (IsNotANumber()) { 484 o << "(0._" << kind << "/0.)"; 485 } else if (IsInfinite()) { 486 if (IsNegative()) { 487 o << "(-1._" << kind << "/0.)"; 488 } else { 489 o << "(1._" << kind << "/0.)"; 490 } 491 } else { 492 using B = decimal::BinaryFloatingPointNumber<P>; 493 const auto *value{reinterpret_cast<const B *>(this)}; 494 char buffer[24000]; // accommodate real*16 495 decimal::DecimalConversionFlags flags{}; // default: exact representation 496 if (minimal) { 497 flags = decimal::Minimize; 498 } 499 auto result{decimal::ConvertToDecimal<P>(buffer, sizeof buffer, flags, 500 static_cast<int>(sizeof buffer), decimal::RoundNearest, *value)}; 501 const char *p{result.str}; 502 if (DEREF(p) == '-' || *p == '+') { 503 o << *p++; 504 } 505 int expo{result.decimalExponent}; 506 if (*p != '0') { 507 --expo; 508 } 509 o << *p << '.' << (p + 1); 510 if (expo != 0) { 511 o << 'e' << expo; 512 } 513 o << '_' << kind; 514 } 515 return o; 516 } 517 518 template class Real<Integer<16>, 11>; 519 template class Real<Integer<16>, 8>; 520 template class Real<Integer<32>, 24>; 521 template class Real<Integer<64>, 53>; 522 template class Real<Integer<80>, 64>; 523 template class Real<Integer<128>, 112>; 524 } 525