1 //===-- lib/Decimal/decimal-to-binary.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 "big-radix-floating-point.h" 10 #include "flang/Common/bit-population-count.h" 11 #include "flang/Common/leading-zero-bit-count.h" 12 #include "flang/Decimal/binary-floating-point.h" 13 #include "flang/Decimal/decimal.h" 14 #include <cinttypes> 15 #include <cstring> 16 #include <ctype.h> 17 18 namespace Fortran::decimal { 19 20 template <int PREC, int LOG10RADIX> 21 bool BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ParseNumber( 22 const char *&p, bool &inexact, const char *end) { 23 SetToZero(); 24 if (end && p >= end) { 25 return false; 26 } 27 // Skip leading spaces 28 for (; p != end && *p == ' '; ++p) { 29 } 30 if (p == end) { 31 return false; 32 } 33 const char *q{p}; 34 isNegative_ = *q == '-'; 35 if (*q == '-' || *q == '+') { 36 ++q; 37 } 38 const char *start{q}; 39 for (; q != end && *q == '0'; ++q) { 40 } 41 const char *firstDigit{q}; 42 for (; q != end && *q >= '0' && *q <= '9'; ++q) { 43 } 44 const char *point{nullptr}; 45 if (q != end && *q == '.') { 46 point = q; 47 for (++q; q != end && *q >= '0' && *q <= '9'; ++q) { 48 } 49 } 50 if (q == start || (q == start + 1 && start == point)) { 51 return false; // require at least one digit 52 } 53 // There's a valid number here; set the reference argument to point to 54 // the first character afterward, which might be an exponent part. 55 p = q; 56 // Strip off trailing zeroes 57 if (point) { 58 while (q[-1] == '0') { 59 --q; 60 } 61 if (q[-1] == '.') { 62 point = nullptr; 63 --q; 64 } 65 } 66 if (!point) { 67 while (q > firstDigit && q[-1] == '0') { 68 --q; 69 ++exponent_; 70 } 71 } 72 // Trim any excess digits 73 const char *limit{firstDigit + maxDigits * log10Radix + (point != nullptr)}; 74 if (q > limit) { 75 inexact = true; 76 if (point >= limit) { 77 q = point; 78 point = nullptr; 79 } 80 if (!point) { 81 exponent_ += q - limit; 82 } 83 q = limit; 84 } 85 if (point) { 86 exponent_ -= static_cast<int>(q - point - 1); 87 } 88 if (q == firstDigit) { 89 exponent_ = 0; // all zeros 90 } 91 // Rack the decimal digits up into big Digits. 92 for (auto times{radix}; q-- > firstDigit;) { 93 if (*q != '.') { 94 if (times == radix) { 95 digit_[digits_++] = *q - '0'; 96 times = 10; 97 } else { 98 digit_[digits_ - 1] += times * (*q - '0'); 99 times *= 10; 100 } 101 } 102 } 103 // Look for an optional exponent field. 104 if (p == end) { 105 return true; 106 } 107 q = p; 108 switch (*q) { 109 case 'e': 110 case 'E': 111 case 'd': 112 case 'D': 113 case 'q': 114 case 'Q': { 115 if (++q == end) { 116 break; 117 } 118 bool negExpo{*q == '-'}; 119 if (*q == '-' || *q == '+') { 120 ++q; 121 } 122 if (q != end && *q >= '0' && *q <= '9') { 123 int expo{0}; 124 for (; q != end && *q == '0'; ++q) { 125 } 126 const char *expDig{q}; 127 for (; q != end && *q >= '0' && *q <= '9'; ++q) { 128 expo = 10 * expo + *q - '0'; 129 } 130 if (q >= expDig + 8) { 131 // There's a ridiculous number of nonzero exponent digits. 132 // The decimal->binary conversion routine will cope with 133 // returning 0 or Inf, but we must ensure that "expo" didn't 134 // overflow back around to something legal. 135 expo = 10 * Real::decimalRange; 136 exponent_ = 0; 137 } 138 p = q; // exponent is valid; advance the termination pointer 139 if (negExpo) { 140 exponent_ -= expo; 141 } else { 142 exponent_ += expo; 143 } 144 } 145 } break; 146 default: 147 break; 148 } 149 return true; 150 } 151 152 template <int PREC, int LOG10RADIX> 153 void BigRadixFloatingPointNumber<PREC, 154 LOG10RADIX>::LoseLeastSignificantDigit() { 155 Digit LSD{digit_[0]}; 156 for (int j{0}; j < digits_ - 1; ++j) { 157 digit_[j] = digit_[j + 1]; 158 } 159 digit_[digits_ - 1] = 0; 160 bool incr{false}; 161 switch (rounding_) { 162 case RoundNearest: 163 incr = LSD > radix / 2 || (LSD == radix / 2 && digit_[0] % 2 != 0); 164 break; 165 case RoundUp: 166 incr = LSD > 0 && !isNegative_; 167 break; 168 case RoundDown: 169 incr = LSD > 0 && isNegative_; 170 break; 171 case RoundToZero: 172 break; 173 case RoundCompatible: 174 incr = LSD >= radix / 2; 175 break; 176 } 177 for (int j{0}; (digit_[j] += incr) == radix; ++j) { 178 digit_[j] = 0; 179 } 180 } 181 182 // This local utility class represents an unrounded nonnegative 183 // binary floating-point value with an unbiased (i.e., signed) 184 // binary exponent, an integer value (not a fraction) with an implied 185 // binary point to its *right*, and some guard bits for rounding. 186 template <int PREC> class IntermediateFloat { 187 public: 188 static constexpr int precision{PREC}; 189 using IntType = common::HostUnsignedIntType<precision>; 190 static constexpr IntType topBit{IntType{1} << (precision - 1)}; 191 static constexpr IntType mask{topBit + (topBit - 1)}; 192 193 IntermediateFloat() {} 194 IntermediateFloat(const IntermediateFloat &) = default; 195 196 // Assumes that exponent_ is valid on entry, and may increment it. 197 // Returns the number of guard_ bits that have been determined. 198 template <typename UINT> bool SetTo(UINT n) { 199 static constexpr int nBits{CHAR_BIT * sizeof n}; 200 if constexpr (precision >= nBits) { 201 value_ = n; 202 guard_ = 0; 203 return 0; 204 } else { 205 int shift{common::BitsNeededFor(n) - precision}; 206 if (shift <= 0) { 207 value_ = n; 208 guard_ = 0; 209 return 0; 210 } else { 211 value_ = n >> shift; 212 exponent_ += shift; 213 n <<= nBits - shift; 214 guard_ = (n >> (nBits - guardBits)) | ((n << guardBits) != 0); 215 return shift; 216 } 217 } 218 } 219 220 void ShiftIn(int bit = 0) { value_ = value_ + value_ + bit; } 221 bool IsFull() const { return value_ >= topBit; } 222 void AdjustExponent(int by) { exponent_ += by; } 223 void SetGuard(int g) { 224 guard_ |= (static_cast<GuardType>(g & 6) << (guardBits - 3)) | (g & 1); 225 } 226 227 ConversionToBinaryResult<PREC> ToBinary( 228 bool isNegative, FortranRounding) const; 229 230 private: 231 static constexpr int guardBits{3}; // guard, round, sticky 232 using GuardType = int; 233 static constexpr GuardType oneHalf{GuardType{1} << (guardBits - 1)}; 234 235 IntType value_{0}; 236 GuardType guard_{0}; 237 int exponent_{0}; 238 }; 239 240 // The standard says that these overflow cases round to "representable" 241 // numbers, and some popular compilers interpret that to mean +/-HUGE() 242 // rather than +/-Inf. 243 static inline constexpr bool RoundOverflowToHuge( 244 enum FortranRounding rounding, bool isNegative) { 245 return rounding == RoundToZero || (!isNegative && rounding == RoundDown) || 246 (isNegative && rounding == RoundUp); 247 } 248 249 template <int PREC> 250 ConversionToBinaryResult<PREC> IntermediateFloat<PREC>::ToBinary( 251 bool isNegative, FortranRounding rounding) const { 252 using Binary = BinaryFloatingPointNumber<PREC>; 253 // Create a fraction with a binary point to the left of the integer 254 // value_, and bias the exponent. 255 IntType fraction{value_}; 256 GuardType guard{guard_}; 257 int expo{exponent_ + Binary::exponentBias + (precision - 1)}; 258 while (expo < 1 && (fraction > 0 || guard > oneHalf)) { 259 guard = (guard & 1) | (guard >> 1) | 260 ((static_cast<GuardType>(fraction) & 1) << (guardBits - 1)); 261 fraction >>= 1; 262 ++expo; 263 } 264 int flags{Exact}; 265 if (guard != 0) { 266 flags |= Inexact; 267 } 268 if (fraction == 0) { 269 if (guard <= oneHalf) { 270 if ((!isNegative && rounding == RoundUp) || 271 (isNegative && rounding == RoundDown)) { 272 // round to least nonzero value 273 } else { // round to zero 274 if (guard != 0) { 275 flags |= Underflow; 276 } 277 return {Binary{}, static_cast<enum ConversionResultFlags>(flags)}; 278 } 279 } 280 } else { 281 // The value is nonzero; normalize it. 282 while (fraction < topBit && expo > 1) { 283 --expo; 284 fraction = fraction * 2 + (guard >> (guardBits - 2)); 285 guard = 286 (((guard >> (guardBits - 2)) & 1) << (guardBits - 1)) | (guard & 1); 287 } 288 } 289 // Apply rounding 290 bool incr{false}; 291 switch (rounding) { 292 case RoundNearest: 293 incr = guard > oneHalf || (guard == oneHalf && (fraction & 1)); 294 break; 295 case RoundUp: 296 incr = guard != 0 && !isNegative; 297 break; 298 case RoundDown: 299 incr = guard != 0 && isNegative; 300 break; 301 case RoundToZero: 302 break; 303 case RoundCompatible: 304 incr = guard >= oneHalf; 305 break; 306 } 307 if (incr) { 308 if (fraction == mask) { 309 // rounding causes a carry 310 ++expo; 311 fraction = topBit; 312 } else { 313 ++fraction; 314 } 315 } 316 if (expo == 1 && fraction < topBit) { 317 expo = 0; // subnormal 318 flags |= Underflow; 319 } else if (expo == 0) { 320 flags |= Underflow; 321 } else if (expo >= Binary::maxExponent) { 322 if (RoundOverflowToHuge(rounding, isNegative)) { 323 expo = Binary::maxExponent - 1; 324 fraction = mask; 325 } else { // Inf 326 expo = Binary::maxExponent; 327 flags |= Overflow; 328 if constexpr (Binary::bits == 80) { // x87 329 fraction = IntType{1} << 63; 330 } else { 331 fraction = 0; 332 } 333 } 334 } 335 using Raw = typename Binary::RawType; 336 Raw raw = static_cast<Raw>(isNegative) << (Binary::bits - 1); 337 raw |= static_cast<Raw>(expo) << Binary::significandBits; 338 if constexpr (Binary::isImplicitMSB) { 339 fraction &= ~topBit; 340 } 341 raw |= fraction; 342 return {Binary(raw), static_cast<enum ConversionResultFlags>(flags)}; 343 } 344 345 template <int PREC, int LOG10RADIX> 346 ConversionToBinaryResult<PREC> 347 BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ConvertToBinary() { 348 // On entry, *this holds a multi-precision integer value in a radix of a 349 // large power of ten. Its radix point is defined to be to the right of its 350 // digits, and "exponent_" is the power of ten by which it is to be scaled. 351 Normalize(); 352 if (digits_ == 0) { // zero value 353 return {Real{SignBit()}}; 354 } 355 // The value is not zero: x = D. * 10.**E 356 // Shift our perspective on the radix (& decimal) point so that 357 // it sits to the *left* of the digits: i.e., x = .D * 10.**E 358 exponent_ += digits_ * log10Radix; 359 // Sanity checks for ridiculous exponents 360 static constexpr int crazy{2 * Real::decimalRange + log10Radix}; 361 if (exponent_ < -crazy) { 362 enum ConversionResultFlags flags { 363 static_cast<enum ConversionResultFlags>(Inexact | Underflow) 364 }; 365 if ((!isNegative_ && rounding_ == RoundUp) || 366 (isNegative_ && rounding_ == RoundDown)) { 367 // return least nonzero value 368 return {Real{Raw{1} | SignBit()}, flags}; 369 } else { // underflow to +/-0. 370 return {Real{SignBit()}, flags}; 371 } 372 } else if (exponent_ > crazy) { // overflow to +/-HUGE() or +/-Inf 373 if (RoundOverflowToHuge(rounding_, isNegative_)) { 374 return {Real{HUGE()}}; 375 } else { 376 return {Real{Infinity()}, Overflow}; 377 } 378 } 379 // Apply any negative decimal exponent by multiplication 380 // by a power of two, adjusting the binary exponent to compensate. 381 IntermediateFloat<PREC> f; 382 while (exponent_ < log10Radix) { 383 // x = 0.D * 10.**E * 2.**(f.ex) -> 512 * 0.D * 10.**E * 2.**(f.ex-9) 384 f.AdjustExponent(-9); 385 digitLimit_ = digits_; 386 if (int carry{MultiplyWithoutNormalization<512>()}) { 387 // x = c.D * 10.**E * 2.**(f.ex) -> .cD * 10.**(E+16) * 2.**(f.ex) 388 PushCarry(carry); 389 exponent_ += log10Radix; 390 } 391 } 392 // Apply any positive decimal exponent greater than 393 // is needed to treat the topmost digit as an integer 394 // part by multiplying by 10 or 10000 repeatedly. 395 while (exponent_ > log10Radix) { 396 digitLimit_ = digits_; 397 int carry; 398 if (exponent_ >= log10Radix + 4) { 399 // x = 0.D * 10.**E * 2.**(f.ex) -> 625 * .D * 10.**(E-4) * 2.**(f.ex+4) 400 exponent_ -= 4; 401 carry = MultiplyWithoutNormalization<(5 * 5 * 5 * 5)>(); 402 f.AdjustExponent(4); 403 } else { 404 // x = 0.D * 10.**E * 2.**(f.ex) -> 5 * .D * 10.**(E-1) * 2.**(f.ex+1) 405 --exponent_; 406 carry = MultiplyWithoutNormalization<5>(); 407 f.AdjustExponent(1); 408 } 409 if (carry != 0) { 410 // x = c.D * 10.**E * 2.**(f.ex) -> .cD * 10.**(E+16) * 2.**(f.ex) 411 PushCarry(carry); 412 exponent_ += log10Radix; 413 } 414 } 415 // So exponent_ is now log10Radix, meaning that the 416 // MSD can be taken as an integer part and transferred 417 // to the binary result. 418 // x = .jD * 10.**16 * 2.**(f.ex) -> .D * j * 2.**(f.ex) 419 int guardShift{f.SetTo(digit_[--digits_])}; 420 // Transfer additional bits until the result is normal. 421 digitLimit_ = digits_; 422 while (!f.IsFull()) { 423 // x = ((b.D)/2) * j * 2.**(f.ex) -> .D * (2j + b) * 2.**(f.ex-1) 424 f.AdjustExponent(-1); 425 std::uint32_t carry = MultiplyWithoutNormalization<2>(); 426 f.ShiftIn(carry); 427 } 428 // Get the next few bits for rounding. Allow for some guard bits 429 // that may have already been set in f.SetTo() above. 430 int guard{0}; 431 if (guardShift == 0) { 432 guard = MultiplyWithoutNormalization<4>(); 433 } else if (guardShift == 1) { 434 guard = MultiplyWithoutNormalization<2>(); 435 } 436 guard = guard + guard + !IsZero(); 437 f.SetGuard(guard); 438 return f.ToBinary(isNegative_, rounding_); 439 } 440 441 template <int PREC, int LOG10RADIX> 442 ConversionToBinaryResult<PREC> 443 BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ConvertToBinary( 444 const char *&p, const char *limit) { 445 bool inexact{false}; 446 if (ParseNumber(p, inexact, limit)) { 447 auto result{ConvertToBinary()}; 448 if (inexact) { 449 result.flags = 450 static_cast<enum ConversionResultFlags>(result.flags | Inexact); 451 } 452 return result; 453 } else { 454 // Could not parse a decimal floating-point number. p has been 455 // advanced over any leading spaces. Most Fortran compilers set 456 // the sign bit for -NaN. 457 const char *q{p}; 458 if (!limit || q < limit) { 459 isNegative_ = *q == '-'; 460 if (isNegative_ || *q == '+') { 461 ++q; 462 } 463 } 464 if ((!limit || limit >= q + 3) && toupper(q[0]) == 'N' && 465 toupper(q[1]) == 'A' && toupper(q[2]) == 'N') { 466 // NaN 467 p = q + 3; 468 bool isQuiet{true}; 469 if ((!limit || p < limit) && *p == '(') { 470 int depth{1}; 471 do { 472 ++p; 473 if (limit && p >= limit) { 474 // Invalid input 475 return {Real{NaN(false)}, Invalid}; 476 } else if (*p == '(') { 477 ++depth; 478 } else if (*p == ')') { 479 --depth; 480 } else if (*p != ' ') { 481 // Implementation dependent, but other compilers 482 // all return quiet NaNs. 483 } 484 } while (depth > 0); 485 ++p; 486 } 487 return {Real{NaN(isQuiet)}}; 488 } else { // Inf? 489 if ((!limit || limit >= q + 3) && toupper(q[0]) == 'I' && 490 toupper(q[1]) == 'N' && toupper(q[2]) == 'F') { 491 if ((!limit || limit >= q + 8) && toupper(q[3]) == 'I' && 492 toupper(q[4]) == 'N' && toupper(q[5]) == 'I' && 493 toupper(q[6]) == 'T' && toupper(q[7]) == 'Y') { 494 p = q + 8; 495 } else { 496 p = q + 3; 497 } 498 return {Real{Infinity()}}; 499 } else { 500 // Invalid input 501 return {Real{NaN()}, Invalid}; 502 } 503 } 504 } 505 } 506 507 template <int PREC> 508 ConversionToBinaryResult<PREC> ConvertToBinary( 509 const char *&p, enum FortranRounding rounding, const char *end) { 510 return BigRadixFloatingPointNumber<PREC>{rounding}.ConvertToBinary(p, end); 511 } 512 513 template ConversionToBinaryResult<8> ConvertToBinary<8>( 514 const char *&, enum FortranRounding, const char *end); 515 template ConversionToBinaryResult<11> ConvertToBinary<11>( 516 const char *&, enum FortranRounding, const char *end); 517 template ConversionToBinaryResult<24> ConvertToBinary<24>( 518 const char *&, enum FortranRounding, const char *end); 519 template ConversionToBinaryResult<53> ConvertToBinary<53>( 520 const char *&, enum FortranRounding, const char *end); 521 template ConversionToBinaryResult<64> ConvertToBinary<64>( 522 const char *&, enum FortranRounding, const char *end); 523 template ConversionToBinaryResult<113> ConvertToBinary<113>( 524 const char *&, enum FortranRounding, const char *end); 525 526 extern "C" { 527 enum ConversionResultFlags ConvertDecimalToFloat( 528 const char **p, float *f, enum FortranRounding rounding) { 529 auto result{Fortran::decimal::ConvertToBinary<24>(*p, rounding)}; 530 std::memcpy(reinterpret_cast<void *>(f), 531 reinterpret_cast<const void *>(&result.binary), sizeof *f); 532 return result.flags; 533 } 534 enum ConversionResultFlags ConvertDecimalToDouble( 535 const char **p, double *d, enum FortranRounding rounding) { 536 auto result{Fortran::decimal::ConvertToBinary<53>(*p, rounding)}; 537 std::memcpy(reinterpret_cast<void *>(d), 538 reinterpret_cast<const void *>(&result.binary), sizeof *d); 539 return result.flags; 540 } 541 enum ConversionResultFlags ConvertDecimalToLongDouble( 542 const char **p, long double *ld, enum FortranRounding rounding) { 543 auto result{Fortran::decimal::ConvertToBinary<64>(*p, rounding)}; 544 std::memcpy(reinterpret_cast<void *>(ld), 545 reinterpret_cast<const void *>(&result.binary), sizeof *ld); 546 return result.flags; 547 } 548 } 549 } // namespace Fortran::decimal 550