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 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 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 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 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