File: thorough-test.cpp

package info (click to toggle)
llvm-toolchain-17 1%3A17.0.6-22
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,799,624 kB
  • sloc: cpp: 6,428,607; ansic: 1,383,196; asm: 793,408; python: 223,504; objc: 75,364; f90: 60,502; lisp: 33,869; pascal: 15,282; sh: 9,684; perl: 7,453; ml: 4,937; awk: 3,523; makefile: 2,889; javascript: 2,149; xml: 888; fortran: 619; cs: 573
file content (89 lines) | stat: -rw-r--r-- 2,455 bytes parent folder | download | duplicates (12)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include "flang/Decimal/decimal.h"
#include "llvm/Support/raw_ostream.h"
#include <cinttypes>
#include <cstdio>
#include <cstring>

static constexpr int incr{1}; // steps through all values
static constexpr bool doNegative{true};
static constexpr bool doMinimize{true};

using namespace Fortran::decimal;

static std::uint64_t tests{0};
static std::uint64_t fails{0};

union u {
  float x;
  std::uint32_t u;
};

llvm::raw_ostream &failed(float x) {
  ++fails;
  union u u;
  u.x = x;
  llvm::outs() << "FAIL: 0x";
  return llvm::outs().write_hex(u.u);
}

void testReadback(float x, int flags) {
  char buffer[1024];
  union u u;
  u.x = x;
  if (!(tests & 0x3fffff)) {
    llvm::errs() << "\n0x";
    llvm::errs().write_hex(u.u) << ' ';
  } else if (!(tests & 0xffff)) {
    llvm::errs() << '.';
  }
  ++tests;
  auto result{ConvertFloatToDecimal(buffer, sizeof buffer,
      static_cast<enum DecimalConversionFlags>(flags), 1024, RoundNearest, x)};
  if (result.str == nullptr) {
    failed(x) << ' ' << flags << ": no result str\n";
  } else {
    float y{0};
    char *q{const_cast<char *>(result.str)};
    if ((*q >= '0' && *q <= '9') ||
        ((*q == '-' || *q == '+') && q[1] >= '0' && q[1] <= '9')) {
      int expo{result.decimalExponent};
      expo -= result.length;
      if (*q == '-' || *q == '+') {
        ++expo;
      }
      std::snprintf(q + result.length,
          buffer + sizeof buffer - (q + result.length), "e%d", expo);
    }
    const char *p{q};
    auto rflags{ConvertDecimalToFloat(&p, &y, RoundNearest)};
    if (!(x == x)) {
      if (y == y || *p != '\0' || (rflags & Invalid)) {
        u.x = y;
        failed(x) << " (NaN) " << flags << ": -> '" << result.str << "' -> 0x";
        failed(x).write_hex(u.u) << " '" << p << "' " << rflags << '\n';
      }
    } else if (x != y || *p != '\0' || (rflags & Invalid)) {
      u.x = y;
      failed(x) << ' ' << flags << ": -> '" << result.str << "' -> 0x";
      failed(x).write_hex(u.u) << " '" << p << "' " << rflags << '\n';
    }
  }
}

int main() {
  union u u;
  for (u.u = 0; u.u < 0x7f800010; u.u += incr) {
    testReadback(u.x, 0);
    if constexpr (doNegative) {
      testReadback(-u.x, 0);
    }
    if constexpr (doMinimize) {
      testReadback(u.x, Minimize);
      if constexpr (doNegative) {
        testReadback(-u.x, Minimize);
      }
    }
  }
  llvm::outs() << '\n' << tests << " tests run, " << fails << " tests failed\n";
  return fails > 0;
}