16c1fc7e4SKirill Okhotnikov //===-- Single-precision atanh function -----------------------------------===// 26c1fc7e4SKirill Okhotnikov // 36c1fc7e4SKirill Okhotnikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 46c1fc7e4SKirill Okhotnikov // See https://llvm.org/LICENSE.txt for license information. 56c1fc7e4SKirill Okhotnikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 66c1fc7e4SKirill Okhotnikov // 76c1fc7e4SKirill Okhotnikov //===----------------------------------------------------------------------===// 86c1fc7e4SKirill Okhotnikov 96c1fc7e4SKirill Okhotnikov #include "src/math/atanhf.h" 106c1fc7e4SKirill Okhotnikov #include "src/__support/FPUtil/FPBits.h" 11*5ff3ff33SPetr Hosek #include "src/__support/macros/config.h" 12737e1cd1SGuillaume Chatelet #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY 136c1fc7e4SKirill Okhotnikov #include "src/math/generic/explogxf.h" 146c1fc7e4SKirill Okhotnikov 15*5ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL { 166c1fc7e4SKirill Okhotnikov 176c1fc7e4SKirill Okhotnikov LLVM_LIBC_FUNCTION(float, atanhf, (float x)) { 186c1fc7e4SKirill Okhotnikov using FPBits = typename fputil::FPBits<float>; 192137894aSGuillaume Chatelet 206c1fc7e4SKirill Okhotnikov FPBits xbits(x); 2111ec512fSGuillaume Chatelet Sign sign = xbits.sign(); 22ea43c8eeSGuillaume Chatelet uint32_t x_abs = xbits.abs().uintval(); 236c1fc7e4SKirill Okhotnikov 246c1fc7e4SKirill Okhotnikov // |x| >= 1.0 2529f8e076SGuillaume Chatelet if (LIBC_UNLIKELY(x_abs >= 0x3F80'0000U)) { 266c1fc7e4SKirill Okhotnikov if (xbits.is_nan()) { 2774ec4679SDominic Chen return x; 286c1fc7e4SKirill Okhotnikov } 2931c39439STue Ly // |x| == 1.0 306c1fc7e4SKirill Okhotnikov if (x_abs == 0x3F80'0000U) { 3131c39439STue Ly fputil::set_errno_if_required(ERANGE); 3231c39439STue Ly fputil::raise_except_if_required(FE_DIVBYZERO); 336b02d2f8SGuillaume Chatelet return FPBits::inf(sign).get_val(); 346c1fc7e4SKirill Okhotnikov } else { 3531c39439STue Ly fputil::set_errno_if_required(EDOM); 3631c39439STue Ly fputil::raise_except_if_required(FE_INVALID); 37ace383dfSGuillaume Chatelet return FPBits::quiet_nan().get_val(); 386c1fc7e4SKirill Okhotnikov } 396c1fc7e4SKirill Okhotnikov } 406c1fc7e4SKirill Okhotnikov 416c1fc7e4SKirill Okhotnikov // |x| < ~0.10 4229f8e076SGuillaume Chatelet if (LIBC_UNLIKELY(x_abs <= 0x3dcc'0000U)) { 436c1fc7e4SKirill Okhotnikov // |x| <= 2^-26 4429f8e076SGuillaume Chatelet if (LIBC_UNLIKELY(x_abs <= 0x3280'0000U)) { 457d11a592SAlex Brachet return static_cast<float>(LIBC_UNLIKELY(x_abs == 0) 467d11a592SAlex Brachet ? x 477d11a592SAlex Brachet : (x + 0x1.5555555555555p-2 * x * x * x)); 486c1fc7e4SKirill Okhotnikov } 496c1fc7e4SKirill Okhotnikov 506c1fc7e4SKirill Okhotnikov double xdbl = x; 516c1fc7e4SKirill Okhotnikov double x2 = xdbl * xdbl; 526c1fc7e4SKirill Okhotnikov // Pure Taylor series. 536c1fc7e4SKirill Okhotnikov double pe = fputil::polyeval(x2, 0.0, 0x1.5555555555555p-2, 546c1fc7e4SKirill Okhotnikov 0x1.999999999999ap-3, 0x1.2492492492492p-3, 556c1fc7e4SKirill Okhotnikov 0x1.c71c71c71c71cp-4, 0x1.745d1745d1746p-4); 567d11a592SAlex Brachet return static_cast<float>(fputil::multiply_add(xdbl, pe, xdbl)); 576c1fc7e4SKirill Okhotnikov } 586c1fc7e4SKirill Okhotnikov double xdbl = x; 597d11a592SAlex Brachet return static_cast<float>(0.5 * log_eval((xdbl + 1.0) / (xdbl - 1.0))); 606c1fc7e4SKirill Okhotnikov } 616c1fc7e4SKirill Okhotnikov 62*5ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL 63