• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_SRC___SUPPORT_FPUTIL_X86_64_NEXTAFTERLONGDOUBLE_H
10 #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_X86_64_NEXTAFTERLONGDOUBLE_H
11 
12 #include "src/__support/macros/properties/architectures.h"
13 
14 #if !defined(LIBC_TARGET_ARCH_IS_X86)
15 #error "Invalid include"
16 #endif
17 
18 #include "src/__support/CPP/bit.h"
19 #include "src/__support/FPUtil/FEnvImpl.h"
20 #include "src/__support/FPUtil/FPBits.h"
21 
22 #include <stdint.h>
23 
24 namespace LIBC_NAMESPACE {
25 namespace fputil {
26 
nextafter(long double from,long double to)27 LIBC_INLINE long double nextafter(long double from, long double to) {
28   using FPBits = FPBits<long double>;
29   FPBits from_bits(from);
30   if (from_bits.is_nan())
31     return from;
32 
33   FPBits to_bits(to);
34   if (to_bits.is_nan())
35     return to;
36 
37   if (from == to)
38     return to;
39 
40   // Convert pseudo subnormal number to normal number.
41   if (from_bits.get_implicit_bit() == 1 && from_bits.is_subnormal()) {
42     from_bits.set_biased_exponent(1);
43   }
44 
45   using StorageType = FPBits::StorageType;
46 
47   constexpr StorageType FRACTION_MASK = FPBits::FRACTION_MASK;
48   // StorageType int_val = from_bits.uintval();
49   if (from == 0.0l) { // +0.0 / -0.0
50     from_bits = FPBits::min_subnormal(from > to ? Sign::NEG : Sign::POS);
51   } else if (from < 0.0l) {
52     if (to < from) { // toward -inf
53       if (from_bits == FPBits::max_subnormal(Sign::NEG)) {
54         // We deal with normal/subnormal boundary separately to avoid
55         // dealing with the implicit bit.
56         from_bits = FPBits::min_normal(Sign::NEG);
57       } else if (from_bits.get_mantissa() == FRACTION_MASK) {
58         from_bits.set_mantissa(0);
59         // Incrementing exponent might overflow the value to infinity,
60         // which is what is expected. Since NaNs are handling separately,
61         // it will never overflow "beyond" infinity.
62         from_bits.set_biased_exponent(from_bits.get_biased_exponent() + 1);
63         if (from_bits.is_inf())
64           raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
65         return from_bits.get_val();
66       } else {
67         from_bits = FPBits(StorageType(from_bits.uintval() + 1));
68       }
69     } else { // toward +inf
70       if (from_bits == FPBits::min_normal(Sign::NEG)) {
71         // We deal with normal/subnormal boundary separately to avoid
72         // dealing with the implicit bit.
73         from_bits = FPBits::max_subnormal(Sign::NEG);
74       } else if (from_bits.get_mantissa() == 0) {
75         from_bits.set_mantissa(FRACTION_MASK);
76         // from == 0 is handled separately so decrementing the exponent will not
77         // lead to underflow.
78         from_bits.set_biased_exponent(from_bits.get_biased_exponent() - 1);
79         return from_bits.get_val();
80       } else {
81         from_bits = FPBits(StorageType(from_bits.uintval() - 1));
82       }
83     }
84   } else {
85     if (to < from) { // toward -inf
86       if (from_bits == FPBits::min_normal(Sign::POS)) {
87         from_bits = FPBits::max_subnormal(Sign::POS);
88       } else if (from_bits.get_mantissa() == 0) {
89         from_bits.set_mantissa(FRACTION_MASK);
90         // from == 0 is handled separately so decrementing the exponent will not
91         // lead to underflow.
92         from_bits.set_biased_exponent(from_bits.get_biased_exponent() - 1);
93         return from_bits.get_val();
94       } else {
95         from_bits = FPBits(StorageType(from_bits.uintval() - 1));
96       }
97     } else { // toward +inf
98       if (from_bits == FPBits::max_subnormal(Sign::POS)) {
99         from_bits = FPBits::min_normal(Sign::POS);
100       } else if (from_bits.get_mantissa() == FRACTION_MASK) {
101         from_bits.set_mantissa(0);
102         // Incrementing exponent might overflow the value to infinity,
103         // which is what is expected. Since NaNs are handling separately,
104         // it will never overflow "beyond" infinity.
105         from_bits.set_biased_exponent(from_bits.get_biased_exponent() + 1);
106         if (from_bits.is_inf())
107           raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
108         return from_bits.get_val();
109       } else {
110         from_bits = FPBits(StorageType(from_bits.uintval() + 1));
111       }
112     }
113   }
114 
115   if (!from_bits.get_implicit_bit())
116     raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
117 
118   return from_bits.get_val();
119 }
120 
121 } // namespace fputil
122 } // namespace LIBC_NAMESPACE
123 
124 #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_X86_64_NEXTAFTERLONGDOUBLE_H
125