Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/arm-optimized-routines/math/aarch64/advsimd/asinhf.c
48375 views
1
/*
2
* Single-precision vector asinh(x) function.
3
*
4
* Copyright (c) 2022-2024, Arm Limited.
5
* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
6
*/
7
8
#include "v_math.h"
9
#include "test_sig.h"
10
#include "test_defs.h"
11
#include "v_log1pf_inline.h"
12
13
const static struct data
14
{
15
struct v_log1pf_data log1pf_consts;
16
float32x4_t one;
17
uint32x4_t big_bound;
18
#if WANT_SIMD_EXCEPT
19
uint32x4_t tiny_bound;
20
#endif
21
} data = {
22
.one = V4 (1),
23
.log1pf_consts = V_LOG1PF_CONSTANTS_TABLE,
24
.big_bound = V4 (0x5f800000), /* asuint(0x1p64). */
25
#if WANT_SIMD_EXCEPT
26
.tiny_bound = V4 (0x30800000) /* asuint(0x1p-30). */
27
#endif
28
};
29
30
static float32x4_t NOINLINE VPCS_ATTR
31
special_case (float32x4_t x, uint32x4_t sign, float32x4_t y,
32
uint32x4_t special, const struct data *d)
33
{
34
return v_call_f32 (
35
asinhf, x,
36
vreinterpretq_f32_u32 (veorq_u32 (
37
sign, vreinterpretq_u32_f32 (log1pf_inline (y, &d->log1pf_consts)))),
38
special);
39
}
40
41
/* Single-precision implementation of vector asinh(x), using vector log1p.
42
Worst-case error is 2.59 ULP:
43
_ZGVnN4v_asinhf(0x1.d86124p-3) got 0x1.d449bep-3
44
want 0x1.d449c4p-3. */
45
float32x4_t VPCS_ATTR NOINLINE V_NAME_F1 (asinh) (float32x4_t x)
46
{
47
const struct data *dat = ptr_barrier (&data);
48
float32x4_t ax = vabsq_f32 (x);
49
uint32x4_t iax = vreinterpretq_u32_f32 (ax);
50
uint32x4_t special = vcgeq_u32 (iax, dat->big_bound);
51
uint32x4_t sign = veorq_u32 (vreinterpretq_u32_f32 (x), iax);
52
float32x4_t special_arg = x;
53
54
#if WANT_SIMD_EXCEPT
55
/* Sidestep tiny and large values to avoid inadvertently triggering
56
under/overflow. */
57
special = vorrq_u32 (special, vcltq_u32 (iax, dat->tiny_bound));
58
if (unlikely (v_any_u32 (special)))
59
{
60
ax = v_zerofy_f32 (ax, special);
61
x = v_zerofy_f32 (x, special);
62
}
63
#endif
64
65
/* asinh(x) = log(x + sqrt(x * x + 1)).
66
For positive x, asinh(x) = log1p(x + x * x / (1 + sqrt(x * x + 1))). */
67
float32x4_t d
68
= vaddq_f32 (v_f32 (1), vsqrtq_f32 (vfmaq_f32 (dat->one, ax, ax)));
69
float32x4_t y = vaddq_f32 (ax, vdivq_f32 (vmulq_f32 (ax, ax), d));
70
71
if (unlikely (v_any_u32 (special)))
72
return special_case (special_arg, sign, y, special, dat);
73
return vreinterpretq_f32_u32 (veorq_u32 (
74
sign, vreinterpretq_u32_f32 (log1pf_inline (y, &dat->log1pf_consts))));
75
}
76
77
HALF_WIDTH_ALIAS_F1 (asinh)
78
79
TEST_SIG (V, F, 1, asinh, -10.0, 10.0)
80
TEST_ULP (V_NAME_F1 (asinh), 2.10)
81
TEST_DISABLE_FENV_IF_NOT (V_NAME_F1 (asinh), WANT_SIMD_EXCEPT)
82
TEST_INTERVAL (V_NAME_F1 (asinh), 0, 0x1p-12, 40000)
83
TEST_INTERVAL (V_NAME_F1 (asinh), 0x1p-12, 1.0, 40000)
84
TEST_INTERVAL (V_NAME_F1 (asinh), 1.0, 0x1p11, 40000)
85
TEST_INTERVAL (V_NAME_F1 (asinh), 0x1p11, inf, 40000)
86
TEST_INTERVAL (V_NAME_F1 (asinh), -0, -0x1p-12, 20000)
87
TEST_INTERVAL (V_NAME_F1 (asinh), -0x1p-12, -1.0, 20000)
88
TEST_INTERVAL (V_NAME_F1 (asinh), -1.0, -0x1p11, 20000)
89
TEST_INTERVAL (V_NAME_F1 (asinh), -0x1p11, -inf, 20000)
90
91