1fcb9d7e2SKirill Okhotnikov //===-- Single-precision cosh function ------------------------------------===// 2fcb9d7e2SKirill Okhotnikov // 3fcb9d7e2SKirill Okhotnikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fcb9d7e2SKirill Okhotnikov // See https://llvm.org/LICENSE.txt for license information. 5fcb9d7e2SKirill Okhotnikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fcb9d7e2SKirill Okhotnikov // 7fcb9d7e2SKirill Okhotnikov //===----------------------------------------------------------------------===// 8fcb9d7e2SKirill Okhotnikov 9fcb9d7e2SKirill Okhotnikov #include "src/math/coshf.h" 10fcb9d7e2SKirill Okhotnikov #include "src/__support/FPUtil/FPBits.h" 11fcb9d7e2SKirill Okhotnikov #include "src/__support/FPUtil/multiply_add.h" 12a9824312STue Ly #include "src/__support/FPUtil/rounding_mode.h" 13*5ff3ff33SPetr Hosek #include "src/__support/macros/config.h" 14737e1cd1SGuillaume Chatelet #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY 1589ed5b7cSKirill Okhotnikov #include "src/math/generic/explogxf.h" 16fcb9d7e2SKirill Okhotnikov 17*5ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL { 18fcb9d7e2SKirill Okhotnikov 19fcb9d7e2SKirill Okhotnikov LLVM_LIBC_FUNCTION(float, coshf, (float x)) { 20fcb9d7e2SKirill Okhotnikov using FPBits = typename fputil::FPBits<float>; 212137894aSGuillaume Chatelet 22fcb9d7e2SKirill Okhotnikov FPBits xbits(x); 2311ec512fSGuillaume Chatelet xbits.set_sign(Sign::POS); 24fcb9d7e2SKirill Okhotnikov x = xbits.get_val(); 25fcb9d7e2SKirill Okhotnikov 26fcb9d7e2SKirill Okhotnikov uint32_t x_u = xbits.uintval(); 27fcb9d7e2SKirill Okhotnikov 280ae409c0STue Ly // When |x| >= 90, or x is inf or nan 290ae409c0STue Ly if (LIBC_UNLIKELY(x_u >= 0x42b4'0000U || x_u <= 0x3280'0000U)) { 30fcb9d7e2SKirill Okhotnikov // |x| <= 2^-26 310ae409c0STue Ly if (x_u <= 0x3280'0000U) { 32fcb9d7e2SKirill Okhotnikov return 1.0f + x; 33fcb9d7e2SKirill Okhotnikov } 34fcb9d7e2SKirill Okhotnikov 35fcb9d7e2SKirill Okhotnikov if (xbits.is_inf_or_nan()) 366b02d2f8SGuillaume Chatelet return x + FPBits::inf().get_val(); 37fcb9d7e2SKirill Okhotnikov 38a9824312STue Ly int rounding = fputil::quick_get_round(); 3929f8e076SGuillaume Chatelet if (LIBC_UNLIKELY(rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)) 406b02d2f8SGuillaume Chatelet return FPBits::max_normal().get_val(); 41fcb9d7e2SKirill Okhotnikov 420aa9593cSTue Ly fputil::set_errno_if_required(ERANGE); 430aa9593cSTue Ly fputil::raise_except_if_required(FE_OVERFLOW); 44fcb9d7e2SKirill Okhotnikov 456b02d2f8SGuillaume Chatelet return x + FPBits::inf().get_val(); 46fcb9d7e2SKirill Okhotnikov } 471c89ae71STue Ly 481c89ae71STue Ly // TODO: We should be able to reduce the latency and reciprocal throughput 491c89ae71STue Ly // further by using a low degree (maybe 3-7 ?) minimax polynomial for small 501c89ae71STue Ly // but not too small inputs, such as |x| < 2^-2, or |x| < 2^-3. 511c89ae71STue Ly 521c89ae71STue Ly // cosh(x) = (e^x + e^(-x)) / 2. 537d11a592SAlex Brachet return static_cast<float>(exp_pm_eval</*is_sinh*/ false>(x)); 54fcb9d7e2SKirill Okhotnikov } 55fcb9d7e2SKirill Okhotnikov 56*5ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL 57