1 //===-- nextafter implementation for x86 long double numbers ----*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_LIBC_UTILS_FPUTIL_NEXT_AFTER_LONG_DOUBLE_X86_H
10 #define LLVM_LIBC_UTILS_FPUTIL_NEXT_AFTER_LONG_DOUBLE_X86_H
11 
12 #include "FPBits.h"
13 
14 #include <stdint.h>
15 
16 namespace __llvm_libc {
17 namespace fputil {
18 
nextafter(long double from,long double to)19 static inline long double nextafter(long double from, long double to) {
20   using FPBits = FPBits<long double>;
21   FPBits fromBits(from);
22   if (fromBits.isNaN())
23     return from;
24 
25   FPBits toBits(to);
26   if (toBits.isNaN())
27     return to;
28 
29   if (from == to)
30     return to;
31 
32   // Convert pseudo subnormal number to normal number.
33   if (fromBits.implicitBit == 1 && fromBits.exponent == 0) {
34     fromBits.exponent = 1;
35   }
36 
37   using UIntType = FPBits::UIntType;
38   constexpr UIntType signVal = (UIntType(1) << 79);
39   constexpr UIntType mantissaMask =
40       (UIntType(1) << MantissaWidth<long double>::value) - 1;
41   auto intVal = fromBits.bitsAsUInt();
42   if (from < 0.0l) {
43     if (from > to) {
44       if (intVal == (signVal + FPBits::maxSubnormal)) {
45         // We deal with normal/subnormal boundary separately to avoid
46         // dealing with the implicit bit.
47         intVal = signVal + FPBits::minNormal;
48       } else if ((intVal & mantissaMask) == mantissaMask) {
49         fromBits.mantissa = 0;
50         // Incrementing exponent might overflow the value to infinity,
51         // which is what is expected. Since NaNs are handling separately,
52         // it will never overflow "beyond" infinity.
53         ++fromBits.exponent;
54         return fromBits;
55       } else {
56         ++intVal;
57       }
58     } else {
59       if (intVal == (signVal + FPBits::minNormal)) {
60         // We deal with normal/subnormal boundary separately to avoid
61         // dealing with the implicit bit.
62         intVal = signVal + FPBits::maxSubnormal;
63       } else if ((intVal & mantissaMask) == 0) {
64         fromBits.mantissa = mantissaMask;
65         // from == 0 is handled separately so decrementing the exponent will not
66         // lead to underflow.
67         --fromBits.exponent;
68         return fromBits;
69       } else {
70         --intVal;
71       }
72     }
73   } else if (from == 0.0l) {
74     if (from > to)
75       intVal = signVal + 1;
76     else
77       intVal = 1;
78   } else {
79     if (from > to) {
80       if (intVal == FPBits::minNormal) {
81         intVal = FPBits::maxSubnormal;
82       } else if ((intVal & mantissaMask) == 0) {
83         fromBits.mantissa = mantissaMask;
84         // from == 0 is handled separately so decrementing the exponent will not
85         // lead to underflow.
86         --fromBits.exponent;
87         return fromBits;
88       } else {
89         --intVal;
90       }
91     } else {
92       if (intVal == FPBits::maxSubnormal) {
93         intVal = FPBits::minNormal;
94       } else if ((intVal & mantissaMask) == mantissaMask) {
95         fromBits.mantissa = 0;
96         // Incrementing exponent might overflow the value to infinity,
97         // which is what is expected. Since NaNs are handling separately,
98         // it will never overflow "beyond" infinity.
99         ++fromBits.exponent;
100         return fromBits;
101       } else {
102         ++intVal;
103       }
104     }
105   }
106 
107   return *reinterpret_cast<long double *>(&intVal);
108   // TODO: Raise floating point exceptions as required by the standard.
109 }
110 
111 } // namespace fputil
112 } // namespace __llvm_libc
113 
114 #endif // LLVM_LIBC_UTILS_FPUTIL_NEXT_AFTER_LONG_DOUBLE_X86_H
115