Skip to content

Commit 86b0cca

Browse files
[libc][NFC] unify nextafter and nexttoward code (#73698)
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.
1 parent 7233e42 commit 86b0cca

File tree

4 files changed

+19
-49
lines changed

4 files changed

+19
-49
lines changed

libc/src/__support/FPUtil/ManipulationFunctions.h

Lines changed: 11 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -144,59 +144,26 @@ LIBC_INLINE T ldexp(T x, int exp) {
144144
return normal;
145145
}
146146

147-
template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
148-
LIBC_INLINE T nextafter(T from, T to) {
149-
FPBits<T> from_bits(from);
150-
if (from_bits.is_nan())
151-
return from;
152-
153-
FPBits<T> to_bits(to);
154-
if (to_bits.is_nan())
155-
return to;
156-
157-
if (from == to)
158-
return to;
159-
160-
using UIntType = typename FPBits<T>::UIntType;
161-
UIntType int_val = from_bits.uintval();
162-
UIntType sign_mask = (UIntType(1) << (sizeof(T) * 8 - 1));
163-
if (from != T(0.0)) {
164-
if ((from < to) == (from > T(0.0))) {
165-
++int_val;
166-
} else {
167-
--int_val;
168-
}
169-
} else {
170-
int_val = (to_bits.uintval() & sign_mask) + UIntType(1);
171-
}
172-
173-
UIntType exponent_bits = int_val & FloatProperties<T>::EXPONENT_MASK;
174-
if (exponent_bits == UIntType(0))
175-
raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
176-
else if (exponent_bits == FloatProperties<T>::EXPONENT_MASK)
177-
raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
178-
179-
return cpp::bit_cast<T>(int_val);
180-
}
181-
182-
template <typename T>
183-
LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T>
184-
nexttoward(T from, long double to) {
147+
template <
148+
typename T, typename U,
149+
cpp::enable_if_t<cpp::is_floating_point_v<T> && cpp::is_floating_point_v<U>,
150+
int> = 0>
151+
LIBC_INLINE T nextafter(T from, U to) {
185152
FPBits<T> from_bits(from);
186153
if (from_bits.is_nan())
187154
return from;
188155

189-
FPBits<long double> to_bits(to);
156+
FPBits<U> to_bits(to);
190157
if (to_bits.is_nan())
191-
return to;
158+
return static_cast<T>(to);
192159

193-
if ((long double)from == to)
194-
return to;
160+
if (static_cast<U>(from) == to)
161+
return static_cast<T>(to);
195162

196163
using UIntType = typename FPBits<T>::UIntType;
197164
UIntType int_val = from_bits.uintval();
198-
if (from != T(0.0)) {
199-
if ((from < to) == (from > T(0.0))) {
165+
if (from != FPBits<T>::zero()) {
166+
if ((static_cast<U>(from) < to) == (from > FPBits<T>::zero())) {
200167
++int_val;
201168
} else {
202169
--int_val;

libc/src/math/generic/nexttoward.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
namespace LIBC_NAMESPACE {
1414

1515
LLVM_LIBC_FUNCTION(double, nexttoward, (double x, long double y)) {
16-
return fputil::nexttoward(x, y);
16+
// We can reuse the nextafter implementation because the internal nextafter is
17+
// templated on the types of the arguments.
18+
return fputil::nextafter(x, y);
1719
}
1820

1921
} // namespace LIBC_NAMESPACE

libc/src/math/generic/nexttowardf.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
namespace LIBC_NAMESPACE {
1414

1515
LLVM_LIBC_FUNCTION(float, nexttowardf, (float x, long double y)) {
16-
return fputil::nexttoward(x, y);
16+
// We can reuse the nextafter implementation because the internal nextafter is
17+
// templated on the types of the arguments.
18+
return fputil::nextafter(x, y);
1719
}
1820

1921
} // namespace LIBC_NAMESPACE

libc/src/math/generic/nexttowardl.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@
1313
namespace LIBC_NAMESPACE {
1414

1515
LLVM_LIBC_FUNCTION(long double, nexttowardl, (long double x, long double y)) {
16-
// We can reuse the nextafter implementation because nexttoward behaves
17-
// exactly same as nextafter in case of long doubles. Also, we have explcitly
18-
// handled the special 80-bit long doubles in nextafter implementation.
16+
// We can reuse the nextafter implementation because the internal nextafter is
17+
// templated on the types of the arguments.
1918
return fputil::nextafter(x, y);
2019
}
2120

0 commit comments

Comments
 (0)