//===-- Floating-point manipulation functions -------------------*- 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_MANIPULATION_FUNCTIONS_H #define LLVM_LIBC_UTILS_FPUTIL_MANIPULATION_FUNCTIONS_H #include "FPBits.h" #include "NearestIntegerOperations.h" #include "NormalFloat.h" #include "utils/CPP/TypeTraits.h" namespace __llvm_libc { namespace fputil { template ::Value, int> = 0> static inline T frexp(T x, int &exp) { FPBits bits(x); if (bits.isInfOrNaN()) return x; if (bits.isZero()) { exp = 0; return x; } NormalFloat normal(bits); exp = normal.exponent + 1; normal.exponent = -1; return normal; } template ::Value, int> = 0> static inline T modf(T x, T &iptr) { FPBits bits(x); if (bits.isZero() || bits.isNaN()) { iptr = x; return x; } else if (bits.isInf()) { iptr = x; return bits.sign ? FPBits::negZero() : FPBits::zero(); } else { iptr = trunc(x); if (x == iptr) { // If x is already an integer value, then return zero with the right // sign. return bits.sign ? FPBits::negZero() : FPBits::zero(); } else { return x - iptr; } } } template ::Value, int> = 0> static inline T copysign(T x, T y) { FPBits xbits(x); xbits.sign = FPBits(y).sign; return xbits; } template ::Value, int> = 0> static inline T logb(T x) { FPBits bits(x); if (bits.isZero()) { // TODO(Floating point exception): Raise div-by-zero exception. // TODO(errno): POSIX requires setting errno to ERANGE. return FPBits::negInf(); } else if (bits.isNaN()) { return x; } else if (bits.isInf()) { // Return positive infinity. return FPBits::inf(); } NormalFloat normal(bits); return normal.exponent; } } // namespace fputil } // namespace __llvm_libc #endif // LLVM_LIBC_UTILS_FPUTIL_MANIPULATION_FUNCTIONS_H