aboutsummaryrefslogtreecommitdiff
path: root/libc/utils
diff options
context:
space:
mode:
authorSiva Chandra Reddy <sivachandra@google.com>2020-05-07 23:19:09 -0700
committerSiva Chandra Reddy <sivachandra@google.com>2020-05-15 11:08:41 -0700
commit32a22a423c71c8dc479cdbd5d6de98772431b10d (patch)
treead7f614fe9d9bda9106eea2b743aa9736c7afabd /libc/utils
parente36223c85cd49858a808a2420144b64cad37839f (diff)
downloadllvm-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.txt1
-rw-r--r--libc/utils/FPUtil/BitPatterns.h62
-rw-r--r--libc/utils/FPUtil/CMakeLists.txt9
-rw-r--r--libc/utils/FPUtil/FloatOperations.h102
-rw-r--r--libc/utils/FPUtil/FloatProperties.h72
-rw-r--r--libc/utils/MPFRWrapper/CMakeLists.txt2
-rw-r--r--libc/utils/MPFRWrapper/MPFRUtils.cpp49
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';
}