}
private:
- constexpr Integer(std::nullptr_t) {} // does not initialize parts
+ // A private constructor, selected by the use of nullptr,
+ // that is used by member functions when it would be a waste
+ // of time to initialize parts_[].
+ constexpr Integer(std::nullptr_t) {}
// Accesses parts in little-endian order.
constexpr const Part &LEPart(int part) const {
}
bool guard{NextQuotientBit(top, msb, divisor)};
bool round{NextQuotientBit(top, msb, divisor)};
- bool sticky{msb | !top.IsZero()};
+ bool sticky{msb || !top.IsZero()};
RoundingBits roundingBits{guard, round, sticky};
if (exponent < 1) {
std::int64_t rshift{1 - exponent};
using ValueType = value::Real<typename Integer<kind>::ValueType, 112>;
};
+// The KIND type parameter on COMPLEX is the kind of each of its components.
template<int KIND> struct Complex {
static constexpr Classification classification{Classification::Complex};
static constexpr int kind{KIND};
static constexpr bool hasLen{false};
- using ValueType = value::Complex<typename Real<(8 * kind / 2)>::ValueType>;
+ using ValueType = value::Complex<typename Real<kind>::ValueType>;
};
template<int KIND> struct Logical {
using DefaultReal = Real<4>;
using DefaultInteger = Integer<DefaultReal::kind>;
using IntrinsicTypeParameterType = DefaultInteger;
-using DefaultComplex = Complex<2 * DefaultReal::kind>;
+using DefaultComplex = Complex<DefaultReal::kind>;
using DefaultLogical = Logical<DefaultReal::kind>;
using DefaultCharacter = Character<1>;
bool Pre(const parser::CallStmt &);
void Post(const parser::CallStmt &);
+ // TODO(tkeith): Needed for clang build only (!?)
+ bool Pre(const parser::ProcedureDeclarationStmt &stmt) {
+ return DeclarationVisitor::Pre(stmt) ||
+ ImplicitRulesVisitor::Pre(stmt);
+ }
+ void Post(const parser::ProcedureDeclarationStmt &stmt) {
+ DeclarationVisitor::Post(stmt);
+ ImplicitRulesVisitor::Post(stmt);
+ }
+
private:
// Kind of procedure we are expecting to see in a ProcedureDesignator
std::optional<Symbol::Flag> expectedProcFlag_;
target_link_libraries(real-test
FortranEvaluate
FortranEvaluateTesting
+ m
)
std::fprintf(stderr, "fegetenv() failed: %s\n", std::strerror(errno));
std::abort();
}
-#ifdef __x86_64__
+#if defined __x86_64__
if (treatDenormalOperandsAsZero) {
currentFenv_.__mxcsr |= 0x0040;
} else {
std::uint32_t FlagsToBits(const RealFlags &flags) {
std::uint32_t bits{0};
+#ifndef __clang__
+ // TODO: clang support for fenv.h is broken, so tests of flag settings
+ // are disabled.
if (flags.test(RealFlag::Overflow)) {
bits |= 1;
}
if (flags.test(RealFlag::Inexact)) {
bits |= 0x10;
}
+#endif // __clang__
return bits;
}
Integer8 ix{x};
ValueWithRealFlags<Real4> real;
real = real.value.ConvertSigned(ix, rounding);
+#ifndef __clang__ // broken and also slow
fpenv.ClearFlags();
+#endif
float fcheck = x; // TODO unsigned too
auto actualFlags{FlagsToBits(fpenv.CurrentFlags())};
u.f = fcheck;
Real4 y{Integer4{std::uint64_t{rk}}};
{
ValueWithRealFlags<Real4> sum{x.Add(y, rounding)};
+#ifndef __clang__ // broken and also slow
fpenv.ClearFlags();
+#endif
float fcheck{fj + fk};
auto actualFlags{FlagsToBits(fpenv.CurrentFlags())};
u.f = fcheck;
}
{
ValueWithRealFlags<Real4> diff{x.Subtract(y, rounding)};
+#ifndef __clang__ // broken and also slow
fpenv.ClearFlags();
+#endif
float fcheck{fj - fk};
auto actualFlags{FlagsToBits(fpenv.CurrentFlags())};
u.f = fcheck;
}
{
ValueWithRealFlags<Real4> prod{x.Multiply(y, rounding)};
+#ifndef __clang__ // broken and also slow
fpenv.ClearFlags();
+#endif
float fcheck{fj * fk};
auto actualFlags{FlagsToBits(fpenv.CurrentFlags())};
u.f = fcheck;
}
{
ValueWithRealFlags<Real4> quot{x.Divide(y, rounding)};
+#ifndef __clang__ // broken and also slow
fpenv.ClearFlags();
+#endif
float fcheck{fj / fk};
auto actualFlags{FlagsToBits(fpenv.CurrentFlags())};
u.f = fcheck;