diff options
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 |