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