|
10 | 10 | #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_MANIPULATIONFUNCTIONS_H |
11 | 11 |
|
12 | 12 | #include "FPBits.h" |
| 13 | +#include "FloatProperties.h" |
13 | 14 | #include "NearestIntegerOperations.h" |
14 | 15 | #include "NormalFloat.h" |
15 | 16 | #include "PlatformDefs.h" |
|
19 | 20 | #include "src/__support/macros/attributes.h" |
20 | 21 | #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY |
21 | 22 |
|
| 23 | +#include <fenv.h> |
22 | 24 | #include <limits.h> |
23 | 25 | #include <math.h> |
24 | 26 |
|
@@ -169,8 +171,49 @@ LIBC_INLINE T nextafter(T from, T to) { |
169 | 171 | int_val = (to_bits.uintval() & sign_mask) + UIntType(1); |
170 | 172 | } |
171 | 173 |
|
| 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 | + |
172 | 216 | return cpp::bit_cast<T>(int_val); |
173 | | - // TODO: Raise floating point exceptions as required by the standard. |
174 | 217 | } |
175 | 218 |
|
176 | 219 | } // namespace fputil |
|
0 commit comments