forked from OSchip/llvm-project
[flang] Begin adding tests
Original-commit: flang-compiler/f18@8776d8b663 Reviewed-on: https://github.com/flang-compiler/f18/pull/671 Tree-same-pre-rewrite: false
This commit is contained in:
parent
9cdb101a4d
commit
afda616c31
|
@ -43,10 +43,11 @@ static constexpr std::uint64_t TenToThe(int power) {
|
|||
// even, so that pairs of decimal digits do not straddle Digits.
|
||||
// So LOG10RADIX must be 16 or 6.
|
||||
template<int PREC, int LOG10RADIX = 16> class BigRadixFloatingPointNumber {
|
||||
private:
|
||||
public:
|
||||
using Real = BinaryFloatingPointNumber<PREC>;
|
||||
|
||||
static constexpr int log10Radix{LOG10RADIX};
|
||||
|
||||
private:
|
||||
static constexpr std::uint64_t uint64Radix{TenToThe(log10Radix)};
|
||||
static constexpr int minDigitBits{
|
||||
64 - common::LeadingZeroBitCount(uint64Radix)};
|
||||
|
@ -103,8 +104,8 @@ public:
|
|||
|
||||
private:
|
||||
BigRadixFloatingPointNumber(const BigRadixFloatingPointNumber &that)
|
||||
: digits_{that.digits_}, exponent_{that.exponent_}, isNegative_{
|
||||
that.isNegative_} {
|
||||
: digits_{that.digits_}, exponent_{that.exponent_},
|
||||
isNegative_{that.isNegative_}, rounding_{that.rounding_} {
|
||||
for (int j{0}; j < digits_; ++j) {
|
||||
digit_[j] = that.digit_[j];
|
||||
}
|
||||
|
|
|
@ -21,13 +21,14 @@ template<int PREC, int LOG10RADIX>
|
|||
BigRadixFloatingPointNumber<PREC, LOG10RADIX>::BigRadixFloatingPointNumber(
|
||||
BinaryFloatingPointNumber<PREC> x, enum FortranRounding rounding)
|
||||
: rounding_{rounding} {
|
||||
if (x.IsNegative() < 0) {
|
||||
isNegative_ = true;
|
||||
x.Negate();
|
||||
}
|
||||
bool negative{x.IsNegative()};
|
||||
if (x.IsZero()) {
|
||||
isNegative_ = negative;
|
||||
return;
|
||||
}
|
||||
if (negative) {
|
||||
x.Negate();
|
||||
}
|
||||
int twoPow{x.UnbiasedExponent()};
|
||||
twoPow -= x.bits - 1;
|
||||
if (!x.implicitMSB) {
|
||||
|
@ -44,6 +45,7 @@ BigRadixFloatingPointNumber<PREC, LOG10RADIX>::BigRadixFloatingPointNumber(
|
|||
auto word{x.Fraction()};
|
||||
word <<= lshift;
|
||||
SetTo(word);
|
||||
isNegative_ = negative;
|
||||
|
||||
// The significand is now encoded in *this as an integer (D) and
|
||||
// decimal exponent (E): x = D * 10.**E * 2.**twoPow
|
||||
|
@ -297,9 +299,9 @@ ConversionToDecimalResult ConvertToDecimal(char *buffer, size_t size, int flags,
|
|||
if (x.IsNaN()) {
|
||||
return {"NaN", 3, 0, Invalid};
|
||||
} else if (x.IsInfinite()) {
|
||||
return {x.IsNegative() ? "-Inf" : "+Inf", 4, 0, Exact};
|
||||
return {x.IsNegative() ? "-Inf" : (flags & AlwaysSign) ? "+Inf" : "Inf", 4,
|
||||
0, Exact};
|
||||
} else {
|
||||
using Binary = BinaryFloatingPointNumber<PREC>;
|
||||
using Big = BigRadixFloatingPointNumber<PREC>;
|
||||
Big number{x, rounding};
|
||||
if ((flags & Minimize) && !x.IsZero()) {
|
||||
|
@ -311,6 +313,7 @@ ConversionToDecimalResult ConvertToDecimal(char *buffer, size_t size, int flags,
|
|||
// the bounds of the range of decimal values that will map back to the
|
||||
// original binary value, and find a (not necessary unique) shortest
|
||||
// decimal sequence in that range.
|
||||
using Binary = typename Big::Real;
|
||||
Binary less{x};
|
||||
--less.raw;
|
||||
Binary more{x};
|
||||
|
|
|
@ -409,3 +409,26 @@ template ConversionToBinaryResult<112> ConvertToBinary<112>(
|
|||
const char *&, enum FortranRounding);
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
ConversionResultFlags ConvertDecimalToFloat(
|
||||
const char **p, float *f, enum FortranRounding rounding) {
|
||||
auto result{Fortran::decimal::ConvertToBinary<24>(*p, rounding)};
|
||||
*f = *reinterpret_cast<const float *>(&result.binary);
|
||||
return result.flags;
|
||||
}
|
||||
ConversionResultFlags ConvertDecimalToDouble(
|
||||
const char **p, double *d, enum FortranRounding rounding) {
|
||||
auto result{Fortran::decimal::ConvertToBinary<53>(*p, rounding)};
|
||||
*d = *reinterpret_cast<const double *>(&result.binary);
|
||||
return result.flags;
|
||||
}
|
||||
#if __x86_64__
|
||||
ConversionResultFlags ConvertDecimalToLongDouble(
|
||||
const char **p, long double *ld, enum FortranRounding rounding) {
|
||||
auto result{Fortran::decimal::ConvertToBinary<64>(*p, rounding)};
|
||||
*ld = *reinterpret_cast<const long double *>(&result.binary);
|
||||
return result.flags;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -67,22 +67,28 @@ enum DecimalConversionFlags {
|
|||
namespace Fortran::decimal {
|
||||
|
||||
template<int PREC>
|
||||
ConversionToDecimalResult ConvertToDecimal(char *, size_t, int flags,
|
||||
int digits, enum FortranRounding rounding,
|
||||
BinaryFloatingPointNumber<PREC> x);
|
||||
ConversionToDecimalResult ConvertToDecimal(char *, size_t,
|
||||
enum DecimalConversionFlags flags, int digits,
|
||||
enum FortranRounding rounding, BinaryFloatingPointNumber<PREC> x);
|
||||
|
||||
extern template ConversionToDecimalResult ConvertToDecimal<8>(char *, size_t,
|
||||
int, int, enum FortranRounding, BinaryFloatingPointNumber<8>);
|
||||
enum DecimalConversionFlags, int, enum FortranRounding,
|
||||
BinaryFloatingPointNumber<8>);
|
||||
extern template ConversionToDecimalResult ConvertToDecimal<11>(char *, size_t,
|
||||
int, int, enum FortranRounding, BinaryFloatingPointNumber<11>);
|
||||
enum DecimalConversionFlags, int, enum FortranRounding,
|
||||
BinaryFloatingPointNumber<11>);
|
||||
extern template ConversionToDecimalResult ConvertToDecimal<24>(char *, size_t,
|
||||
int, int, enum FortranRounding, BinaryFloatingPointNumber<24>);
|
||||
enum DecimalConversionFlags, int, enum FortranRounding,
|
||||
BinaryFloatingPointNumber<24>);
|
||||
extern template ConversionToDecimalResult ConvertToDecimal<53>(char *, size_t,
|
||||
int, int, enum FortranRounding, BinaryFloatingPointNumber<53>);
|
||||
enum DecimalConversionFlags, int, enum FortranRounding,
|
||||
BinaryFloatingPointNumber<53>);
|
||||
extern template ConversionToDecimalResult ConvertToDecimal<64>(char *, size_t,
|
||||
int, int, enum FortranRounding, BinaryFloatingPointNumber<64>);
|
||||
enum DecimalConversionFlags, int, enum FortranRounding,
|
||||
BinaryFloatingPointNumber<64>);
|
||||
extern template ConversionToDecimalResult ConvertToDecimal<112>(char *, size_t,
|
||||
int, int, enum FortranRounding, BinaryFloatingPointNumber<112>);
|
||||
enum DecimalConversionFlags, int, enum FortranRounding,
|
||||
BinaryFloatingPointNumber<112>);
|
||||
|
||||
template<int PREC> struct ConversionToBinaryResult {
|
||||
BinaryFloatingPointNumber<PREC> binary;
|
||||
|
@ -105,7 +111,7 @@ extern template ConversionToBinaryResult<64> ConvertToBinary<64>(
|
|||
const char *&, enum FortranRounding = RoundNearest);
|
||||
extern template ConversionToBinaryResult<112> ConvertToBinary<112>(
|
||||
const char *&, enum FortranRounding = RoundNearest);
|
||||
} // namespace
|
||||
}
|
||||
extern "C" {
|
||||
#endif /* C++ */
|
||||
|
||||
|
@ -118,7 +124,16 @@ ConversionToDecimalResult ConvertLongDoubleToDecimal(
|
|||
char *, size_t, int flags, int digits, enum FortranRounding, long double);
|
||||
#endif
|
||||
|
||||
ConversionResultFlags ConvertDecimalToFloat(
|
||||
const char **, float *, enum FortranRounding);
|
||||
ConversionResultFlags ConvertDecimalToDouble(
|
||||
const char **, double *, enum FortranRounding);
|
||||
#if __x86_64__
|
||||
ConversionResultFlags ConvertDecimalToLongDouble(
|
||||
const char **, long double *, enum FortranRounding);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* C++ */
|
||||
#endif /* DECIMAL_H_ */
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright (c) 2018-2019, 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.
|
||||
|
@ -12,5 +12,6 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
add_subdirectory(decimal)
|
||||
add_subdirectory(evaluate)
|
||||
add_subdirectory(semantics)
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
# Copyright (c) 2019, 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.
|
||||
|
||||
add_executable(quick-sanity-test
|
||||
quick-sanity-test.cc
|
||||
)
|
||||
|
||||
target_link_libraries(quick-sanity-test
|
||||
FortranDecimal
|
||||
)
|
||||
|
||||
# add_executable(thorough-test
|
||||
# thorough-test.cc
|
||||
# )
|
||||
|
||||
# target_link_libraries(thorough-test
|
||||
# FortranDecimal
|
||||
# )
|
||||
|
||||
# add_executable(benchmark01
|
||||
# benchmark01.cc
|
||||
# )
|
||||
|
||||
# target_link_libraries(benchmark01
|
||||
# FortranDecimal
|
||||
# )
|
||||
|
||||
add_test(Sanity quick-sanity-test)
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright (c) 2019, 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/decimal/decimal.h"
|
||||
#include <cinttypes>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
static int tests{0};
|
||||
static int fails{0};
|
||||
|
||||
std::ostream &failed(float x) {
|
||||
++fails;
|
||||
return std::cout << "FAIL: 0x" << std::hex
|
||||
<< *reinterpret_cast<std::uint32_t *>(&x) << std::dec;
|
||||
}
|
||||
|
||||
void testDirect(float x, const char *expect, int expectExpo) {
|
||||
char buffer[1024];
|
||||
++tests;
|
||||
auto result{ConvertFloatToDecimal(buffer, sizeof buffer,
|
||||
static_cast<enum DecimalConversionFlags>(0), 1024,
|
||||
RoundNearest, x)};
|
||||
if (result.str == nullptr) {
|
||||
failed(x) << ": no result str\n";
|
||||
} else if (std::strcmp(result.str, expect) != 0) {
|
||||
failed(x) << ": expect '" << expect << "', got '" << result.str << "'\n";
|
||||
} else if (result.decimalExponent != expectExpo) {
|
||||
failed(x) << ": expect exponent " << expectExpo << ", got "
|
||||
<< result.decimalExponent << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
void testReadback(float x) {
|
||||
char buffer[1024];
|
||||
++tests;
|
||||
auto result{ConvertFloatToDecimal(buffer, sizeof buffer,
|
||||
static_cast<enum DecimalConversionFlags>(0), 1024,
|
||||
RoundNearest, x)};
|
||||
if (result.str == nullptr) {
|
||||
failed(x) << ": no result str\n";
|
||||
} else {
|
||||
float y{0};
|
||||
char *q{const_cast<char *>(result.str)};
|
||||
std::sprintf(q + result.length, "e%d", static_cast<int>(result.decimalExponent - result.length));
|
||||
const char *p{q};
|
||||
auto flags{ConvertDecimalToFloat(&p, &y, RoundNearest)};
|
||||
if (x != y || *p != '\0' || (flags & Invalid)) {
|
||||
failed(x) << ": -> '" << buffer << "' -> 0x"
|
||||
<< std::hex << *reinterpret_cast<std::uint32_t *>(&y)
|
||||
<< std::dec << " '" << p << "'\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
testDirect(-1.0, "-1", 1);
|
||||
testDirect(0.0, "0", 0);
|
||||
testDirect(1.0, "1", 1);
|
||||
testDirect(2.0, "2", 1);
|
||||
testDirect(-1.0, "-1", 1);
|
||||
testDirect(314159, "314159", 6);
|
||||
testDirect(0.0625, "625", -1);
|
||||
float x;
|
||||
std::uint32_t *ix{reinterpret_cast<std::uint32_t *>(&x)};
|
||||
*ix = 0x80000000;
|
||||
testDirect(x, "-0", 0);
|
||||
*ix = 0x7f800000;
|
||||
testDirect(x, "Inf", 0);
|
||||
*ix = 0xff800000;
|
||||
testDirect(x, "-Inf", 0);
|
||||
*ix = 0xffffffff;
|
||||
testDirect(x, "NaN", 0);
|
||||
std::cout << tests << " tests run, " << fails << " tests failed\n";
|
||||
return fails > 0;
|
||||
}
|
Loading…
Reference in New Issue