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