diff options
author | Siva Chandra Reddy <sivachandra@google.com> | 2020-05-07 23:19:09 -0700 |
---|---|---|
committer | Siva Chandra Reddy <sivachandra@google.com> | 2020-05-15 11:08:41 -0700 |
commit | 32a22a423c71c8dc479cdbd5d6de98772431b10d (patch) | |
tree | ad7f614fe9d9bda9106eea2b743aa9736c7afabd /libc/utils | |
parent | e36223c85cd49858a808a2420144b64cad37839f (diff) | |
download | llvm-32a22a423c71c8dc479cdbd5d6de98772431b10d.zip llvm-32a22a423c71c8dc479cdbd5d6de98772431b10d.tar.gz llvm-32a22a423c71c8dc479cdbd5d6de98772431b10d.tar.bz2 |
[libc] Consolidate floating point utils into a single utils library.
A new utils library named 'fputil' is added. This library is used in
math tests and the MPFR wrapper. The math implementations will be
modified to use this library in a later round.
Reviewers: phosek
Differential Revision: https://reviews.llvm.org/D79724
Diffstat (limited to 'libc/utils')
-rw-r--r-- | libc/utils/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libc/utils/FPUtil/BitPatterns.h | 62 | ||||
-rw-r--r-- | libc/utils/FPUtil/CMakeLists.txt | 9 | ||||
-rw-r--r-- | libc/utils/FPUtil/FloatOperations.h | 102 | ||||
-rw-r--r-- | libc/utils/FPUtil/FloatProperties.h | 72 | ||||
-rw-r--r-- | libc/utils/MPFRWrapper/CMakeLists.txt | 2 | ||||
-rw-r--r-- | libc/utils/MPFRWrapper/MPFRUtils.cpp | 49 |
7 files changed, 255 insertions, 42 deletions
diff --git a/libc/utils/CMakeLists.txt b/libc/utils/CMakeLists.txt index 1e85d05..8a7ee53 100644 --- a/libc/utils/CMakeLists.txt +++ b/libc/utils/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(CPP) +add_subdirectory(FPUtil) add_subdirectory(HdrGen) add_subdirectory(MPFRWrapper) add_subdirectory(testutils) diff --git a/libc/utils/FPUtil/BitPatterns.h b/libc/utils/FPUtil/BitPatterns.h new file mode 100644 index 0000000..35c58a4 --- /dev/null +++ b/libc/utils/FPUtil/BitPatterns.h @@ -0,0 +1,62 @@ +//===-- Bit patterns of common floating point numbers -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_UTILS_FPUTIL_BIT_PATTERNS_H +#define LLVM_LIBC_UTILS_FPUTIL_BIT_PATTERNS_H + +#include "FloatProperties.h" + +namespace __llvm_libc { +namespace fputil { + +template <typename T> struct BitPatterns {}; + +template <> struct BitPatterns<float> { + using BitsType = FloatProperties<float>::BitsType; + + static constexpr BitsType inf = 0x7f800000U; + static constexpr BitsType negInf = 0xff800000U; + + static constexpr BitsType zero = 0x0; + static constexpr BitsType negZero = 0x80000000U; + + static constexpr BitsType one = 0x3f800000U; + + // Examples of quiet NAN. + static constexpr BitsType aQuietNaN = 0x7fc00000U; + static constexpr BitsType aNegativeQuietNaN = 0xffc00000U; + + // Examples of signalling NAN. + static constexpr BitsType aSignallingNaN = 0x7f800001U; + static constexpr BitsType aNegativeSignallingNaN = 0xff800001U; +}; + +template <> struct BitPatterns<double> { + using BitsType = FloatProperties<double>::BitsType; + + static constexpr BitsType inf = 0x7ff0000000000000ULL; + static constexpr BitsType negInf = 0xfff0000000000000ULL; + + static constexpr BitsType zero = 0x0ULL; + static constexpr BitsType negZero = 0x8000000000000000ULL; + + static constexpr BitsType one = 0x3FF0000000000000ULL; + + // Examples of quiet NAN. + static constexpr BitsType aQuietNaN = 0x7ff8000000000000ULL; + static constexpr BitsType aNegativeQuietNaN = 0xfff8000000000000ULL; + + // Examples of signalling NAN. + static constexpr BitsType aSignallingNaN = 0x7ff0000000000001ULL; + static constexpr BitsType aNegativeSignallingNaN = 0xfff0000000000001ULL; +}; + +} // namespace fputil +} // namespace __llvm_libc + +#endif // LLVM_LIBC_UTILS_FPUTIL_BIT_PATTERNS_H diff --git a/libc/utils/FPUtil/CMakeLists.txt b/libc/utils/FPUtil/CMakeLists.txt new file mode 100644 index 0000000..b50ede1 --- /dev/null +++ b/libc/utils/FPUtil/CMakeLists.txt @@ -0,0 +1,9 @@ +add_header_library( + fputil + HDRS + BitPatterns.h + FloatOperations.h + FloatProperties.h + DEPS + libc.utils.CPP.standalone_cpp +) diff --git a/libc/utils/FPUtil/FloatOperations.h b/libc/utils/FPUtil/FloatOperations.h new file mode 100644 index 0000000..902929e --- /dev/null +++ b/libc/utils/FPUtil/FloatOperations.h @@ -0,0 +1,102 @@ +//===-- Common operations on floating point numbers -------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_UTILS_FPUTIL_FLOAT_OPERATIONS_H +#define LLVM_LIBC_UTILS_FPUTIL_FLOAT_OPERATIONS_H + +#include "BitPatterns.h" +#include "FloatProperties.h" + +#include "utils/CPP/TypeTraits.h" + +namespace __llvm_libc { +namespace fputil { + +// Return the bits of a float value. +template <typename T, + cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0> +static inline typename FloatProperties<T>::BitsType valueAsBits(T x) { + using BitsType = typename FloatProperties<T>::BitsType; + return *reinterpret_cast<BitsType *>(&x); +} + +// Return the float value from bits. +template <typename BitsType, + cpp::EnableIfType< + cpp::IsFloatingPointType<FloatTypeT<BitsType>>::Value, int> = 0> +static inline FloatTypeT<BitsType> valueFromBits(BitsType bits) { + return *reinterpret_cast<FloatTypeT<BitsType> *>(&bits); +} + +// Return the bits of abs(x). +template <typename T, + cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0> +static inline typename FloatProperties<T>::BitsType absBits(T x) { + return valueAsBits(x) & (~FloatProperties<T>::signMask); +} + +// Return the zero adjusted exponent value of x. +template <typename T, + cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0> +int getExponent(T x) { + using Properties = FloatProperties<T>; + using BitsType = typename Properties::BitsType; + BitsType bits = absBits(x); + int e = (bits >> Properties::mantissaWidth); // Shift out the mantissa. + e -= Properties::exponentOffset; // Zero adjust. + return e; +} + +// Return true if x is infinity (positive or negative.) +template <typename T, + cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0> +static inline bool isInf(T x) { + using Properties = FloatProperties<T>; + using BitsType = typename FloatProperties<T>::BitsType; + BitsType bits = valueAsBits(x); + return ((bits & BitPatterns<T>::inf) == BitPatterns<T>::inf) && + ((bits & Properties::mantissaMask) == 0); +} + +// Return true if x is a NAN (quiet or signalling.) +template <typename T, + cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0> +static inline bool isNaN(T x) { + using Properties = FloatProperties<T>; + using BitsType = typename FloatProperties<T>::BitsType; + BitsType bits = valueAsBits(x); + return ((bits & BitPatterns<T>::inf) == BitPatterns<T>::inf) && + ((bits & Properties::mantissaMask) != 0); +} + +// Return true if x is a quiet NAN. +template <typename T, + cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0> +static inline bool isQuietNaN(T x) { + using Properties = FloatProperties<T>; + using BitsType = typename FloatProperties<T>::BitsType; + BitsType bits = valueAsBits(x); + return ((bits & BitPatterns<T>::inf) == BitPatterns<T>::inf) && + ((bits & Properties::quietNaNMask) != 0); +} + +// Return true if x is a quiet NAN with sign bit set. +template <typename T, + cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0> +static inline bool isNegativeQuietNaN(T x) { + using Properties = FloatProperties<T>; + using BitsType = typename FloatProperties<T>::BitsType; + BitsType bits = valueAsBits(x); + return ((bits & BitPatterns<T>::negInf) == BitPatterns<T>::negInf) && + ((bits & Properties::quietNaNMask) != 0); +} + +} // namespace fputil +} // namespace __llvm_libc + +#endif // LLVM_LIBC_UTILS_FPUTIL_FLOAT_OPERATIONS_H diff --git a/libc/utils/FPUtil/FloatProperties.h b/libc/utils/FPUtil/FloatProperties.h new file mode 100644 index 0000000..a9584c7 --- /dev/null +++ b/libc/utils/FPUtil/FloatProperties.h @@ -0,0 +1,72 @@ +//===-- Properties of floating point numbers --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_UTILS_FPUTIL_FLOAT_PROPERTIES_H +#define LLVM_LIBC_UTILS_FPUTIL_FLOAT_PROPERTIES_H + +#include <stdint.h> + +namespace __llvm_libc { +namespace fputil { + +template <typename T> struct FloatProperties {}; + +template <> struct FloatProperties<float> { + typedef uint32_t BitsType; + static_assert(sizeof(BitsType) == sizeof(float), + "Unexpected size of 'float' type."); + + static constexpr uint32_t mantissaWidth = 23; + static constexpr BitsType mantissaMask = 0x007fffffU; + static constexpr BitsType signMask = 0x80000000U; + static constexpr uint32_t exponentOffset = 127; + + // If a number x is a NAN, then it is a quiet NAN if: + // QuietNaNMask & bits(x) != 0 + // Else, it is a signalling NAN. + static constexpr BitsType quietNaNMask = 0x00400000U; +}; + +template <> struct FloatProperties<double> { + typedef uint64_t BitsType; + static_assert(sizeof(BitsType) == sizeof(double), + "Unexpected size of 'double' type."); + + static constexpr uint32_t mantissaWidth = 52; + static constexpr BitsType mantissaMask = 0x000fffffffffffffU; + static constexpr BitsType signMask = 0x8000000000000000ULL; + static constexpr uint32_t exponentOffset = 1023; + + // If a number x is a NAN, then it is a quiet NAN if: + // QuietNaNMask & bits(x) != 0 + // Else, it is a signalling NAN. + static constexpr BitsType quietNaNMask = 0x0008000000000000ULL; +}; + +// Define the float type corresponding to the BitsType. +template <typename BitsType> struct FloatType; + +template <> struct FloatType<uint32_t> { + static_assert(sizeof(uint32_t) == sizeof(float), + "Unexpected size of 'float' type."); + typedef float Type; +}; + +template <> struct FloatType<uint64_t> { + static_assert(sizeof(uint64_t) == sizeof(double), + "Unexpected size of 'double' type."); + typedef double Type; +}; + +template <typename BitsType> +using FloatTypeT = typename FloatType<BitsType>::Type; + +} // namespace fputil +} // namespace __llvm_libc + +#endif // LLVM_LIBC_UTILS_FPUTIL_FLOAT_PROPERTIES_H diff --git a/libc/utils/MPFRWrapper/CMakeLists.txt b/libc/utils/MPFRWrapper/CMakeLists.txt index 218d5af..6a3c24e 100644 --- a/libc/utils/MPFRWrapper/CMakeLists.txt +++ b/libc/utils/MPFRWrapper/CMakeLists.txt @@ -12,7 +12,7 @@ if(LIBC_TESTS_CAN_USE_MPFR) MPFRUtils.cpp MPFRUtils.h ) - add_dependencies(libcMPFRWrapper libc.utils.CPP.standalone_cpp LibcUnitTest LLVMSupport) + add_dependencies(libcMPFRWrapper libc.utils.CPP.standalone_cpp libc.utils.FPUtil.fputil LibcUnitTest LLVMSupport) target_link_libraries(libcMPFRWrapper -lmpfr -lgmp LibcUnitTest LLVMSupport) else() message(WARNING "Math tests using MPFR will be skipped.") diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp index 980557a..74bb07a 100644 --- a/libc/utils/MPFRWrapper/MPFRUtils.cpp +++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp @@ -8,6 +8,8 @@ #include "MPFRUtils.h" +#include "utils/FPUtil/FloatOperations.h" + #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" @@ -19,44 +21,6 @@ namespace __llvm_libc { namespace testing { namespace mpfr { -template <typename T> struct FloatProperties {}; - -template <> struct FloatProperties<float> { - typedef uint32_t BitsType; - static_assert(sizeof(BitsType) == sizeof(float), - "Unexpected size of 'float' type."); - - static constexpr uint32_t mantissaWidth = 23; - static constexpr BitsType signMask = 0x7FFFFFFFU; - static constexpr uint32_t exponentOffset = 127; -}; - -template <> struct FloatProperties<double> { - typedef uint64_t BitsType; - static_assert(sizeof(BitsType) == sizeof(double), - "Unexpected size of 'double' type."); - - static constexpr uint32_t mantissaWidth = 52; - static constexpr BitsType signMask = 0x7FFFFFFFFFFFFFFFULL; - static constexpr uint32_t exponentOffset = 1023; -}; - -template <typename T> typename FloatProperties<T>::BitsType getBits(T x) { - using BitsType = typename FloatProperties<T>::BitsType; - return *reinterpret_cast<BitsType *>(&x); -} - -// Returns the zero adjusted exponent value of abs(x). -template <typename T> int getExponent(T x) { - using Properties = FloatProperties<T>; - using BitsType = typename Properties::BitsType; - BitsType bits = *reinterpret_cast<BitsType *>(&x); - bits &= Properties::signMask; // Zero the sign bit. - int e = (bits >> Properties::mantissaWidth); // Shift out the mantissa. - e -= Properties::exponentOffset; // Zero adjust. - return e; -} - class MPFRNumber { // A precision value which allows sufficiently large additional // precision even compared to double precision floating point values. @@ -94,7 +58,7 @@ public: template <typename XType> MPFRNumber(XType x, const Tolerance &t) { mpfr_init2(value, mpfrPrecision); mpfr_set_zero(value, 1); // Set to positive zero. - MPFRNumber xExponent(getExponent(x)); + MPFRNumber xExponent(fputil::getExponent(x)); // E = 2^E mpfr_exp2(xExponent.value, xExponent.value, MPFR_RNDN); uint32_t bitMask = 1 << (t.width - 1); @@ -170,15 +134,18 @@ namespace internal { template <typename T> void MPFRMatcher<T>::explainError(testutils::StreamWrapper &OS) { + using fputil::valueAsBits; + MPFRNumber mpfrResult(operation, input); MPFRNumber mpfrInput(input); MPFRNumber mpfrMatchValue(matchValue); MPFRNumber mpfrToleranceValue(matchValue, tolerance); OS << "Match value not within tolerance value of MPFR result:\n" << " Input decimal: " << mpfrInput.str() << '\n' - << " Input bits: 0x" << llvm::utohexstr(getBits(input)) << '\n' + << " Input bits: 0x" << llvm::utohexstr(valueAsBits(input)) << '\n' << " Match decimal: " << mpfrMatchValue.str() << '\n' - << " Match bits: 0x" << llvm::utohexstr(getBits(matchValue)) << '\n' + << " Match bits: 0x" << llvm::utohexstr(valueAsBits(matchValue)) + << '\n' << " MPFR result: " << mpfrResult.str() << '\n' << "Tolerance value: " << mpfrToleranceValue.str() << '\n'; } |