1 #include "flang/Decimal/decimal.h"
2 #include "llvm/Support/raw_ostream.h"
3 #include <cinttypes>
4 #include <cstdio>
5 #include <cstring>
6
7 using namespace Fortran::decimal;
8
9 static int tests{0};
10 static int fails{0};
11
12 union u {
13 float x;
14 std::uint32_t u;
15 };
16
failed(float x)17 llvm::raw_ostream &failed(float x) {
18 ++fails;
19 union u u;
20 u.x = x;
21 llvm::outs() << "FAIL: 0x";
22 return llvm::outs().write_hex(u.u);
23 }
24
testDirect(float x,const char * expect,int expectExpo,int flags=0)25 void testDirect(float x, const char *expect, int expectExpo, int flags = 0) {
26 char buffer[1024];
27 ++tests;
28 auto result{ConvertFloatToDecimal(buffer, sizeof buffer,
29 static_cast<enum DecimalConversionFlags>(flags), 1024, RoundNearest, x)};
30 if (result.str == nullptr) {
31 failed(x) << ' ' << flags << ": no result str\n";
32 } else if (std::strcmp(result.str, expect) != 0 ||
33 result.decimalExponent != expectExpo) {
34 failed(x) << ' ' << flags << ": expect '." << expect << 'e' << expectExpo
35 << "', got '." << result.str << 'e' << result.decimalExponent
36 << "'\n";
37 }
38 }
39
testReadback(float x,int flags)40 void testReadback(float x, int flags) {
41 char buffer[1024];
42 ++tests;
43 auto result{ConvertFloatToDecimal(buffer, sizeof buffer,
44 static_cast<enum DecimalConversionFlags>(flags), 1024, RoundNearest, x)};
45 if (result.str == nullptr) {
46 failed(x) << ' ' << flags << ": no result str\n";
47 } else {
48 float y{0};
49 char *q{const_cast<char *>(result.str)};
50 int expo{result.decimalExponent};
51 expo -= result.length;
52 if (*q == '-' || *q == '+') {
53 ++expo;
54 }
55 if (q >= buffer && q < buffer + sizeof buffer) {
56 std::sprintf(q + result.length, "e%d", expo);
57 }
58 const char *p{q};
59 auto rflags{ConvertDecimalToFloat(&p, &y, RoundNearest)};
60 union u u;
61 if (!(x == x)) {
62 if (y == y || *p != '\0' || (rflags & Invalid)) {
63 u.x = y;
64 (failed(x) << " (NaN) " << flags << ": -> '" << result.str << "' -> 0x")
65 .write_hex(u.u)
66 << " '" << p << "' " << rflags << '\n';
67 }
68 } else if (x != y || *p != '\0' || (rflags & Invalid)) {
69 u.x = x;
70 (failed(x) << ' ' << flags << ": -> '" << result.str << "' -> 0x")
71 .write_hex(u.u)
72 << " '" << p << "' " << rflags << '\n';
73 }
74 }
75 }
76
main()77 int main() {
78 union u u;
79 testDirect(-1.0, "-1", 1);
80 testDirect(0.0, "0", 0);
81 testDirect(0.0, "+0", 0, AlwaysSign);
82 testDirect(1.0, "1", 1);
83 testDirect(2.0, "2", 1);
84 testDirect(-1.0, "-1", 1);
85 testDirect(314159, "314159", 6);
86 testDirect(0.0625, "625", -1);
87 u.u = 0x80000000;
88 testDirect(u.x, "-0", 0);
89 u.u = 0x7f800000;
90 testDirect(u.x, "Inf", 0);
91 testDirect(u.x, "+Inf", 0, AlwaysSign);
92 u.u = 0xff800000;
93 testDirect(u.x, "-Inf", 0);
94 u.u = 0xffffffff;
95 testDirect(u.x, "NaN", 0);
96 testDirect(u.x, "NaN", 0, AlwaysSign);
97 u.u = 1;
98 testDirect(u.x,
99 "140129846432481707092372958328991613128026194187651577175706828388979108"
100 "268586060148663818836212158203125",
101 -44, 0);
102 testDirect(u.x, "1", -44, Minimize);
103 u.u = 0x7f777777;
104 testDirect(u.x, "3289396118917826996438159226753253376", 39, 0);
105 testDirect(u.x, "32893961", 39, Minimize);
106 for (u.u = 0; u.u < 16; ++u.u) {
107 testReadback(u.x, 0);
108 testReadback(-u.x, 0);
109 testReadback(u.x, Minimize);
110 testReadback(-u.x, Minimize);
111 }
112 for (u.u = 1; u.u < 0x7f800000; u.u *= 2) {
113 testReadback(u.x, 0);
114 testReadback(-u.x, 0);
115 testReadback(u.x, Minimize);
116 testReadback(-u.x, Minimize);
117 }
118 for (u.u = 0x7f7ffff0; u.u < 0x7f800010; ++u.u) {
119 testReadback(u.x, 0);
120 testReadback(-u.x, 0);
121 testReadback(u.x, Minimize);
122 testReadback(-u.x, Minimize);
123 }
124 for (u.u = 0; u.u < 0x7f800000; u.u += 65536) {
125 testReadback(u.x, 0);
126 testReadback(-u.x, 0);
127 testReadback(u.x, Minimize);
128 testReadback(-u.x, Minimize);
129 }
130 for (u.u = 0; u.u < 0x7f800000; u.u += 99999) {
131 testReadback(u.x, 0);
132 testReadback(-u.x, 0);
133 testReadback(u.x, Minimize);
134 testReadback(-u.x, Minimize);
135 }
136 for (u.u = 0; u.u < 0x7f800000; u.u += 32767) {
137 testReadback(u.x, 0);
138 testReadback(-u.x, 0);
139 testReadback(u.x, Minimize);
140 testReadback(-u.x, Minimize);
141 }
142 llvm::outs() << tests << " tests run, " << fails << " tests failed\n";
143 return fails > 0;
144 }
145