1*71db0c75SAndroid Build Coastguard Worker //===-- Single-precision atanh function -----------------------------------===// 2*71db0c75SAndroid Build Coastguard Worker // 3*71db0c75SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*71db0c75SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information. 5*71db0c75SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*71db0c75SAndroid Build Coastguard Worker // 7*71db0c75SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 8*71db0c75SAndroid Build Coastguard Worker 9*71db0c75SAndroid Build Coastguard Worker #include "src/math/atanhf.h" 10*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/FPBits.h" 11*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/config.h" 12*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY 13*71db0c75SAndroid Build Coastguard Worker #include "src/math/generic/explogxf.h" 14*71db0c75SAndroid Build Coastguard Worker 15*71db0c75SAndroid Build Coastguard Worker namespace LIBC_NAMESPACE_DECL { 16*71db0c75SAndroid Build Coastguard Worker 17*71db0c75SAndroid Build Coastguard Worker LLVM_LIBC_FUNCTION(float, atanhf, (float x)) { 18*71db0c75SAndroid Build Coastguard Worker using FPBits = typename fputil::FPBits<float>; 19*71db0c75SAndroid Build Coastguard Worker 20*71db0c75SAndroid Build Coastguard Worker FPBits xbits(x); 21*71db0c75SAndroid Build Coastguard Worker Sign sign = xbits.sign(); 22*71db0c75SAndroid Build Coastguard Worker uint32_t x_abs = xbits.abs().uintval(); 23*71db0c75SAndroid Build Coastguard Worker 24*71db0c75SAndroid Build Coastguard Worker // |x| >= 1.0 25*71db0c75SAndroid Build Coastguard Worker if (LIBC_UNLIKELY(x_abs >= 0x3F80'0000U)) { 26*71db0c75SAndroid Build Coastguard Worker if (xbits.is_nan()) { 27*71db0c75SAndroid Build Coastguard Worker return x; 28*71db0c75SAndroid Build Coastguard Worker } 29*71db0c75SAndroid Build Coastguard Worker // |x| == 1.0 30*71db0c75SAndroid Build Coastguard Worker if (x_abs == 0x3F80'0000U) { 31*71db0c75SAndroid Build Coastguard Worker fputil::set_errno_if_required(ERANGE); 32*71db0c75SAndroid Build Coastguard Worker fputil::raise_except_if_required(FE_DIVBYZERO); 33*71db0c75SAndroid Build Coastguard Worker return FPBits::inf(sign).get_val(); 34*71db0c75SAndroid Build Coastguard Worker } else { 35*71db0c75SAndroid Build Coastguard Worker fputil::set_errno_if_required(EDOM); 36*71db0c75SAndroid Build Coastguard Worker fputil::raise_except_if_required(FE_INVALID); 37*71db0c75SAndroid Build Coastguard Worker return FPBits::quiet_nan().get_val(); 38*71db0c75SAndroid Build Coastguard Worker } 39*71db0c75SAndroid Build Coastguard Worker } 40*71db0c75SAndroid Build Coastguard Worker 41*71db0c75SAndroid Build Coastguard Worker // |x| < ~0.10 42*71db0c75SAndroid Build Coastguard Worker if (LIBC_UNLIKELY(x_abs <= 0x3dcc'0000U)) { 43*71db0c75SAndroid Build Coastguard Worker // |x| <= 2^-26 44*71db0c75SAndroid Build Coastguard Worker if (LIBC_UNLIKELY(x_abs <= 0x3280'0000U)) { 45*71db0c75SAndroid Build Coastguard Worker return static_cast<float>(LIBC_UNLIKELY(x_abs == 0) 46*71db0c75SAndroid Build Coastguard Worker ? x 47*71db0c75SAndroid Build Coastguard Worker : (x + 0x1.5555555555555p-2 * x * x * x)); 48*71db0c75SAndroid Build Coastguard Worker } 49*71db0c75SAndroid Build Coastguard Worker 50*71db0c75SAndroid Build Coastguard Worker double xdbl = x; 51*71db0c75SAndroid Build Coastguard Worker double x2 = xdbl * xdbl; 52*71db0c75SAndroid Build Coastguard Worker // Pure Taylor series. 53*71db0c75SAndroid Build Coastguard Worker double pe = fputil::polyeval(x2, 0.0, 0x1.5555555555555p-2, 54*71db0c75SAndroid Build Coastguard Worker 0x1.999999999999ap-3, 0x1.2492492492492p-3, 55*71db0c75SAndroid Build Coastguard Worker 0x1.c71c71c71c71cp-4, 0x1.745d1745d1746p-4); 56*71db0c75SAndroid Build Coastguard Worker return static_cast<float>(fputil::multiply_add(xdbl, pe, xdbl)); 57*71db0c75SAndroid Build Coastguard Worker } 58*71db0c75SAndroid Build Coastguard Worker double xdbl = x; 59*71db0c75SAndroid Build Coastguard Worker return static_cast<float>(0.5 * log_eval((xdbl + 1.0) / (xdbl - 1.0))); 60*71db0c75SAndroid Build Coastguard Worker } 61*71db0c75SAndroid Build Coastguard Worker 62*71db0c75SAndroid Build Coastguard Worker } // namespace LIBC_NAMESPACE_DECL 63