1#include "flang/Decimal/decimal.h"
2#include "llvm/Support/raw_ostream.h"
3#include <cinttypes>
4#include <cstdio>
5#include <cstring>
6
7using namespace Fortran::decimal;
8
9static int tests{0};
10static int fails{0};
11
12union u {
13 float x;
14 std::uint32_t u;
15};
16
17llvm::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(N: u.u);
23}
24
25void 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(s1: result.str, s2: 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
40void 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::snprintf(s: q + result.length,
57 maxlen: buffer + sizeof buffer - (q + result.length), format: "e%d", expo);
58 }
59 const char *p{q};
60 auto rflags{ConvertDecimalToFloat(&p, &y, RoundNearest)};
61 union u u;
62 if (!(x == x)) {
63 if (y == y || *p != '\0' || (rflags & Invalid)) {
64 u.x = y;
65 (failed(x) << " (NaN) " << flags << ": -> '" << result.str << "' -> 0x")
66 .write_hex(u.u)
67 << " '" << p << "' " << rflags << '\n';
68 }
69 } else if (x != y || *p != '\0' || (rflags & Invalid)) {
70 u.x = x;
71 (failed(x) << ' ' << flags << ": -> '" << result.str << "' -> 0x")
72 .write_hex(u.u)
73 << " '" << p << "' " << rflags << '\n';
74 }
75 }
76}
77
78int main() {
79 union u u;
80 testDirect(x: -1.0, expect: "-1", expectExpo: 1);
81 testDirect(x: 0.0, expect: "0", expectExpo: 0);
82 testDirect(0.0, "+0", 0, AlwaysSign);
83 testDirect(x: 1.0, expect: "1", expectExpo: 1);
84 testDirect(x: 2.0, expect: "2", expectExpo: 1);
85 testDirect(x: -1.0, expect: "-1", expectExpo: 1);
86 testDirect(x: 314159, expect: "314159", expectExpo: 6);
87 testDirect(x: 0.0625, expect: "625", expectExpo: -1);
88 u.u = 0x80000000;
89 testDirect(x: u.x, expect: "-0", expectExpo: 0);
90 u.u = 0x7f800000;
91 testDirect(x: u.x, expect: "Inf", expectExpo: 0);
92 testDirect(u.x, "+Inf", 0, AlwaysSign);
93 u.u = 0xff800000;
94 testDirect(x: u.x, expect: "-Inf", expectExpo: 0);
95 u.u = 0xffffffff;
96 testDirect(x: u.x, expect: "NaN", expectExpo: 0);
97 testDirect(u.x, "NaN", 0, AlwaysSign);
98 u.u = 1;
99 testDirect(x: u.x,
100 expect: "140129846432481707092372958328991613128026194187651577175706828388979108"
101 "268586060148663818836212158203125",
102 expectExpo: -44, flags: 0);
103 testDirect(u.x, "1", -44, Minimize);
104 u.u = 0x7f777777;
105 testDirect(x: u.x, expect: "3289396118917826996438159226753253376", expectExpo: 39, flags: 0);
106 testDirect(u.x, "32893961", 39, Minimize);
107 for (u.u = 0; u.u < 16; ++u.u) {
108 testReadback(x: u.x, flags: 0);
109 testReadback(x: -u.x, flags: 0);
110 testReadback(u.x, Minimize);
111 testReadback(-u.x, Minimize);
112 }
113 for (u.u = 1; u.u < 0x7f800000; u.u *= 2) {
114 testReadback(x: u.x, flags: 0);
115 testReadback(x: -u.x, flags: 0);
116 testReadback(u.x, Minimize);
117 testReadback(-u.x, Minimize);
118 }
119 for (u.u = 0x7f7ffff0; u.u < 0x7f800010; ++u.u) {
120 testReadback(x: u.x, flags: 0);
121 testReadback(x: -u.x, flags: 0);
122 testReadback(u.x, Minimize);
123 testReadback(-u.x, Minimize);
124 }
125 for (u.u = 0; u.u < 0x7f800000; u.u += 65536) {
126 testReadback(x: u.x, flags: 0);
127 testReadback(x: -u.x, flags: 0);
128 testReadback(u.x, Minimize);
129 testReadback(-u.x, Minimize);
130 }
131 for (u.u = 0; u.u < 0x7f800000; u.u += 99999) {
132 testReadback(x: u.x, flags: 0);
133 testReadback(x: -u.x, flags: 0);
134 testReadback(u.x, Minimize);
135 testReadback(-u.x, Minimize);
136 }
137 for (u.u = 0; u.u < 0x7f800000; u.u += 32767) {
138 testReadback(x: u.x, flags: 0);
139 testReadback(x: -u.x, flags: 0);
140 testReadback(u.x, Minimize);
141 testReadback(-u.x, Minimize);
142 }
143 llvm::outs() << tests << " tests run, " << fails << " tests failed\n";
144 return fails > 0;
145}
146

source code of flang/unittests/Decimal/quick-sanity-test.cpp