Path: blob/main/contrib/arm-optimized-routines/math/aarch64/advsimd/coshf.c
48378 views
/*1* Single-precision vector cosh(x) function.2*3* Copyright (c) 2022-2024, Arm Limited.4* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception5*/67#include "v_expf_inline.h"8#include "v_math.h"9#include "test_sig.h"10#include "test_defs.h"1112static const struct data13{14struct v_expf_data expf_consts;15uint32x4_t tiny_bound;16float32x4_t bound;17#if WANT_SIMD_EXCEPT18uint32x4_t special_bound;19#endif20} data = {21.expf_consts = V_EXPF_DATA,22.tiny_bound = V4 (0x20000000), /* 0x1p-63: Round to 1 below this. */23/* 0x1.5a92d8p+6: expf overflows above this, so have to use special case. */24.bound = V4 (0x1.5a92d8p+6),25#if WANT_SIMD_EXCEPT26.special_bound = V4 (0x42ad496c),27#endif28};2930#if !WANT_SIMD_EXCEPT31static float32x4_t NOINLINE VPCS_ATTR32special_case (float32x4_t x, float32x4_t half_t, float32x4_t half_over_t,33uint32x4_t special)34{35return v_call_f32 (coshf, x, vaddq_f32 (half_t, half_over_t), special);36}37#endif3839/* Single-precision vector cosh, using vector expf.40Maximum error is 2.38 ULP:41_ZGVnN4v_coshf (0x1.e8001ep+1) got 0x1.6a491ep+442want 0x1.6a4922p+4. */43float32x4_t VPCS_ATTR NOINLINE V_NAME_F1 (cosh) (float32x4_t x)44{45const struct data *d = ptr_barrier (&data);4647#if WANT_SIMD_EXCEPT48/* If fp exceptions are to be triggered correctly, fall back to the scalar49variant for all inputs if any input is a special value or above the bound50at which expf overflows. */51float32x4_t ax = vabsq_f32 (x);52uint32x4_t iax = vreinterpretq_u32_f32 (ax);53uint32x4_t special = vcgeq_u32 (iax, d->special_bound);54if (unlikely (v_any_u32 (special)))55return v_call_f32 (coshf, x, x, v_u32 (-1));5657uint32x4_t tiny = vcleq_u32 (iax, d->tiny_bound);58/* If any input is tiny, avoid underflow exception by fixing tiny lanes of59input to 0, which will generate no exceptions. */60if (unlikely (v_any_u32 (tiny)))61ax = v_zerofy_f32 (ax, tiny);62float32x4_t t = v_expf_inline (ax, &d->expf_consts);63#else64uint32x4_t special = vcageq_f32 (x, d->bound);65float32x4_t t = v_expf_inline (x, &d->expf_consts);66#endif6768/* Calculate cosh by exp(x) / 2 + exp(-x) / 2. */69float32x4_t half_t = vmulq_n_f32 (t, 0.5);70float32x4_t half_over_t = vdivq_f32 (v_f32 (0.5), t);7172#if WANT_SIMD_EXCEPT73if (unlikely (v_any_u32 (tiny)))74return vbslq_f32 (tiny, v_f32 (1), vaddq_f32 (half_t, half_over_t));75#else76if (unlikely (v_any_u32 (special)))77return special_case (x, half_t, half_over_t, special);78#endif7980return vaddq_f32 (half_t, half_over_t);81}8283HALF_WIDTH_ALIAS_F1 (cosh)8485TEST_SIG (V, F, 1, cosh, -10.0, 10.0)86TEST_ULP (V_NAME_F1 (cosh), 1.89)87TEST_DISABLE_FENV_IF_NOT (V_NAME_F1 (cosh), WANT_SIMD_EXCEPT)88TEST_SYM_INTERVAL (V_NAME_F1 (cosh), 0, 0x1p-63, 100)89TEST_SYM_INTERVAL (V_NAME_F1 (cosh), 0x1p-63, 1, 1000)90TEST_SYM_INTERVAL (V_NAME_F1 (cosh), 1, 0x1.5a92d8p+6, 80000)91TEST_SYM_INTERVAL (V_NAME_F1 (cosh), 0x1.5a92d8p+6, inf, 2000)929394