forked from OSchip/llvm-project
115 lines
3.6 KiB
C++
115 lines
3.6 KiB
C++
//===-- nextafter implementation for x86 long double numbers ----*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_LIBC_UTILS_FPUTIL_NEXT_AFTER_LONG_DOUBLE_X86_H
|
|
#define LLVM_LIBC_UTILS_FPUTIL_NEXT_AFTER_LONG_DOUBLE_X86_H
|
|
|
|
#include "FPBits.h"
|
|
|
|
#include <stdint.h>
|
|
|
|
namespace __llvm_libc {
|
|
namespace fputil {
|
|
|
|
static inline long double nextafter(long double from, long double to) {
|
|
using FPBits = FPBits<long double>;
|
|
FPBits fromBits(from);
|
|
if (fromBits.isNaN())
|
|
return from;
|
|
|
|
FPBits toBits(to);
|
|
if (toBits.isNaN())
|
|
return to;
|
|
|
|
if (from == to)
|
|
return to;
|
|
|
|
// Convert pseudo subnormal number to normal number.
|
|
if (fromBits.encoding.implicitBit == 1 && fromBits.encoding.exponent == 0) {
|
|
fromBits.encoding.exponent = 1;
|
|
}
|
|
|
|
using UIntType = FPBits::UIntType;
|
|
constexpr UIntType signVal = (UIntType(1) << 79);
|
|
constexpr UIntType mantissaMask =
|
|
(UIntType(1) << MantissaWidth<long double>::value) - 1;
|
|
UIntType intVal = fromBits.uintval();
|
|
if (from < 0.0l) {
|
|
if (from > to) {
|
|
if (intVal == (signVal + FPBits::maxSubnormal)) {
|
|
// We deal with normal/subnormal boundary separately to avoid
|
|
// dealing with the implicit bit.
|
|
intVal = signVal + FPBits::minNormal;
|
|
} else if ((intVal & mantissaMask) == mantissaMask) {
|
|
fromBits.encoding.mantissa = 0;
|
|
// Incrementing exponent might overflow the value to infinity,
|
|
// which is what is expected. Since NaNs are handling separately,
|
|
// it will never overflow "beyond" infinity.
|
|
++fromBits.encoding.exponent;
|
|
return fromBits;
|
|
} else {
|
|
++intVal;
|
|
}
|
|
} else {
|
|
if (intVal == (signVal + FPBits::minNormal)) {
|
|
// We deal with normal/subnormal boundary separately to avoid
|
|
// dealing with the implicit bit.
|
|
intVal = signVal + FPBits::maxSubnormal;
|
|
} else if ((intVal & mantissaMask) == 0) {
|
|
fromBits.encoding.mantissa = mantissaMask;
|
|
// from == 0 is handled separately so decrementing the exponent will not
|
|
// lead to underflow.
|
|
--fromBits.encoding.exponent;
|
|
return fromBits;
|
|
} else {
|
|
--intVal;
|
|
}
|
|
}
|
|
} else if (from == 0.0l) {
|
|
if (from > to)
|
|
intVal = signVal + 1;
|
|
else
|
|
intVal = 1;
|
|
} else {
|
|
if (from > to) {
|
|
if (intVal == FPBits::minNormal) {
|
|
intVal = FPBits::maxSubnormal;
|
|
} else if ((intVal & mantissaMask) == 0) {
|
|
fromBits.encoding.mantissa = mantissaMask;
|
|
// from == 0 is handled separately so decrementing the exponent will not
|
|
// lead to underflow.
|
|
--fromBits.encoding.exponent;
|
|
return fromBits;
|
|
} else {
|
|
--intVal;
|
|
}
|
|
} else {
|
|
if (intVal == FPBits::maxSubnormal) {
|
|
intVal = FPBits::minNormal;
|
|
} else if ((intVal & mantissaMask) == mantissaMask) {
|
|
fromBits.encoding.mantissa = 0;
|
|
// Incrementing exponent might overflow the value to infinity,
|
|
// which is what is expected. Since NaNs are handling separately,
|
|
// it will never overflow "beyond" infinity.
|
|
++fromBits.encoding.exponent;
|
|
return fromBits;
|
|
} else {
|
|
++intVal;
|
|
}
|
|
}
|
|
}
|
|
|
|
return *reinterpret_cast<long double *>(&intVal);
|
|
// TODO: Raise floating point exceptions as required by the standard.
|
|
}
|
|
|
|
} // namespace fputil
|
|
} // namespace __llvm_libc
|
|
|
|
#endif // LLVM_LIBC_UTILS_FPUTIL_NEXT_AFTER_LONG_DOUBLE_X86_H
|