aboutsummaryrefslogtreecommitdiff
path: root/libc/utils
diff options
context:
space:
mode:
authorSiva Chandra Reddy <sivachandra@google.com>2020-05-18 15:06:01 -0700
committerSiva Chandra Reddy <sivachandra@google.com>2020-06-01 08:36:59 -0700
commit1caedd0c550646557d8d2feb97b3cbba8c48b2d7 (patch)
treef0992458fcbbfe66de36b50ee07e01d527cf9ede /libc/utils
parent26c78e3095f42c066804cf517339002a1028ed61 (diff)
downloadllvm-1caedd0c550646557d8d2feb97b3cbba8c48b2d7.zip
llvm-1caedd0c550646557d8d2feb97b3cbba8c48b2d7.tar.gz
llvm-1caedd0c550646557d8d2feb97b3cbba8c48b2d7.tar.bz2
[libc] Add implementations of ceil[f], floor[f] and trunc[f] from math.h.
Reviewers: abrachet Differential Revision: https://reviews.llvm.org/D80612
Diffstat (limited to 'libc/utils')
-rw-r--r--libc/utils/FPUtil/FloatOperations.h125
-rw-r--r--libc/utils/FPUtil/FloatProperties.h6
-rw-r--r--libc/utils/MPFRWrapper/MPFRUtils.cpp12
-rw-r--r--libc/utils/MPFRWrapper/MPFRUtils.h12
4 files changed, 147 insertions, 8 deletions
diff --git a/libc/utils/FPUtil/FloatOperations.h b/libc/utils/FPUtil/FloatOperations.h
index ff7604b..a378903 100644
--- a/libc/utils/FPUtil/FloatOperations.h
+++ b/libc/utils/FPUtil/FloatOperations.h
@@ -40,18 +40,23 @@ static inline typename FloatProperties<T>::BitsType absBits(T x) {
return valueAsBits(x) & (~FloatProperties<T>::signMask);
}
-// Return the zero adjusted exponent value of x.
-template <typename T,
- cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
-int getExponent(T x) {
- using Properties = FloatProperties<T>;
- using BitsType = typename Properties::BitsType;
- BitsType bits = absBits(x);
+template <typename BitsType>
+static inline int getExponentFromBits(BitsType bits) {
+ using FPType = typename FloatType<BitsType>::Type;
+ using Properties = FloatProperties<FPType>;
+ bits &= Properties::exponentMask;
int e = (bits >> Properties::mantissaWidth); // Shift out the mantissa.
e -= Properties::exponentOffset; // Zero adjust.
return e;
}
+// Return the zero adjusted exponent value of x.
+template <typename T,
+ cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
+static inline int getExponent(T x) {
+ return getExponentFromBits(valueAsBits(x));
+}
+
// Return true if x is infinity (positive or negative.)
template <typename T,
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
@@ -74,6 +79,24 @@ static inline bool isNaN(T x) {
((bits & Properties::mantissaMask) != 0);
}
+template <typename BitsType> static inline bool bitsAreInfOrNaN(BitsType bits) {
+ using FPType = typename FloatType<BitsType>::Type;
+ return (bits & BitPatterns<FPType>::inf) == BitPatterns<FPType>::inf;
+}
+
+template <typename BitsType> static inline bool bitsAreZero(BitsType bits) {
+ using FPType = typename FloatType<BitsType>::Type;
+ return (bits == BitPatterns<FPType>::zero) ||
+ (bits == BitPatterns<FPType>::negZero);
+}
+
+// Return true if x is any kind of NaN or infinity.
+template <typename T,
+ cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
+static inline bool isInfOrNaN(T x) {
+ return bitsAreInfOrNaN(valueAsBits(x));
+}
+
// Return true if x is a quiet NAN.
template <typename T,
cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
@@ -103,6 +126,94 @@ static inline T abs(T x) {
return valueFromBits(absBits(x));
}
+// Return the trucated value of x. If x is non-negative, then the return value
+// is greatest integer less than or equal to x. Otherwise, return the smallest
+// integer greater than or equal to x. That is, return the integer value rounded
+// toward zero.
+template <typename T,
+ cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
+static inline T trunc(T x) {
+ using Properties = FloatProperties<T>;
+ using BitsType = typename FloatProperties<T>::BitsType;
+
+ BitsType bits = valueAsBits(x);
+
+ // If x is infinity, NaN or zero, return it.
+ if (bitsAreInfOrNaN(bits) || bitsAreZero(bits))
+ return x;
+
+ int exponent = getExponentFromBits(bits);
+
+ // If the exponent is greater than the most negative mantissa
+ // exponent, then x is already an integer.
+ if (exponent >= static_cast<int>(Properties::mantissaWidth))
+ return x;
+
+ // If the exponent is such that abs(x) is less than 1, then return 0.
+ if (exponent <= -1) {
+ if (Properties::signMask & bits)
+ return T(-0.0);
+ else
+ return T(0.0);
+ }
+
+ uint32_t trimSize = Properties::mantissaWidth - exponent;
+ return valueFromBits((bits >> trimSize) << trimSize);
+}
+
+template <typename T,
+ cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
+static inline T ceil(T x) {
+ using Properties = FloatProperties<T>;
+ using BitsType = typename FloatProperties<T>::BitsType;
+
+ BitsType bits = valueAsBits(x);
+
+ // If x is infinity NaN or zero, return it.
+ if (bitsAreInfOrNaN(bits) || bitsAreZero(bits))
+ return x;
+
+ bool isNeg = bits & Properties::signMask;
+ int exponent = getExponentFromBits(bits);
+
+ // If the exponent is greater than the most negative mantissa
+ // exponent, then x is already an integer.
+ if (exponent >= static_cast<int>(Properties::mantissaWidth))
+ return x;
+
+ if (exponent <= -1) {
+ if (isNeg)
+ return T(-0.0);
+ else
+ return T(1.0);
+ }
+
+ uint32_t trimSize = Properties::mantissaWidth - exponent;
+ // If x is already an integer, return it.
+ if ((bits << (Properties::bitWidth - trimSize)) == 0)
+ return x;
+
+ BitsType truncBits = (bits >> trimSize) << trimSize;
+ T truncValue = valueFromBits(truncBits);
+
+ // If x is negative, the ceil operation is equivalent to the trunc operation.
+ if (isNeg)
+ return truncValue;
+
+ return truncValue + T(1.0);
+}
+
+template <typename T,
+ cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
+static inline T floor(T x) {
+ auto bits = valueAsBits(x);
+ if (FloatProperties<T>::signMask & bits) {
+ return -ceil(-x);
+ } else {
+ return trunc(x);
+ }
+}
+
} // namespace fputil
} // namespace __llvm_libc
diff --git a/libc/utils/FPUtil/FloatProperties.h b/libc/utils/FPUtil/FloatProperties.h
index a9584c7..fb09172 100644
--- a/libc/utils/FPUtil/FloatProperties.h
+++ b/libc/utils/FPUtil/FloatProperties.h
@@ -21,9 +21,12 @@ template <> struct FloatProperties<float> {
static_assert(sizeof(BitsType) == sizeof(float),
"Unexpected size of 'float' type.");
+ static constexpr uint32_t bitWidth = sizeof(BitsType) << 3;
+
static constexpr uint32_t mantissaWidth = 23;
static constexpr BitsType mantissaMask = 0x007fffffU;
static constexpr BitsType signMask = 0x80000000U;
+ static constexpr BitsType exponentMask = ~(signMask | mantissaMask);
static constexpr uint32_t exponentOffset = 127;
// If a number x is a NAN, then it is a quiet NAN if:
@@ -37,9 +40,12 @@ template <> struct FloatProperties<double> {
static_assert(sizeof(BitsType) == sizeof(double),
"Unexpected size of 'double' type.");
+ static constexpr uint32_t bitWidth = sizeof(BitsType) << 3;
+
static constexpr uint32_t mantissaWidth = 52;
static constexpr BitsType mantissaMask = 0x000fffffffffffffU;
static constexpr BitsType signMask = 0x8000000000000000ULL;
+ static constexpr BitsType exponentMask = ~(signMask | mantissaMask);
static constexpr uint32_t exponentOffset = 1023;
// If a number x is a NAN, then it is a quiet NAN if:
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index 51c8c37..1bbc84d 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -89,6 +89,9 @@ public:
case Operation::Abs:
mpfr_abs(value, mpfrInput.value, MPFR_RNDN);
break;
+ case Operation::Ceil:
+ mpfr_ceil(value, mpfrInput.value);
+ break;
case Operation::Cos:
mpfr_cos(value, mpfrInput.value, MPFR_RNDN);
break;
@@ -98,9 +101,18 @@ public:
case Operation::Exp2:
mpfr_exp2(value, mpfrInput.value, MPFR_RNDN);
break;
+ case Operation::Floor:
+ mpfr_floor(value, mpfrInput.value);
+ break;
+ case Operation::Round:
+ mpfr_round(value, mpfrInput.value);
+ break;
case Operation::Sin:
mpfr_sin(value, mpfrInput.value, MPFR_RNDN);
break;
+ case Operation::Trunc:
+ mpfr_trunc(value, mpfrInput.value);
+ break;
}
}
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.h b/libc/utils/MPFRWrapper/MPFRUtils.h
index e39ed91..5628165 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.h
+++ b/libc/utils/MPFRWrapper/MPFRUtils.h
@@ -39,7 +39,17 @@ struct Tolerance {
uint32_t bits;
};
-enum class Operation : int { Abs, Cos, Exp, Exp2, Sin };
+enum class Operation : int {
+ Abs,
+ Ceil,
+ Cos,
+ Exp,
+ Exp2,
+ Floor,
+ Round,
+ Sin,
+ Trunc
+};
namespace internal {