#ifndef FORTRAN_EVALUATE_TYPE_H_
#define FORTRAN_EVALUATE_TYPE_H_
-// These definitions map Fortran's intrinsic types to their value
-// representation types in the evaluation library for ease of template
-// programming.
+// These definitions map Fortran's intrinsic types, characterized by byte
+// sizes encoded in KIND type parameter values, to their value representation
+// types in the evaluation library, which are parameterized in terms of
+// total bit width and real precision.
#include "complex.h"
#include "integer.h"
using ValueType = value::Logical<8 * kind>;
};
-#if 0 // TODO
template<int KIND> struct Character {
static constexpr Classification classification{Classification::Character};
static constexpr int kind{KIND};
static constexpr bool hasLen{true};
- using ValueType = value::Character<8 * kind>;
+ using ValueType = std::uint8_t[kind]; // TODO: ?
};
-#endif
// Default REAL just simply has to be IEEE-754 single precision today.
// It occupies one numeric storage unit by definition. The default INTEGER
using IntrinsicTypeParameterType = DefaultInteger;
using DefaultComplex = Complex<2 * DefaultReal::kind>;
using DefaultLogical = Logical<DefaultReal::kind>;
-#if 0 // TODO
using DefaultCharacter = Character<1>;
-#endif
} // namespace Fortran::evaluate::type
#endif // FORTRAN_EVALUATE_TYPE_H_
#include "testing.h"
#include "../../lib/evaluate/type.h"
#include <cstdio>
+#include <cstdlib>
using namespace Fortran::evaluate;
// the upper two bits and lowest bit in the significand. The middle bits
// of the significand are either all zeroes or all ones.
std::uint32_t MakeReal(std::uint32_t n) {
- return ((n & 0x1ffc) << 20) | !!(n & 2) | ((-(n & 1) & 0xfffff) << 1);
+ std::uint32_t n0_8{n & 0x1ff};
+ std::uint32_t n9{(n >> 9) & 1};
+ std::uint32_t n10{(n >> 10) & 1};
+ std::uint32_t n11{(n >> 11) & 1};
+ std::uint32_t n12{(n >> 12) & 1};
+ return (n0_8 << 23) | (n9 << 22) | (n11 << 21) | (-n12 & 0x1ffffe) | n10;
}
std::uint32_t NormalizeNaN(std::uint32_t x) {
MATCH(actualFlags, FlagsToBits(real.flags))("%d 0x%llx", pass, x);
}
-void subset32bit(int pass, Rounding rounding) {
+void subset32bit(int pass, Rounding rounding, std::uint32_t opds) {
for (int j{0}; j < 63; ++j) {
std::int64_t x{1};
x <<= j;
} u;
ScopedHostFloatingPointEnvironment fpenv;
- for (std::uint32_t j{0}; j < 8192; ++j) {
+ for (std::uint32_t j{0}; j < opds; ++j) {
std::uint32_t rj{MakeReal(j)};
u.u32 = rj;
float fj{u.f};
Real4 x{Integer4{std::uint64_t{rj}}};
- for (std::uint32_t k{0}; k < 8192; ++k) {
+ for (std::uint32_t k{0}; k < opds; ++k) {
std::uint32_t rk{MakeReal(k)};
u.u32 = rk;
float fk{u.f};
}
}
-void roundTest(int rm, Rounding rounding) {
+void roundTest(int rm, Rounding rounding, std::uint32_t opds) {
basicTests<Real2>(rm, rounding);
basicTests<Real4>(rm, rounding);
basicTests<Real8>(rm, rounding);
basicTests<Real10>(rm, rounding);
basicTests<Real16>(rm, rounding);
ScopedHostFloatingPointEnvironment::SetRounding(rounding);
- subset32bit(rm, rounding);
+ subset32bit(rm, rounding, opds);
}
int main() {
- roundTest(0, Rounding::TiesToEven);
- roundTest(1, Rounding::ToZero);
- roundTest(2, Rounding::Up);
- roundTest(3, Rounding::Down);
+ std::uint32_t opds{1024};
+ if (const char *p{std::getenv("REAL_TEST_OPERANDS")}) {
+ // Use 8192 for more exhaustive testing.
+ opds = std::atol(p);
+ }
+ roundTest(0, Rounding::TiesToEven, opds);
+ roundTest(1, Rounding::ToZero, opds);
+ roundTest(2, Rounding::Up, opds);
+ roundTest(3, Rounding::Down, opds);
// TODO: how to test Rounding::TiesAwayFromZero on x86?
}