Skip to content

Commit 6a9f4c4

Browse files
committed
[libc][math] Implement nexttoward functions
1 parent 0530022 commit 6a9f4c4

23 files changed

+541
-2
lines changed

libc/config/darwin/arm/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,9 @@ set(TARGET_LIBM_ENTRYPOINTS
199199
libc.src.math.nextafter
200200
libc.src.math.nextafterf
201201
libc.src.math.nextafterl
202+
libc.src.math.nexttoward
203+
libc.src.math.nexttowardf
204+
libc.src.math.nexttowardl
202205
libc.src.math.powf
203206
libc.src.math.remainderf
204207
libc.src.math.remainder

libc/config/darwin/x86_64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,9 @@ set(TARGET_LIBM_ENTRYPOINTS
178178
#libc.src.math.nextafter
179179
#libc.src.math.nextafterf
180180
#libc.src.math.nextafterl
181+
#libc.src.math.nexttoward
182+
#libc.src.math.nexttowardf
183+
#libc.src.math.nexttowardl
181184
#libc.src.math.remainderf
182185
#libc.src.math.remainder
183186
#libc.src.math.remainderl

libc/config/gpu/entrypoints.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ set(TARGET_LIBM_ENTRYPOINTS
219219
libc.src.math.nearbyintf
220220
libc.src.math.nextafter
221221
libc.src.math.nextafterf
222+
libc.src.math.nexttoward
223+
libc.src.math.nexttowardf
222224
libc.src.math.pow
223225
libc.src.math.powf
224226
libc.src.math.remainder

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,9 @@ set(TARGET_LIBM_ENTRYPOINTS
316316
libc.src.math.nextafter
317317
libc.src.math.nextafterf
318318
libc.src.math.nextafterl
319+
libc.src.math.nexttoward
320+
libc.src.math.nexttowardf
321+
libc.src.math.nexttowardl
319322
libc.src.math.powf
320323
libc.src.math.remainderf
321324
libc.src.math.remainder

libc/config/linux/riscv/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,9 @@ set(TARGET_LIBM_ENTRYPOINTS
325325
libc.src.math.nextafter
326326
libc.src.math.nextafterf
327327
libc.src.math.nextafterl
328+
libc.src.math.nexttoward
329+
libc.src.math.nexttowardf
330+
libc.src.math.nexttowardl
328331
libc.src.math.powf
329332
libc.src.math.remainderf
330333
libc.src.math.remainder

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,9 @@ set(TARGET_LIBM_ENTRYPOINTS
329329
libc.src.math.nextafter
330330
libc.src.math.nextafterf
331331
libc.src.math.nextafterl
332+
libc.src.math.nexttoward
333+
libc.src.math.nexttowardf
334+
libc.src.math.nexttowardl
332335
libc.src.math.powf
333336
libc.src.math.remainderf
334337
libc.src.math.remainder

libc/config/windows/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ set(TARGET_LIBM_ENTRYPOINTS
198198
libc.src.math.nextafter
199199
libc.src.math.nextafterf
200200
libc.src.math.nextafterl
201+
libc.src.math.nexttoward
202+
libc.src.math.nexttowardf
203+
libc.src.math.nexttowardl
201204
libc.src.math.powf
202205
libc.src.math.remainderf
203206
libc.src.math.remainder

libc/spec/stdc.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,10 @@ def StdC : StandardSpec<"stdc"> {
492492
FunctionSpec<"nextafter", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
493493
FunctionSpec<"nextafterl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
494494

495+
FunctionSpec<"nexttowardf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<LongDoubleType>]>,
496+
FunctionSpec<"nexttoward", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<LongDoubleType>]>,
497+
FunctionSpec<"nexttowardl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
498+
495499
FunctionSpec<"powf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
496500
FunctionSpec<"pow", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
497501

libc/src/__support/FPUtil/ManipulationFunctions.h

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_MANIPULATIONFUNCTIONS_H
1111

1212
#include "FPBits.h"
13+
#include "FloatProperties.h"
1314
#include "NearestIntegerOperations.h"
1415
#include "NormalFloat.h"
1516
#include "PlatformDefs.h"
@@ -19,6 +20,7 @@
1920
#include "src/__support/macros/attributes.h"
2021
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
2122

23+
#include <fenv.h>
2224
#include <limits.h>
2325
#include <math.h>
2426

@@ -169,8 +171,49 @@ LIBC_INLINE T nextafter(T from, T to) {
169171
int_val = (to_bits.uintval() & sign_mask) + UIntType(1);
170172
}
171173

174+
UIntType exponent_bits = int_val & FloatProperties<T>::EXPONENT_MASK;
175+
if (exponent_bits == UIntType(0))
176+
raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
177+
else if (exponent_bits == FloatProperties<T>::EXPONENT_MASK)
178+
raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
179+
180+
return cpp::bit_cast<T>(int_val);
181+
}
182+
183+
template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
184+
LIBC_INLINE T nexttoward(T from, long double to) {
185+
FPBits<T> from_bits(from);
186+
if (from_bits.is_nan())
187+
return from;
188+
189+
FPBits<long double> to_bits(to);
190+
if (to_bits.is_nan())
191+
return to;
192+
193+
if ((long double)from == to)
194+
return to;
195+
196+
using UIntType = typename FPBits<T>::UIntType;
197+
UIntType int_val = from_bits.uintval();
198+
if (from != T(0.0)) {
199+
if ((from < to) == (from > T(0.0))) {
200+
++int_val;
201+
} else {
202+
--int_val;
203+
}
204+
} else {
205+
int_val = FPBits<T>::MIN_SUBNORMAL;
206+
if (to_bits.get_sign())
207+
int_val |= FloatProperties<T>::SIGN_MASK;
208+
}
209+
210+
UIntType exponent_bits = int_val & FloatProperties<T>::EXPONENT_MASK;
211+
if (exponent_bits == UIntType(0))
212+
raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
213+
else if (exponent_bits == FloatProperties<T>::EXPONENT_MASK)
214+
raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
215+
172216
return cpp::bit_cast<T>(int_val);
173-
// TODO: Raise floating point exceptions as required by the standard.
174217
}
175218

176219
} // namespace fputil

libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ LIBC_INLINE long double nextafter(long double from, long double to) {
5959
// which is what is expected. Since NaNs are handling separately,
6060
// it will never overflow "beyond" infinity.
6161
from_bits.set_unbiased_exponent(from_bits.get_unbiased_exponent() + 1);
62+
if (from_bits.is_inf())
63+
raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
6264
return from_bits;
6365
} else {
6466
++int_val;
@@ -105,15 +107,21 @@ LIBC_INLINE long double nextafter(long double from, long double to) {
105107
// which is what is expected. Since NaNs are handling separately,
106108
// it will never overflow "beyond" infinity.
107109
from_bits.set_unbiased_exponent(from_bits.get_unbiased_exponent() + 1);
110+
if (from_bits.is_inf())
111+
raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
108112
return from_bits;
109113
} else {
110114
++int_val;
111115
}
112116
}
113117
}
114118

119+
UIntType implicit_bit =
120+
int_val & (UIntType(1) << MantissaWidth<long double>::VALUE);
121+
if (implicit_bit == UIntType(0))
122+
raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
123+
115124
return cpp::bit_cast<long double>(int_val);
116-
// TODO: Raise floating point exceptions as required by the standard.
117125
}
118126

119127
} // namespace fputil

0 commit comments

Comments
 (0)