#include "flang/Decimal/decimal.h" #include "llvm/Support/raw_ostream.h" #include #include #include static constexpr int incr{1}; // steps through all values static constexpr bool doNegative{true}; static constexpr bool doMinimize{true}; using namespace Fortran::decimal; static std::uint64_t tests{0}; static std::uint64_t fails{0}; union u { float x; std::uint32_t u; }; llvm::raw_ostream &failed(float x) { ++fails; union u u; u.x = x; llvm::outs() << "FAIL: 0x"; return llvm::outs().write_hex(u.u); } void testReadback(float x, int flags) { char buffer[1024]; union u u; u.x = x; if (!(tests & 0x3fffff)) { llvm::errs() << "\n0x"; llvm::errs().write_hex(u.u) << ' '; } else if (!(tests & 0xffff)) { llvm::errs() << '.'; } ++tests; auto result{ConvertFloatToDecimal(buffer, sizeof buffer, static_cast(flags), 1024, RoundNearest, x)}; if (result.str == nullptr) { failed(x) << ' ' << flags << ": no result str\n"; } else { float y{0}; char *q{const_cast(result.str)}; if ((*q >= '0' && *q <= '9') || ((*q == '-' || *q == '+') && q[1] >= '0' && q[1] <= '9')) { int expo{result.decimalExponent}; expo -= result.length; if (*q == '-' || *q == '+') { ++expo; } std::sprintf(q + result.length, "e%d", expo); } const char *p{q}; auto rflags{ConvertDecimalToFloat(&p, &y, RoundNearest)}; if (!(x == x)) { if (y == y || *p != '\0' || (rflags & Invalid)) { u.x = y; failed(x) << " (NaN) " << flags << ": -> '" << result.str << "' -> 0x"; failed(x).write_hex(u.u) << " '" << p << "' " << rflags << '\n'; } } else if (x != y || *p != '\0' || (rflags & Invalid)) { u.x = y; failed(x) << ' ' << flags << ": -> '" << result.str << "' -> 0x"; failed(x).write_hex(u.u) << " '" << p << "' " << rflags << '\n'; } } } int main() { union u u; for (u.u = 0; u.u < 0x7f800010; u.u += incr) { testReadback(u.x, 0); if constexpr (doNegative) { testReadback(-u.x, 0); } if constexpr (doMinimize) { testReadback(u.x, Minimize); if constexpr (doNegative) { testReadback(-u.x, Minimize); } } } llvm::outs() << '\n' << tests << " tests run, " << fails << " tests failed\n"; return fails > 0; }