aboutsummaryrefslogtreecommitdiff
path: root/libc/utils
diff options
context:
space:
mode:
authorSiva Chandra Reddy <sivachandra@google.com>2020-06-02 14:04:57 -0700
committerSiva Chandra Reddy <sivachandra@google.com>2020-06-11 12:23:11 -0700
commit118c13c691a5b3b0c5760061a89d5ef7a319c15b (patch)
tree255b838742255c4c9f5b9e58e04710b86a7182a9 /libc/utils
parent269d843720382a8beafdf156cd01f9791faff66c (diff)
downloadllvm-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.h6
-rw-r--r--libc/utils/FPUtil/CMakeLists.txt1
-rw-r--r--libc/utils/FPUtil/FloatOperations.h24
-rw-r--r--libc/utils/FPUtil/ManipulationFunctions.h102
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