forked from OSchip/llvm-project
[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:
parent
321056b53c
commit
eb9ad7ef07
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -42,3 +42,12 @@ target_link_libraries(integer-test
|
|||
FortranEvaluate
|
||||
FortranEvaluateTesting
|
||||
)
|
||||
|
||||
add_executable(real-test
|
||||
real.cc
|
||||
)
|
||||
|
||||
target_link_libraries(real-test
|
||||
FortranEvaluate
|
||||
FortranEvaluateTesting
|
||||
)
|
||||
|
|
|
@ -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();
|
||||
}
|
Loading…
Reference in New Issue