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
failed(float x)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
testReadback(float x,int flags)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
main()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