1 //===-- nextafter implementation for x86 long double numbers ----*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIBC_SRC_SUPPORT_FPUTIL_X86_64_NEXT_AFTER_LONG_DOUBLE_H
10 #define LLVM_LIBC_SRC_SUPPORT_FPUTIL_X86_64_NEXT_AFTER_LONG_DOUBLE_H
12 #include "src/__support/macros/properties/architectures.h"
14 #if !defined(LIBC_TARGET_ARCH_IS_X86)
15 #error "Invalid include"
18 #include "src/__support/CPP/bit.h"
19 #include "src/__support/FPUtil/FPBits.h"
23 namespace __llvm_libc
{
26 LIBC_INLINE
long double nextafter(long double from
, long double to
) {
27 using FPBits
= FPBits
<long double>;
28 FPBits
from_bits(from
);
29 if (from_bits
.is_nan())
39 // Convert pseudo subnormal number to normal number.
40 if (from_bits
.get_implicit_bit() == 1 &&
41 from_bits
.get_unbiased_exponent() == 0) {
42 from_bits
.set_unbiased_exponent(1);
45 using UIntType
= FPBits::UIntType
;
46 constexpr UIntType SIGN_VAL
= (UIntType(1) << 79);
47 constexpr UIntType MANTISSA_MASK
=
48 (UIntType(1) << MantissaWidth
<long double>::VALUE
) - 1;
49 UIntType int_val
= from_bits
.uintval();
52 if (int_val
== (SIGN_VAL
+ FPBits::MAX_SUBNORMAL
)) {
53 // We deal with normal/subnormal boundary separately to avoid
54 // dealing with the implicit bit.
55 int_val
= SIGN_VAL
+ FPBits::MIN_NORMAL
;
56 } else if ((int_val
& MANTISSA_MASK
) == MANTISSA_MASK
) {
57 from_bits
.set_mantissa(0);
58 // Incrementing exponent might overflow the value to infinity,
59 // which is what is expected. Since NaNs are handling separately,
60 // it will never overflow "beyond" infinity.
61 from_bits
.set_unbiased_exponent(from_bits
.get_unbiased_exponent() + 1);
67 if (int_val
== (SIGN_VAL
+ FPBits::MIN_NORMAL
)) {
68 // We deal with normal/subnormal boundary separately to avoid
69 // dealing with the implicit bit.
70 int_val
= SIGN_VAL
+ FPBits::MAX_SUBNORMAL
;
71 } else if ((int_val
& MANTISSA_MASK
) == 0) {
72 from_bits
.set_mantissa(MANTISSA_MASK
);
73 // from == 0 is handled separately so decrementing the exponent will not
75 from_bits
.set_unbiased_exponent(from_bits
.get_unbiased_exponent() - 1);
81 } else if (from
== 0.0l) {
83 int_val
= SIGN_VAL
+ 1;
88 if (int_val
== FPBits::MIN_NORMAL
) {
89 int_val
= FPBits::MAX_SUBNORMAL
;
90 } else if ((int_val
& MANTISSA_MASK
) == 0) {
91 from_bits
.set_mantissa(MANTISSA_MASK
);
92 // from == 0 is handled separately so decrementing the exponent will not
94 from_bits
.set_unbiased_exponent(from_bits
.get_unbiased_exponent() - 1);
100 if (int_val
== FPBits::MAX_SUBNORMAL
) {
101 int_val
= FPBits::MIN_NORMAL
;
102 } else if ((int_val
& MANTISSA_MASK
) == MANTISSA_MASK
) {
103 from_bits
.set_mantissa(0);
104 // Incrementing exponent might overflow the value to infinity,
105 // which is what is expected. Since NaNs are handling separately,
106 // it will never overflow "beyond" infinity.
107 from_bits
.set_unbiased_exponent(from_bits
.get_unbiased_exponent() + 1);
115 return cpp::bit_cast
<long double>(int_val
);
116 // TODO: Raise floating point exceptions as required by the standard.
119 } // namespace fputil
120 } // namespace __llvm_libc
122 #endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_X86_64_NEXT_AFTER_LONG_DOUBLE_H