2020-02-25 23:11:52 +08:00
|
|
|
#include "flang/Decimal/decimal.h"
|
2020-02-28 23:11:03 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2019-08-15 06:25:16 +08:00
|
|
|
#include <cinttypes>
|
|
|
|
#include <cstdio>
|
|
|
|
#include <cstring>
|
|
|
|
|
2019-08-17 02:12:18 +08:00
|
|
|
using namespace Fortran::decimal;
|
|
|
|
|
2019-08-15 06:25:16 +08:00
|
|
|
static int tests{0};
|
|
|
|
static int fails{0};
|
|
|
|
|
2019-08-20 06:50:21 +08:00
|
|
|
union u {
|
|
|
|
float x;
|
|
|
|
std::uint32_t u;
|
|
|
|
};
|
|
|
|
|
2020-02-28 23:11:03 +08:00
|
|
|
llvm::raw_ostream &failed(float x) {
|
2019-08-15 06:25:16 +08:00
|
|
|
++fails;
|
2019-08-20 06:50:21 +08:00
|
|
|
union u u;
|
|
|
|
u.x = x;
|
2020-02-28 23:11:03 +08:00
|
|
|
llvm::outs() << "FAIL: 0x";
|
|
|
|
return llvm::outs().write_hex(u.u);
|
2019-08-15 06:25:16 +08:00
|
|
|
}
|
|
|
|
|
2019-08-15 07:21:46 +08:00
|
|
|
void testDirect(float x, const char *expect, int expectExpo, int flags = 0) {
|
2019-08-15 06:25:16 +08:00
|
|
|
char buffer[1024];
|
|
|
|
++tests;
|
|
|
|
auto result{ConvertFloatToDecimal(buffer, sizeof buffer,
|
2019-08-15 07:21:46 +08:00
|
|
|
static_cast<enum DecimalConversionFlags>(flags), 1024, RoundNearest, x)};
|
2019-08-15 06:25:16 +08:00
|
|
|
if (result.str == nullptr) {
|
2019-08-15 07:21:46 +08:00
|
|
|
failed(x) << ' ' << flags << ": no result str\n";
|
|
|
|
} else if (std::strcmp(result.str, expect) != 0 ||
|
|
|
|
result.decimalExponent != expectExpo) {
|
|
|
|
failed(x) << ' ' << flags << ": expect '." << expect << 'e' << expectExpo
|
|
|
|
<< "', got '." << result.str << 'e' << result.decimalExponent
|
|
|
|
<< "'\n";
|
2019-08-15 06:25:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-15 07:21:46 +08:00
|
|
|
void testReadback(float x, int flags) {
|
2019-08-15 06:25:16 +08:00
|
|
|
char buffer[1024];
|
|
|
|
++tests;
|
|
|
|
auto result{ConvertFloatToDecimal(buffer, sizeof buffer,
|
2019-08-15 07:21:46 +08:00
|
|
|
static_cast<enum DecimalConversionFlags>(flags), 1024, RoundNearest, x)};
|
2019-08-15 06:25:16 +08:00
|
|
|
if (result.str == nullptr) {
|
2019-08-15 07:21:46 +08:00
|
|
|
failed(x) << ' ' << flags << ": no result str\n";
|
2019-08-15 06:25:16 +08:00
|
|
|
} else {
|
|
|
|
float y{0};
|
|
|
|
char *q{const_cast<char *>(result.str)};
|
2019-08-15 07:21:46 +08:00
|
|
|
int expo{result.decimalExponent};
|
|
|
|
expo -= result.length;
|
|
|
|
if (*q == '-' || *q == '+') {
|
|
|
|
++expo;
|
|
|
|
}
|
2019-08-15 08:05:08 +08:00
|
|
|
if (q >= buffer && q < buffer + sizeof buffer) {
|
|
|
|
std::sprintf(q + result.length, "e%d", expo);
|
|
|
|
}
|
2019-08-15 06:25:16 +08:00
|
|
|
const char *p{q};
|
2019-08-15 08:05:08 +08:00
|
|
|
auto rflags{ConvertDecimalToFloat(&p, &y, RoundNearest)};
|
2019-08-20 06:50:21 +08:00
|
|
|
union u u;
|
2019-08-15 08:05:08 +08:00
|
|
|
if (!(x == x)) {
|
|
|
|
if (y == y || *p != '\0' || (rflags & Invalid)) {
|
2019-08-20 06:50:21 +08:00
|
|
|
u.x = y;
|
2020-02-28 23:11:03 +08:00
|
|
|
failed(x) << " (NaN) " << flags << ": -> '" << result.str << "' -> 0x";
|
|
|
|
failed(x).write_hex(u.u) << " '" << p << "' " << rflags << '\n';
|
2019-08-15 08:05:08 +08:00
|
|
|
}
|
|
|
|
} else if (x != y || *p != '\0' || (rflags & Invalid)) {
|
2019-08-20 06:50:21 +08:00
|
|
|
u.x = y;
|
2020-02-28 23:11:03 +08:00
|
|
|
failed(x) << ' ' << flags << ": -> '" << result.str << "' -> 0x";
|
|
|
|
failed(x).write_hex(u.u) << " '" << p << "' " << rflags << '\n';
|
2019-08-15 06:25:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main() {
|
2019-08-20 06:50:21 +08:00
|
|
|
union u u;
|
2019-08-15 06:25:16 +08:00
|
|
|
testDirect(-1.0, "-1", 1);
|
|
|
|
testDirect(0.0, "0", 0);
|
2019-08-15 07:21:46 +08:00
|
|
|
testDirect(0.0, "+0", 0, AlwaysSign);
|
2019-08-15 06:25:16 +08:00
|
|
|
testDirect(1.0, "1", 1);
|
|
|
|
testDirect(2.0, "2", 1);
|
|
|
|
testDirect(-1.0, "-1", 1);
|
|
|
|
testDirect(314159, "314159", 6);
|
|
|
|
testDirect(0.0625, "625", -1);
|
2019-08-20 06:50:21 +08:00
|
|
|
u.u = 0x80000000;
|
|
|
|
testDirect(u.x, "-0", 0);
|
|
|
|
u.u = 0x7f800000;
|
|
|
|
testDirect(u.x, "Inf", 0);
|
|
|
|
testDirect(u.x, "+Inf", 0, AlwaysSign);
|
|
|
|
u.u = 0xff800000;
|
|
|
|
testDirect(u.x, "-Inf", 0);
|
|
|
|
u.u = 0xffffffff;
|
|
|
|
testDirect(u.x, "NaN", 0);
|
|
|
|
testDirect(u.x, "NaN", 0, AlwaysSign);
|
|
|
|
u.u = 1;
|
|
|
|
testDirect(u.x,
|
2019-08-15 07:21:46 +08:00
|
|
|
"140129846432481707092372958328991613128026194187651577175706828388979108"
|
|
|
|
"268586060148663818836212158203125",
|
|
|
|
-44, 0);
|
2019-08-20 06:50:21 +08:00
|
|
|
testDirect(u.x, "1", -44, Minimize);
|
|
|
|
u.u = 0x7f777777;
|
|
|
|
testDirect(u.x, "3289396118917826996438159226753253376", 39, 0);
|
|
|
|
testDirect(u.x, "32893961", 39, Minimize);
|
|
|
|
for (u.u = 0; u.u < 16; ++u.u) {
|
|
|
|
testReadback(u.x, 0);
|
|
|
|
testReadback(-u.x, 0);
|
|
|
|
testReadback(u.x, Minimize);
|
|
|
|
testReadback(-u.x, Minimize);
|
2019-08-15 07:21:46 +08:00
|
|
|
}
|
2019-08-20 06:50:21 +08:00
|
|
|
for (u.u = 1; u.u < 0x7f800000; u.u *= 2) {
|
|
|
|
testReadback(u.x, 0);
|
|
|
|
testReadback(-u.x, 0);
|
|
|
|
testReadback(u.x, Minimize);
|
|
|
|
testReadback(-u.x, Minimize);
|
2019-08-15 07:21:46 +08:00
|
|
|
}
|
2019-08-20 06:50:21 +08:00
|
|
|
for (u.u = 0x7f7ffff0; u.u < 0x7f800010; ++u.u) {
|
|
|
|
testReadback(u.x, 0);
|
|
|
|
testReadback(-u.x, 0);
|
|
|
|
testReadback(u.x, Minimize);
|
|
|
|
testReadback(-u.x, Minimize);
|
2019-08-15 07:21:46 +08:00
|
|
|
}
|
2019-08-20 06:50:21 +08:00
|
|
|
for (u.u = 0; u.u < 0x7f800000; u.u += 65536) {
|
|
|
|
testReadback(u.x, 0);
|
|
|
|
testReadback(-u.x, 0);
|
|
|
|
testReadback(u.x, Minimize);
|
|
|
|
testReadback(-u.x, Minimize);
|
2019-08-15 07:21:46 +08:00
|
|
|
}
|
2019-08-20 06:50:21 +08:00
|
|
|
for (u.u = 0; u.u < 0x7f800000; u.u += 99999) {
|
|
|
|
testReadback(u.x, 0);
|
|
|
|
testReadback(-u.x, 0);
|
|
|
|
testReadback(u.x, Minimize);
|
|
|
|
testReadback(-u.x, Minimize);
|
2019-08-15 07:21:46 +08:00
|
|
|
}
|
2019-08-20 06:50:21 +08:00
|
|
|
for (u.u = 0; u.u < 0x7f800000; u.u += 32767) {
|
|
|
|
testReadback(u.x, 0);
|
|
|
|
testReadback(-u.x, 0);
|
|
|
|
testReadback(u.x, Minimize);
|
|
|
|
testReadback(-u.x, Minimize);
|
2019-08-15 07:21:46 +08:00
|
|
|
}
|
2020-02-28 23:11:03 +08:00
|
|
|
llvm::outs() << tests << " tests run, " << fails << " tests failed\n";
|
2019-08-15 06:25:16 +08:00
|
|
|
return fails > 0;
|
|
|
|
}
|