[libc-commits] [libc] [libc][NFC] unify nextafter and nexttoward code (PR #73698)
via libc-commits
libc-commits at lists.llvm.org
Tue Nov 28 12:45:11 PST 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: None (michaelrj-google)
<details>
<summary>Changes</summary>
Previously the nextafter and nexttoward implementations were almost
identical, with the exception of whether or not the second argument was
a template or just long double. This patch unifies them by making the
two argument templates independent.
---
Full diff: https://github.com/llvm/llvm-project/pull/73698.diff
4 Files Affected:
- (modified) libc/src/__support/FPUtil/ManipulationFunctions.h (+10-43)
- (modified) libc/src/math/generic/nexttoward.cpp (+3-1)
- (modified) libc/src/math/generic/nexttowardf.cpp (+3-1)
- (modified) libc/src/math/generic/nexttowardl.cpp (+2-3)
``````````diff
diff --git a/libc/src/__support/FPUtil/ManipulationFunctions.h b/libc/src/__support/FPUtil/ManipulationFunctions.h
index f1768885d4ca500..6624d8c34d29385 100644
--- a/libc/src/__support/FPUtil/ManipulationFunctions.h
+++ b/libc/src/__support/FPUtil/ManipulationFunctions.h
@@ -144,59 +144,26 @@ LIBC_INLINE T ldexp(T x, int exp) {
return normal;
}
-template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
-LIBC_INLINE T nextafter(T from, T to) {
- FPBits<T> from_bits(from);
- if (from_bits.is_nan())
- return from;
-
- FPBits<T> to_bits(to);
- if (to_bits.is_nan())
- return to;
-
- if (from == to)
- return to;
-
- using UIntType = typename FPBits<T>::UIntType;
- UIntType int_val = from_bits.uintval();
- UIntType sign_mask = (UIntType(1) << (sizeof(T) * 8 - 1));
- if (from != T(0.0)) {
- if ((from < to) == (from > T(0.0))) {
- ++int_val;
- } else {
- --int_val;
- }
- } else {
- int_val = (to_bits.uintval() & sign_mask) + UIntType(1);
- }
-
- UIntType exponent_bits = int_val & FloatProperties<T>::EXPONENT_MASK;
- if (exponent_bits == UIntType(0))
- raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
- else if (exponent_bits == FloatProperties<T>::EXPONENT_MASK)
- raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
-
- return cpp::bit_cast<T>(int_val);
-}
-
-template <typename T>
-LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T>
-nexttoward(T from, long double to) {
+template <
+ typename T, typename U,
+ cpp::enable_if_t<cpp::is_floating_point_v<T> && cpp::is_floating_point_v<U>,
+ int> = 0>
+LIBC_INLINE T nextafter(T from, U to) {
FPBits<T> from_bits(from);
if (from_bits.is_nan())
return from;
- FPBits<long double> to_bits(to);
+ FPBits<U> to_bits(to);
if (to_bits.is_nan())
- return to;
+ return static_cast<T>(to);
- if ((long double)from == to)
- return to;
+ if (static_cast<U>(from) == to)
+ return static_cast<T>(to);
using UIntType = typename FPBits<T>::UIntType;
UIntType int_val = from_bits.uintval();
if (from != T(0.0)) {
- if ((from < to) == (from > T(0.0))) {
+ if ((static_cast<U>(from) < to) == (from > T(0.0))) {
++int_val;
} else {
--int_val;
diff --git a/libc/src/math/generic/nexttoward.cpp b/libc/src/math/generic/nexttoward.cpp
index 38b45d6d2f65d9c..ce3e4e6a69ad231 100644
--- a/libc/src/math/generic/nexttoward.cpp
+++ b/libc/src/math/generic/nexttoward.cpp
@@ -13,7 +13,9 @@
namespace LIBC_NAMESPACE {
LLVM_LIBC_FUNCTION(double, nexttoward, (double x, long double y)) {
- return fputil::nexttoward(x, y);
+ // We can reuse the nextafter implementation because the internal nextafter is
+ // templated on the types of the arguments.
+ return fputil::nextafter(x, y);
}
} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/nexttowardf.cpp b/libc/src/math/generic/nexttowardf.cpp
index 59a9f805a6946a1..3b0762c50160ac1 100644
--- a/libc/src/math/generic/nexttowardf.cpp
+++ b/libc/src/math/generic/nexttowardf.cpp
@@ -13,7 +13,9 @@
namespace LIBC_NAMESPACE {
LLVM_LIBC_FUNCTION(float, nexttowardf, (float x, long double y)) {
- return fputil::nexttoward(x, y);
+ // We can reuse the nextafter implementation because the internal nextafter is
+ // templated on the types of the arguments.
+ return fputil::nextafter(x, y);
}
} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/nexttowardl.cpp b/libc/src/math/generic/nexttowardl.cpp
index 0c887ae0671bc98..e9f7f8390760342 100644
--- a/libc/src/math/generic/nexttowardl.cpp
+++ b/libc/src/math/generic/nexttowardl.cpp
@@ -13,9 +13,8 @@
namespace LIBC_NAMESPACE {
LLVM_LIBC_FUNCTION(long double, nexttowardl, (long double x, long double y)) {
- // We can reuse the nextafter implementation because nexttoward behaves
- // exactly same as nextafter in case of long doubles. Also, we have explcitly
- // handled the special 80-bit long doubles in nextafter implementation.
+ // We can reuse the nextafter implementation because the internal nextafter is
+ // templated on the types of the arguments.
return fputil::nextafter(x, y);
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/73698
More information about the libc-commits
mailing list