if (exponent == maxExponent && !fraction.IsZero()) { // NaN
result.flags |= RealFlag::InvalidArgument;
result.value = result.value.HUGE();
- } else if (exponent >= exponentBias + result.value.bits) { // +/-Inf
+ } else if (exponent >= maxExponent || exponent >= exponentBias + result.value.bits) { // +/-Inf
if (isNegative) {
result.value = result.value.MASKL(1);
} else {
result.value = result.value.HUGE();
}
- result.flags = RealFlag::Overflow;
+ result.flags |= RealFlag::Overflow;
} else if (exponent < exponentBias) { // |x| < 1.0
if (!fraction.IsZero()) {
result.flags |= RealFlag::Underflow | RealFlag::Inexact;
// +/-0.0
word_ = Word{};
} else if (biasedExponent <= leadz) {
+ // denormal
word_ = Word::Convert(fraction).value.SHIFTL(biasedExponent);
- // TODO: Underflow
} else {
word_ = Word::Convert(fraction).value.SHIFTL(leadz);
if (implicitMSB) {
}
}
+ // Determines whether a value should be rounded by increasing its
+ // fraction, given a rounding mode and a summary of the lost bits.
constexpr bool MustRound(Rounding rounding, const RoundingBits &bits) const {
bool round{false}; // to dodge bogus g++ warning about missing return
switch (rounding) {
return round;
}
- // Returns flags.
+ // Rounds a result, if necessary; returns flags.
int Round(Rounding rounding, const RoundingBits &bits) {
std::uint64_t exponent{Exponent()};
int flags{(bits.round | bits.guard) ? RealFlag::Inexact : RealFlag::Ok};
Word word_{}; // an Integer<>
};
+using RealKind2 = Real<Integer<16>, 11>;
extern template class Real<Integer<16>, 11>;
+
+using RealKind4 = Real<Integer<32>, 24>;
extern template class Real<Integer<32>, 24>;
+
+using RealKind8 = Real<Integer<64>, 53>;
extern template class Real<Integer<64>, 53>;
+
+using RealKind10 = Real<Integer<80>, 64, false>; // 80387
extern template class Real<Integer<80>, 64, false>;
+
+using RealKind16 = Real<Integer<128>, 112>;
extern template class Real<Integer<128>, 112>;
+// N.B. No "double-double" support.
+
} // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_REAL_H_
#include "testing.h"
#include <cstdio>
-using Fortran::evaluate::Integer;
-using Fortran::evaluate::Ordering;
-using Fortran::evaluate::Real;
-using Fortran::evaluate::Relation;
-using Fortran::evaluate::ValueWithRealFlags;
+using namespace Fortran::evaluate;
template<typename R> void tests() {
char desc[64];
TEST(!vr.value.IsZero())("%s,%d,0x%llx",desc,j,x);
auto ivf = vr.value.template ToInteger<Integer<64>>();
if (j > (maxExponent / 2)) {
- MATCH(Fortran::evaluate::RealFlag::Overflow, vr.flags)(desc);
+ MATCH(RealFlag::Overflow, vr.flags)(desc);
TEST(vr.value.IsInfinite())("%s,%d,0x%llx",desc,j,x);
- MATCH(Fortran::evaluate::RealFlag::Overflow, ivf.flags)("%s,%d,0x%llx",desc,j,x);
+ MATCH(RealFlag::Overflow, ivf.flags)("%s,%d,0x%llx",desc,j,x);
MATCH(0x7fffffffffffffff, ivf.value.ToUInt64())("%s,%d,0x%llx",desc,j,x);
} else {
- MATCH(Fortran::evaluate::RealFlag::Ok, vr.flags)(desc);
+ MATCH(RealFlag::Ok, vr.flags)(desc);
TEST(!vr.value.IsInfinite())("%s,%d,0x%llx",desc,j,x);
- MATCH(Fortran::evaluate::RealFlag::Ok, ivf.flags)("%s,%d,0x%llx",desc,j,x);
+ MATCH(RealFlag::Ok, ivf.flags)("%s,%d,0x%llx",desc,j,x);
MATCH(x, ivf.value.ToUInt64())("%s,%d,0x%llx",desc,j,x);
}
}
}
int main() {
- tests<Real<Integer<16>, 11>>();
- tests<Real<Integer<32>, 24>>();
- tests<Real<Integer<64>, 53>>();
- tests<Real<Integer<80>, 64, false>>();
- tests<Real<Integer<128>, 112>>();
+ tests<RealKind2>();
+ tests<RealKind4>();
+ tests<RealKind8>();
+ tests<RealKind10>();
+ tests<RealKind16>();
return testing::Complete();
}