diff options
author | Siva Chandra Reddy <sivachandra@google.com> | 2020-08-19 01:08:03 -0700 |
---|---|---|
committer | Siva Chandra Reddy <sivachandra@google.com> | 2020-08-20 09:00:35 -0700 |
commit | 87bf0b0ee986078a2c9e9bca02cf7a4c42012925 (patch) | |
tree | 5c2805a2c73319a39bbf47d538c032eda2cf228c /libc/utils/FPUtil/ManipulationFunctions.h | |
parent | 4aaf77254296a3dddbbca416c5adfc3c6d63a0e7 (diff) | |
download | llvm-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.h | 111 |
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 |