| 437 | } |
| 438 | |
| 439 | fl::string ieee754_format_decimal(u32 bits, int precision) FL_NOEXCEPT { |
| 440 | if (precision < 0) precision = 0; |
| 441 | if (precision > 9) precision = 9; |
| 442 | |
| 443 | const bool neg = (bits >> 31) & 1u; |
| 444 | const int biased_exp = static_cast<int>((bits >> 23) & 0xFFu); |
| 445 | const u32 mant_bits = bits & 0x7FFFFFu; |
| 446 | |
| 447 | // Inf / NaN. |
| 448 | if (biased_exp == 0xFF) { |
| 449 | if (mant_bits != 0) return fl::string("nan"); |
| 450 | return neg ? fl::string("-inf") : fl::string("inf"); |
| 451 | } |
| 452 | |
| 453 | fl::string s; |
| 454 | |
| 455 | auto append_zero_with_precision = [&]() { |
| 456 | s += "0"; |
| 457 | if (precision > 0) { |
| 458 | s += "."; |
| 459 | for (int i = 0; i < precision; ++i) s += "0"; |
| 460 | } |
| 461 | }; |
| 462 | |
| 463 | // +/- 0 (and any subnormal -- those collapse to zero per the parser's |
| 464 | // contract, so the serializer matches). |
| 465 | if (biased_exp == 0) { |
| 466 | if (neg) s += "-"; |
| 467 | append_zero_with_precision(); |
| 468 | return s; |
| 469 | } |
| 470 | |
| 471 | // Normal number: value = mantissa_full * 2**bin_exp. |
| 472 | // mantissa_full carries the implicit leading 1. |
| 473 | const u32 mantissa_full = mant_bits | 0x800000u; // 24 bits |
| 474 | const int bin_exp_raw = biased_exp - 127 - 23; // signed |
| 475 | |
| 476 | // Lift to a 64-bit normalized representation so we can multiply against |
| 477 | // the shared pow10 table. mantissa_full's bit 23 is set, so shifting left by 40 |
| 478 | // puts that set bit in position 63. |
| 479 | const u64 mant64 = static_cast<u64>(mantissa_full) << 40; |
| 480 | const int bin_exp = bin_exp_raw - 40; |
| 481 | |
| 482 | // Look up the normalized representation of 10**precision. |
| 483 | const fl::size idx = static_cast<fl::size>(precision - kPow10KMin); |
| 484 | const u64 pow_mant = kPow10Mant[idx]; |
| 485 | const int pow_exp = kPow10BExp[idx]; |
| 486 | |
| 487 | // Multiply via the same widening helper the parser uses. |
| 488 | u64 scaled_hi = mul_hi_u64(mant64, pow_mant); |
| 489 | int scaled_bin_exp = bin_exp + pow_exp + 64; |
| 490 | if ((scaled_hi & 0x8000000000000000ull) == 0) { |
| 491 | scaled_hi <<= 1; |
| 492 | --scaled_bin_exp; |
| 493 | } |
| 494 | |
| 495 | // Convert (scaled_hi, scaled_bin_exp) to a u64 integer count of |
| 496 | // `precision` decimal places. Overflow on the way up clamps to +/- inf; |
no test coverage detected