1 #include "flang/Decimal/decimal.h" 2 #include "llvm/Support/raw_ostream.h" 3 #include <cinttypes> 4 #include <cstdio> 5 #include <cstring> 6 7 static constexpr int incr{1}; // steps through all values 8 static constexpr bool doNegative{true}; 9 static constexpr bool doMinimize{true}; 10 11 using namespace Fortran::decimal; 12 13 static std::uint64_t tests{0}; 14 static std::uint64_t fails{0}; 15 16 union u { 17 float x; 18 std::uint32_t u; 19 }; 20 21 llvm::raw_ostream &failed(float x) { 22 ++fails; 23 union u u; 24 u.x = x; 25 llvm::outs() << "FAIL: 0x"; 26 return llvm::outs().write_hex(u.u); 27 } 28 29 void testReadback(float x, int flags) { 30 char buffer[1024]; 31 union u u; 32 u.x = x; 33 if (!(tests & 0x3fffff)) { 34 llvm::errs() << "\n0x"; 35 llvm::errs().write_hex(u.u) << ' '; 36 } else if (!(tests & 0xffff)) { 37 llvm::errs() << '.'; 38 } 39 ++tests; 40 auto result{ConvertFloatToDecimal(buffer, sizeof buffer, 41 static_cast<enum DecimalConversionFlags>(flags), 1024, RoundNearest, x)}; 42 if (result.str == nullptr) { 43 failed(x) << ' ' << flags << ": no result str\n"; 44 } else { 45 float y{0}; 46 char *q{const_cast<char *>(result.str)}; 47 if ((*q >= '0' && *q <= '9') || 48 ((*q == '-' || *q == '+') && q[1] >= '0' && q[1] <= '9')) { 49 int expo{result.decimalExponent}; 50 expo -= result.length; 51 if (*q == '-' || *q == '+') { 52 ++expo; 53 } 54 std::sprintf(q + result.length, "e%d", expo); 55 } 56 const char *p{q}; 57 auto rflags{ConvertDecimalToFloat(&p, &y, RoundNearest)}; 58 if (!(x == x)) { 59 if (y == y || *p != '\0' || (rflags & Invalid)) { 60 u.x = y; 61 failed(x) << " (NaN) " << flags << ": -> '" << result.str << "' -> 0x"; 62 failed(x).write_hex(u.u) << " '" << p << "' " << rflags << '\n'; 63 } 64 } else if (x != y || *p != '\0' || (rflags & Invalid)) { 65 u.x = y; 66 failed(x) << ' ' << flags << ": -> '" << result.str << "' -> 0x"; 67 failed(x).write_hex(u.u) << " '" << p << "' " << rflags << '\n'; 68 } 69 } 70 } 71 72 int main() { 73 union u u; 74 for (u.u = 0; u.u < 0x7f800010; u.u += incr) { 75 testReadback(u.x, 0); 76 if constexpr (doNegative) { 77 testReadback(-u.x, 0); 78 } 79 if constexpr (doMinimize) { 80 testReadback(u.x, Minimize); 81 if constexpr (doNegative) { 82 testReadback(-u.x, Minimize); 83 } 84 } 85 } 86 llvm::outs() << '\n' << tests << " tests run, " << fails << " tests failed\n"; 87 return fails > 0; 88 } 89