[flang] begin testing reals

Original-commit: flang-compiler/f18@9d261b594b
Reviewed-on: https://github.com/flang-compiler/f18/pull/101
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler 2018-06-05 16:29:26 -07:00
parent 321056b53c
commit eb9ad7ef07
4 changed files with 159 additions and 22 deletions

View File

@ -108,3 +108,4 @@ enable_testing()
add_test(NAME Leadz COMMAND leading-zero-bit-count-test)
add_test(NAME PopPar COMMAND bit-population-count-test)
add_test(NAME Integer COMMAND integer-test)
add_test(NAME Real COMMAND real-test)

View File

@ -40,29 +40,31 @@ public:
constexpr Real() {} // +0.0
constexpr Real(const Real &) = default;
constexpr Real &operator=(const Real &) = default;
constexpr Real(const Word &bits) : word_{bits} {}
template<typename INT>
static constexpr ValueWithRealFlags<Real> ConvertSigned(
const INT &n, Rounding rounding = Rounding::TiesToEven) {
bool isNegative{n.IsNegative()};
INT absN{n};
if (isNegative) {
n = n.Negate().value; // overflow is okay
absN = n.Negate().value; // overflow is safe to ignore
}
int leadz{n.LEADZ()};
if (leadz >= n.bits) {
int leadz{absN.LEADZ()};
if (leadz >= absN.bits) {
return {}; // all bits zero -> +0.0
}
ValueWithRealFlags<Real> result;
int exponent{exponentBias + n.bits - leadz - 1};
int bitsNeeded{n.bits - (leadz + implicitMSB)};
std::uint64_t exponent{exponentBias + absN.bits - leadz - 1};
int bitsNeeded{absN.bits - (leadz + implicitMSB)};
int bitsLost{bitsNeeded - significandBits};
if (bitsLost <= 0) {
Fraction fraction{Fraction::Convert(n).value};
Fraction fraction{Fraction::Convert(absN).value};
result.flags |= result.value.Normalize(
isNegative, exponent, fraction.SHIFTL(-bitsLost));
} else {
RoundingBits roundingBits{GetRoundingBits(n, bitsLost)};
Fraction fraction{Fraction::Convert(n.SHIFTR(bitsLost)).value};
RoundingBits roundingBits{GetRoundingBits(absN, bitsLost)};
Fraction fraction{Fraction::Convert(absN.SHIFTR(bitsLost)).value};
result.flags |= result.value.Normalize(isNegative, exponent, fraction);
result.flags |= result.value.Round(rounding, roundingBits);
}
@ -74,10 +76,15 @@ public:
// HUGE, INT/NINT, MAXEXPONENT, MINEXPONENT, NEAREST, OUT_OF_RANGE,
// PRECISION, HUGE, TINY, RRSPACING/SPACING, SCALE, SET_EXPONENT, SIGN
constexpr Word RawBits() const {
return word_;
}
constexpr std::uint64_t Exponent() const {
return word_.IBITS(significandBits, exponentBits).ToUInt64();
}
constexpr bool IsNegative() const { return word_.BTEST(bits - 1); }
constexpr bool IsNegative() const {
return !IsNotANumber() && word_.BTEST(bits - 1);
}
constexpr bool IsNotANumber() const {
return Exponent() == maxExponent && !GetSignificand().IsZero();
}
@ -158,7 +165,7 @@ public:
result.value = result.value.HUGE();
} else if (isNegative) {
auto negated = result.value.Negate();
if (result.overflow) {
if (negated.overflow) {
result.flags |= RealFlag::Overflow;
result.value = result.value.HUGE();
} else {
@ -369,8 +376,8 @@ private:
}
}
static constexpr RoundingBits GetRoundingBits(
const Fraction &fraction, int rshift) {
template<typename INT>
static constexpr RoundingBits GetRoundingBits(const INT &fraction, int rshift) {
RoundingBits roundingBits;
if (rshift > fraction.bits) {
roundingBits.guard = !fraction.IsZero();
@ -392,16 +399,10 @@ private:
bool negative, std::uint64_t biasedExponent, const Fraction &fraction) {
if (biasedExponent >= maxExponent) {
word_ = Word{maxExponent}.SHIFTL(significandBits);
if (fraction.IsZero()) {
// infinity
if (negative) {
word_ = word_.IBSET(bits - 1);
}
return RealFlag::Ok;
} else {
word_ = NaNWord();
return RealFlag::InvalidArgument;
if (negative) {
word_ = word_.IBSET(bits - 1);
}
return RealFlag::Overflow;
} else {
std::uint64_t leadz = fraction.LEADZ();
if (leadz >= precision) {
@ -415,7 +416,7 @@ private:
if (implicitMSB) {
word_ = word_.IBCLR(significandBits);
}
word_.IOR(Word{biasedExponent - leadz}.SHIFTL(significandBits));
word_ = word_.IOR(Word{biasedExponent - leadz}.SHIFTL(significandBits));
}
if (negative) {
word_ = word_.IBSET(bits - 1);

View File

@ -42,3 +42,12 @@ target_link_libraries(integer-test
FortranEvaluate
FortranEvaluateTesting
)
add_executable(real-test
real.cc
)
target_link_libraries(real-test
FortranEvaluate
FortranEvaluateTesting
)

126
flang/test/evaluate/real.cc Normal file
View File

@ -0,0 +1,126 @@
// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "../../lib/evaluate/integer.h"
#include "../../lib/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;
template<typename R> void tests() {
char desc[64];
using Word = typename R::Word;
std::snprintf(desc, sizeof desc, "bits=%d, le=%d",
R::bits, Word::littleEndian);
R zero;
TEST(!zero.IsNegative())(desc);
TEST(!zero.IsNotANumber())(desc);
TEST(!zero.IsInfinite())(desc);
TEST(zero.IsZero())(desc);
MATCH(0, zero.Exponent())(desc);
TEST(zero.RawBits().IsZero())(desc);
MATCH(0, zero.RawBits().ToUInt64())(desc);
TEST(zero.ABS().RawBits().IsZero())(desc);
TEST(zero.Negate().RawBits().IEOR(Word::MASKL(1)).IsZero())(desc);
TEST(zero.Compare(zero) == Relation::Equal)(desc);
R minusZero{Word{std::uint64_t{1}}.SHIFTL(R::bits - 1)};
TEST(minusZero.IsNegative())(desc);
TEST(!minusZero.IsNotANumber())(desc);
TEST(!minusZero.IsInfinite())(desc);
TEST(minusZero.IsZero())(desc);
TEST(minusZero.ABS().RawBits().IsZero())(desc);
TEST(minusZero.Negate().RawBits().IsZero())(desc);
MATCH(0, minusZero.Exponent())(desc);
MATCH(0, minusZero.RawBits().LEADZ())(desc);
MATCH(1, minusZero.RawBits().POPCNT())(desc);
TEST(minusZero.Compare(minusZero) == Relation::Equal)(desc);
TEST(zero.Compare(minusZero) == Relation::Equal)(desc);
ValueWithRealFlags<R> vr;
MATCH(0, vr.value.RawBits().ToUInt64())(desc);
MATCH(0, vr.flags)(desc);
R nan{Word{std::uint64_t{1}}.SHIFTL(R::bits).SubtractSigned(Word{std::uint64_t{1}}).value};
MATCH(R::bits, nan.RawBits().POPCNT())(desc);
TEST(!nan.IsNegative())(desc);
TEST(nan.IsNotANumber())(desc);
TEST(!nan.IsInfinite())(desc);
TEST(!nan.IsZero())(desc);
TEST(zero.Compare(nan) == Relation::Unordered)(desc);
TEST(minusZero.Compare(nan) == Relation::Unordered)(desc);
TEST(nan.Compare(zero) == Relation::Unordered)(desc);
TEST(nan.Compare(minusZero) == Relation::Unordered)(desc);
TEST(nan.Compare(nan) == Relation::Unordered)(desc);
int significandBits{R::precision - R::implicitMSB};
int exponentBits{R::bits - significandBits - 1};
std::uint64_t maxExponent{(std::uint64_t{1} << exponentBits) - 1};
MATCH(nan.Exponent(), maxExponent)(desc);
R inf{Word{maxExponent}.SHIFTL(significandBits)};
TEST(!inf.IsNegative())(desc);
TEST(!inf.IsNotANumber())(desc);
TEST(inf.IsInfinite())(desc);
TEST(!inf.IsZero())(desc);
TEST(inf.RawBits().CompareUnsigned(inf.ABS().RawBits()) == Ordering::Equal)(desc);
TEST(zero.Compare(inf) == Relation::Less)(desc);
TEST(minusZero.Compare(inf) == Relation::Less)(desc);
TEST(nan.Compare(inf) == Relation::Unordered)(desc);
TEST(inf.Compare(inf) == Relation::Equal)(desc);
R negInf{Word{maxExponent}.SHIFTL(significandBits).IOR(Word::MASKL(1))};
TEST(negInf.IsNegative())(desc);
TEST(!negInf.IsNotANumber())(desc);
TEST(negInf.IsInfinite())(desc);
TEST(!negInf.IsZero())(desc);
TEST(inf.RawBits().CompareUnsigned(negInf.ABS().RawBits()) == Ordering::Equal)(desc);
TEST(inf.RawBits().CompareUnsigned(negInf.Negate().RawBits()) == Ordering::Equal)(desc);
TEST(inf.Negate().RawBits().CompareUnsigned(negInf.RawBits()) == Ordering::Equal)(desc);
TEST(zero.Compare(negInf) == Relation::Greater)(desc);
TEST(minusZero.Compare(negInf) == Relation::Greater)(desc);
TEST(nan.Compare(negInf) == Relation::Unordered)(desc);
TEST(inf.Compare(negInf) == Relation::Greater)(desc);
TEST(negInf.Compare(negInf) == Relation::Equal)(desc);
for (std::uint64_t j{0}; j < 63; ++j) {
std::uint64_t x{1};
x <<= j;
Integer<64> ix{x};
MATCH(x, ix.ToUInt64())("%s,%d,0x%llx",desc,j,x);
vr = R::ConvertSigned(ix);
TEST(!vr.value.IsNegative())("%s,%d,0x%llx",desc,j,x);
TEST(!vr.value.IsNotANumber())("%s,%d,0x%llx",desc,j,x);
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);
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(0x7fffffffffffffff, ivf.value.ToUInt64())("%s,%d,0x%llx",desc,j,x);
} else {
MATCH(Fortran::evaluate::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(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>>();
return testing::Complete();
}