aboutsummaryrefslogtreecommitdiff
path: root/libc/utils/FPUtil/ManipulationFunctions.h
diff options
context:
space:
mode:
authorSiva Chandra Reddy <sivachandra@google.com>2020-08-19 01:08:03 -0700
committerSiva Chandra Reddy <sivachandra@google.com>2020-08-20 09:00:35 -0700
commit87bf0b0ee986078a2c9e9bca02cf7a4c42012925 (patch)
tree5c2805a2c73319a39bbf47d538c032eda2cf228c /libc/utils/FPUtil/ManipulationFunctions.h
parent4aaf77254296a3dddbbca416c5adfc3c6d63a0e7 (diff)
downloadllvm-87bf0b0ee986078a2c9e9bca02cf7a4c42012925.zip
llvm-87bf0b0ee986078a2c9e9bca02cf7a4c42012925.tar.gz
llvm-87bf0b0ee986078a2c9e9bca02cf7a4c42012925.tar.bz2
[libc] Add a class called NormalFloat which represents normalized floats.
This class helps in dealing with normal and subnormal numbers uniformly. Moreover, since this class has been designed to handle all floating formats across platforms, it helps implement floating point functions in a uniform manner. The implementations of frexp and logb have been switched to use this new class as it allows us to use just one implementation across all different floating point formats. Reviewed By: lntue Differential Revision: https://reviews.llvm.org/D86241
Diffstat (limited to 'libc/utils/FPUtil/ManipulationFunctions.h')
-rw-r--r--libc/utils/FPUtil/ManipulationFunctions.h111
1 files changed, 14 insertions, 97 deletions
diff --git a/libc/utils/FPUtil/ManipulationFunctions.h b/libc/utils/FPUtil/ManipulationFunctions.h
index ce5400f..f233fcd 100644
--- a/libc/utils/FPUtil/ManipulationFunctions.h
+++ b/libc/utils/FPUtil/ManipulationFunctions.h
@@ -6,37 +6,20 @@
//
//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_UTILS_FPUTIL_MANIPULATION_FUNCTIONS_H
+#define LLVM_LIBC_UTILS_FPUTIL_MANIPULATION_FUNCTIONS_H
+
#include "FPBits.h"
#include "NearestIntegerOperations.h"
+#include "NormalFloat.h"
#include "utils/CPP/TypeTraits.h"
-#ifndef LLVM_LIBC_UTILS_FPUTIL_MANIPULATION_FUNCTIONS_H
-#define LLVM_LIBC_UTILS_FPUTIL_MANIPULATION_FUNCTIONS_H
-
namespace __llvm_libc {
namespace fputil {
-#if defined(__x86_64__) || defined(__i386__)
-template <typename T> struct Standard754Type {
- static constexpr bool Value =
- cpp::IsSame<float, cpp::RemoveCVType<T>>::Value ||
- cpp::IsSame<double, cpp::RemoveCVType<T>>::Value;
-};
-#else
-template <typename T> struct Standard754Type {
- static constexpr bool Value = cpp::IsFloatingPointType<T>::Value;
-};
-#endif
-
-template <typename T> static inline T frexp_impl(FPBits<T> &bits, int &exp) {
- exp = bits.getExponent() + 1;
- static constexpr uint16_t resultExponent = FPBits<T>::exponentBias - 1;
- bits.exponent = resultExponent;
- return bits;
-}
-
-template <typename T, cpp::EnableIfType<Standard754Type<T>::Value, int> = 0>
+template <typename T,
+ cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
static inline T frexp(T x, int &exp) {
FPBits<T> bits(x);
if (bits.isInfOrNaN())
@@ -46,42 +29,12 @@ static inline T frexp(T x, int &exp) {
return x;
}
- return frexp_impl(bits, exp);
+ NormalFloat<T> normal(bits);
+ exp = normal.exponent + 1;
+ normal.exponent = -1;
+ return normal;
}
-#if defined(__x86_64__) || defined(__i386__)
-static inline long double frexp(long double x, int &exp) {
- FPBits<long double> bits(x);
- if (bits.isInfOrNaN())
- return x;
- if (bits.isZero()) {
- exp = 0;
- return x;
- }
-
- if (bits.exponent != 0 || bits.implicitBit == 1)
- return frexp_impl(bits, exp);
-
- exp = bits.getExponent();
- int shiftCount = 0;
- uint64_t fullMantissa = *reinterpret_cast<uint64_t *>(&bits);
- static constexpr uint64_t msBitMask = uint64_t(1) << 63;
- for (; (fullMantissa & msBitMask) == uint64_t(0);
- fullMantissa <<= 1, ++shiftCount) {
- // This for loop will terminate as fullMantissa is != 0. If it were 0,
- // then x will be NaN and handled before control reaches here.
- // When the loop terminates, fullMantissa will represent the full mantissa
- // of a normal long double value. That is, the implicit bit has the value
- // of 1.
- }
-
- exp = exp - shiftCount + 1;
- *reinterpret_cast<uint64_t *>(&bits) = fullMantissa;
- bits.exponent = FPBits<long double>::exponentBias - 1;
- return bits;
-}
-#endif
-
template <typename T,
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
static inline T modf(T x, T &iptr) {
@@ -112,11 +65,8 @@ static inline T copysign(T x, T y) {
return xbits;
}
-template <typename T> static inline T logb_impl(const FPBits<T> &bits) {
- return bits.getExponent();
-}
-
-template <typename T, cpp::EnableIfType<Standard754Type<T>::Value, int> = 0>
+template <typename T,
+ cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
static inline T logb(T x) {
FPBits<T> bits(x);
if (bits.isZero()) {
@@ -130,42 +80,9 @@ static inline T logb(T x) {
return FPBits<T>::inf();
}
- return logb_impl(bits);
-}
-
-#if defined(__x86_64__) || defined(__i386__)
-static inline long double logb(long double x) {
- FPBits<long double> bits(x);
- if (bits.isZero()) {
- // TODO(Floating point exception): Raise div-by-zero exception.
- // TODO(errno): POSIX requires setting errno to ERANGE.
- return FPBits<long double>::negInf();
- } else if (bits.isNaN()) {
- return x;
- } else if (bits.isInf()) {
- // Return positive infinity.
- return FPBits<long double>::inf();
- }
-
- if (bits.exponent != 0 || bits.implicitBit == 1)
- return logb_impl(bits);
-
- int exp = bits.getExponent();
- int shiftCount = 0;
- uint64_t fullMantissa = *reinterpret_cast<uint64_t *>(&bits);
- static constexpr uint64_t msBitMask = uint64_t(1) << 63;
- for (; (fullMantissa & msBitMask) == uint64_t(0);
- fullMantissa <<= 1, ++shiftCount) {
- // This for loop will terminate as fullMantissa is != 0. If it were 0,
- // then x will be NaN and handled before control reaches here.
- // When the loop terminates, fullMantissa will represent the full mantissa
- // of a normal long double value. That is, the implicit bit has the value
- // of 1.
- }
-
- return exp - shiftCount;
+ NormalFloat<T> normal(bits);
+ return normal.exponent;
}
-#endif
} // namespace fputil
} // namespace __llvm_libc