125 lines · c
1//===-- Implementation header for coshf16 -----------------------*- 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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_COSHF16_H10#define LLVM_LIBC_SRC___SUPPORT_MATH_COSHF16_H11 12#include "include/llvm-libc-macros/float16-macros.h"13 14#ifdef LIBC_TYPES_HAS_FLOAT1615 16#include "expxf16_utils.h"17#include "src/__support/FPUtil/FEnvImpl.h"18#include "src/__support/FPUtil/FPBits.h"19#include "src/__support/FPUtil/except_value_utils.h"20#include "src/__support/FPUtil/rounding_mode.h"21#include "src/__support/macros/config.h"22#include "src/__support/macros/optimization.h"23 24namespace LIBC_NAMESPACE_DECL {25 26namespace math {27 28LIBC_INLINE static constexpr float16 coshf16(float16 x) {29 30#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS31 constexpr fputil::ExceptValues<float16, 9> COSHF16_EXCEPTS_POS = {{32 // x = 0x1.6ap-5, coshf16(x) = 0x1p+0 (RZ)33 {0x29a8U, 0x3c00U, 1U, 0U, 1U},34 // x = 0x1.8c4p+0, coshf16(x) = 0x1.3a8p+1 (RZ)35 {0x3e31U, 0x40eaU, 1U, 0U, 0U},36 // x = 0x1.994p+0, coshf16(x) = 0x1.498p+1 (RZ)37 {0x3e65U, 0x4126U, 1U, 0U, 0U},38 // x = 0x1.b6p+0, coshf16(x) = 0x1.6d8p+1 (RZ)39 {0x3ed8U, 0x41b6U, 1U, 0U, 1U},40 // x = 0x1.aap+1, coshf16(x) = 0x1.be8p+3 (RZ)41 {0x42a8U, 0x4afaU, 1U, 0U, 1U},42 // x = 0x1.cc4p+1, coshf16(x) = 0x1.23cp+4 (RZ)43 {0x4331U, 0x4c8fU, 1U, 0U, 0U},44 // x = 0x1.288p+2, coshf16(x) = 0x1.9b4p+5 (RZ)45 {0x44a2U, 0x526dU, 1U, 0U, 0U},46 // x = 0x1.958p+2, coshf16(x) = 0x1.1a4p+8 (RZ)47 {0x4656U, 0x5c69U, 1U, 0U, 0U},48 // x = 0x1.5fp+3, coshf16(x) = 0x1.c54p+14 (RZ)49 {0x497cU, 0x7715U, 1U, 0U, 1U},50 }};51 52 constexpr fputil::ExceptValues<float16, 6> COSHF16_EXCEPTS_NEG = {{53 // x = -0x1.6ap-5, coshf16(x) = 0x1p+0 (RZ)54 {0xa9a8U, 0x3c00U, 1U, 0U, 1U},55 // x = -0x1.b6p+0, coshf16(x) = 0x1.6d8p+1 (RZ)56 {0xbed8U, 0x41b6U, 1U, 0U, 1U},57 // x = -0x1.288p+2, coshf16(x) = 0x1.9b4p+5 (RZ)58 {0xc4a2U, 0x526dU, 1U, 0U, 0U},59 // x = -0x1.5fp+3, coshf16(x) = 0x1.c54p+14 (RZ)60 {0xc97cU, 0x7715U, 1U, 0U, 1U},61 // x = -0x1.8c4p+0, coshf16(x) = 0x1.3a8p+1 (RZ)62 {0xbe31U, 0x40eaU, 1U, 0U, 0U},63 // x = -0x1.994p+0, coshf16(x) = 0x1.498p+1 (RZ)64 {0xbe65U, 0x4126U, 1U, 0U, 0U},65 }};66#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS67 68 using namespace expxf16_internal;69 using FPBits = fputil::FPBits<float16>;70 FPBits x_bits(x);71 72 uint16_t x_u = x_bits.uintval();73 uint16_t x_abs = x_u & 0x7fffU;74 75 // When |x| >= acosh(2^16), or x is NaN.76 if (LIBC_UNLIKELY(x_abs >= 0x49e5U)) {77 // cosh(NaN) = NaN78 if (x_bits.is_nan()) {79 if (x_bits.is_signaling_nan()) {80 fputil::raise_except_if_required(FE_INVALID);81 return FPBits::quiet_nan().get_val();82 }83 84 return x;85 }86 87 // When |x| >= acosh(2^16).88 if (x_abs >= 0x49e5U) {89 // cosh(+/-inf) = +inf90 if (x_bits.is_inf())91 return FPBits::inf().get_val();92 93 switch (fputil::quick_get_round()) {94 case FE_TONEAREST:95 case FE_UPWARD:96 fputil::set_errno_if_required(ERANGE);97 fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);98 return FPBits::inf().get_val();99 default:100 return FPBits::max_normal().get_val();101 }102 }103 }104 105#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS106 if (x_bits.is_pos()) {107 if (auto r = COSHF16_EXCEPTS_POS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))108 return r.value();109 } else {110 if (auto r = COSHF16_EXCEPTS_NEG.lookup(x_u); LIBC_UNLIKELY(r.has_value()))111 return r.value();112 }113#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS114 115 return eval_sinh_or_cosh</*IsSinh=*/false>(x);116}117 118} // namespace math119 120} // namespace LIBC_NAMESPACE_DECL121 122#endif // LIBC_TYPES_HAS_FLOAT16123 124#endif // LLVM_LIBC_SRC___SUPPORT_MATH_COSHF16_H125