90 lines · cpp
1#include "flang/Decimal/decimal.h"2#include "llvm/Support/raw_ostream.h"3#include <cinttypes>4#include <cstdio>5#include <cstring>6 7static constexpr int incr{1}; // steps through all values8static constexpr bool doNegative{true};9static constexpr bool doMinimize{true};10 11using namespace Fortran::decimal;12 13static std::uint64_t tests{0};14static std::uint64_t fails{0};15 16union u {17 float x;18 std::uint32_t u;19};20 21llvm::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 29void 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::snprintf(q + result.length,55 buffer + sizeof buffer - (q + result.length), "e%d", expo);56 }57 const char *p{q};58 auto rflags{ConvertDecimalToFloat(&p, &y, RoundNearest)};59 if (!(x == x)) {60 if (y == y || *p != '\0' || (rflags & Invalid)) {61 u.x = y;62 failed(x) << " (NaN) " << flags << ": -> '" << result.str << "' -> 0x";63 failed(x).write_hex(u.u) << " '" << p << "' " << rflags << '\n';64 }65 } else if (x != y || *p != '\0' || (rflags & Invalid)) {66 u.x = y;67 failed(x) << ' ' << flags << ": -> '" << result.str << "' -> 0x";68 failed(x).write_hex(u.u) << " '" << p << "' " << rflags << '\n';69 }70 }71}72 73int main() {74 union u u;75 for (u.u = 0; u.u < 0x7f800010; u.u += incr) {76 testReadback(u.x, 0);77 if constexpr (doNegative) {78 testReadback(-u.x, 0);79 }80 if constexpr (doMinimize) {81 testReadback(u.x, Minimize);82 if constexpr (doNegative) {83 testReadback(-u.x, Minimize);84 }85 }86 }87 llvm::outs() << '\n' << tests << " tests run, " << fails << " tests failed\n";88 return fails > 0;89}90