diff options
author | Siva Chandra Reddy <sivachandra@google.com> | 2020-06-02 14:04:57 -0700 |
---|---|---|
committer | Siva Chandra Reddy <sivachandra@google.com> | 2020-06-11 12:23:11 -0700 |
commit | 118c13c691a5b3b0c5760061a89d5ef7a319c15b (patch) | |
tree | 255b838742255c4c9f5b9e58e04710b86a7182a9 /libc/utils | |
parent | 269d843720382a8beafdf156cd01f9791faff66c (diff) | |
download | llvm-118c13c691a5b3b0c5760061a89d5ef7a319c15b.zip llvm-118c13c691a5b3b0c5760061a89d5ef7a319c15b.tar.gz llvm-118c13c691a5b3b0c5760061a89d5ef7a319c15b.tar.bz2 |
[libc] Add implementation of few floating point manipulation functions.
Implementations of copysign[f], frexp[f], logb[f], and modf[f] are added.
Reviewers: asteinhauser
Differential Revision: https://reviews.llvm.org/D81134
Diffstat (limited to 'libc/utils')
-rw-r--r-- | libc/utils/FPUtil/BitPatterns.h | 6 | ||||
-rw-r--r-- | libc/utils/FPUtil/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libc/utils/FPUtil/FloatOperations.h | 24 | ||||
-rw-r--r-- | libc/utils/FPUtil/ManipulationFunctions.h | 102 |
4 files changed, 123 insertions, 10 deletions
diff --git a/libc/utils/FPUtil/BitPatterns.h b/libc/utils/FPUtil/BitPatterns.h index 35c58a4..439ccbc 100644 --- a/libc/utils/FPUtil/BitPatterns.h +++ b/libc/utils/FPUtil/BitPatterns.h @@ -11,6 +11,12 @@ #include "FloatProperties.h" +#include <float.h> + +static_assert( + FLT_RADIX == 2, + "LLVM libc only supports radix 2 IEEE 754 floating point formats."); + namespace __llvm_libc { namespace fputil { diff --git a/libc/utils/FPUtil/CMakeLists.txt b/libc/utils/FPUtil/CMakeLists.txt index b50ede1..21013ee 100644 --- a/libc/utils/FPUtil/CMakeLists.txt +++ b/libc/utils/FPUtil/CMakeLists.txt @@ -4,6 +4,7 @@ add_header_library( BitPatterns.h FloatOperations.h FloatProperties.h + ManipulationFunctions.h DEPS libc.utils.CPP.standalone_cpp ) diff --git a/libc/utils/FPUtil/FloatOperations.h b/libc/utils/FPUtil/FloatOperations.h index d841237..b599aad 100644 --- a/libc/utils/FPUtil/FloatOperations.h +++ b/libc/utils/FPUtil/FloatOperations.h @@ -57,26 +57,30 @@ static inline int getExponent(T x) { return getExponentFromBits(valueAsBits(x)); } +template <typename BitsType> static inline bool bitsAreInf(BitsType bits) { + using FPType = typename FloatType<BitsType>::Type; + return ((bits & BitPatterns<FPType>::inf) == BitPatterns<FPType>::inf) && + ((bits & FloatProperties<FPType>::mantissaMask) == 0); +} + // 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 bitsAreInf(valueAsBits(x)); +} + +template <typename BitsType> static inline bool bitsAreNaN(BitsType bits) { + using FPType = typename FloatType<BitsType>::Type; + return ((bits & BitPatterns<FPType>::inf) == BitPatterns<FPType>::inf) && + ((bits & FloatProperties<FPType>::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 bitsAreNaN(valueAsBits(x)); } template <typename BitsType> static inline bool bitsAreInfOrNaN(BitsType bits) { diff --git a/libc/utils/FPUtil/ManipulationFunctions.h b/libc/utils/FPUtil/ManipulationFunctions.h new file mode 100644 index 0000000..a59c0a7 --- /dev/null +++ b/libc/utils/FPUtil/ManipulationFunctions.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 +// +//===----------------------------------------------------------------------===// + +#include "BitPatterns.h" +#include "FloatOperations.h" +#include "FloatProperties.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 { + +template <typename T, + cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0> +static inline T frexp(T x, int &exp) { + using Properties = FloatProperties<T>; + using BitsType = typename Properties::BitsType; + + auto bits = valueAsBits(x); + if (bitsAreInfOrNaN(bits)) + return x; + if (bitsAreZero(bits)) { + exp = 0; + return x; + } + + exp = getExponentFromBits(bits) + 1; + + static constexpr BitsType resultExponent = + Properties::exponentOffset - BitsType(1); + // Capture the sign and mantissa part. + bits &= (Properties::mantissaMask | Properties::signMask); + // Insert the new exponent. + bits |= (resultExponent << Properties::mantissaWidth); + + return valueFromBits(bits); +} + +template <typename T, + cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0> +static inline T modf(T x, T &iptr) { + auto bits = valueAsBits(x); + if (bitsAreZero(bits) || bitsAreNaN(bits)) { + iptr = x; + return x; + } else if (bitsAreInf(bits)) { + iptr = x; + return bits & FloatProperties<T>::signMask + ? valueFromBits(BitPatterns<T>::negZero) + : valueFromBits(BitPatterns<T>::zero); + } else { + iptr = trunc(x); + if (x == iptr) { + // If x is already an integer value, then return zero with the right + // sign. + return bits & FloatProperties<T>::signMask + ? valueFromBits(BitPatterns<T>::negZero) + : valueFromBits(BitPatterns<T>::zero); + } else { + return x - iptr; + } + } +} + +template <typename T, + cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0> +static inline T copysign(T x, T y) { + constexpr auto signMask = FloatProperties<T>::signMask; + auto xbits = valueAsBits(x); + auto ybits = valueAsBits(y); + return valueFromBits((xbits & ~signMask) | (ybits & signMask)); +} + +template <typename T, + cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0> +static inline T logb(T x) { + auto bits = valueAsBits(x); + if (bitsAreZero(bits)) { + // TODO(Floating point exception): Raise div-by-zero exception. + // TODO(errno): POSIX requires setting errno to ERANGE. + return valueFromBits(BitPatterns<T>::negInf); + } else if (bitsAreInf(bits)) { + return valueFromBits(BitPatterns<T>::inf); + } else if (bitsAreNaN(bits)) { + return x; + } else { + return getExponentFromBits(bits); + } +} + +} // namespace fputil +} // namespace __llvm_libc + +#endif // LLVM_LIBC_UTILS_FPUTIL_MANIPULATION_FUNCTIONS_H |