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)19static 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