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 values
8static 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(N: 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(N: 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(s: q + result.length,
55 maxlen: buffer + sizeof buffer - (q + result.length), format: "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(N: 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(N: 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(x: u.x, flags: 0);
77 if constexpr (doNegative) {
78 testReadback(x: -u.x, flags: 0);
79 }
80 if constexpr (doMinimize) {
81 testReadback(x: u.x, flags: Minimize);
82 if constexpr (doNegative) {
83 testReadback(x: -u.x, flags: Minimize);
84 }
85 }
86 }
87 llvm::outs() << '\n' << tests << " tests run, " << fails << " tests failed\n";
88 return fails > 0;
89}
90

source code of flang/unittests/Decimal/thorough-test.cpp