1*f3087befSAndrew Turner /*
2*f3087befSAndrew Turner * Single-precision acosh(x) function.
3*f3087befSAndrew Turner *
4*f3087befSAndrew Turner * Copyright (c) 2022-2024, Arm Limited.
5*f3087befSAndrew Turner * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
6*f3087befSAndrew Turner */
7*f3087befSAndrew Turner
8*f3087befSAndrew Turner #include "math_config.h"
9*f3087befSAndrew Turner #include "test_sig.h"
10*f3087befSAndrew Turner #include "test_defs.h"
11*f3087befSAndrew Turner
12*f3087befSAndrew Turner #define Ln2 (0x1.62e4p-1f)
13*f3087befSAndrew Turner #define MinusZero 0x80000000
14*f3087befSAndrew Turner #define SquareLim 0x5f800000 /* asuint(0x1p64). */
15*f3087befSAndrew Turner #define Two 0x40000000
16*f3087befSAndrew Turner
17*f3087befSAndrew Turner /* acoshf approximation using a variety of approaches on different intervals:
18*f3087befSAndrew Turner
19*f3087befSAndrew Turner x >= 2^64: We cannot square x without overflow. For huge x, sqrt(x*x - 1) is
20*f3087befSAndrew Turner close enough to x that we can calculate the result by ln(2x) == ln(x) +
21*f3087befSAndrew Turner ln(2). The greatest error in the region is 0.94 ULP:
22*f3087befSAndrew Turner acoshf(0x1.15f706p+92) got 0x1.022e14p+6 want 0x1.022e16p+6.
23*f3087befSAndrew Turner
24*f3087befSAndrew Turner x > 2: Calculate the result directly using definition of asinh(x) = ln(x +
25*f3087befSAndrew Turner sqrt(x*x - 1)). Greatest error in this region is 1.30 ULP:
26*f3087befSAndrew Turner acoshf(0x1.249d8p+1) got 0x1.77e1aep+0 want 0x1.77e1bp+0.
27*f3087befSAndrew Turner
28*f3087befSAndrew Turner 0 <= x <= 2: Calculate the result using log1p. For x < 1, acosh(x) is
29*f3087befSAndrew Turner undefined. For 1 <= x <= 2, the greatest error is 2.78 ULP:
30*f3087befSAndrew Turner acoshf(0x1.07887p+0) got 0x1.ef9e9cp-3 want 0x1.ef9ea2p-3. */
31*f3087befSAndrew Turner float
acoshf(float x)32*f3087befSAndrew Turner acoshf (float x)
33*f3087befSAndrew Turner {
34*f3087befSAndrew Turner uint32_t ix = asuint (x);
35*f3087befSAndrew Turner
36*f3087befSAndrew Turner if (unlikely (ix >= MinusZero))
37*f3087befSAndrew Turner return __math_invalidf (x);
38*f3087befSAndrew Turner
39*f3087befSAndrew Turner if (unlikely (ix >= SquareLim))
40*f3087befSAndrew Turner return logf (x) + Ln2;
41*f3087befSAndrew Turner
42*f3087befSAndrew Turner if (ix > Two)
43*f3087befSAndrew Turner return logf (x + sqrtf (x * x - 1));
44*f3087befSAndrew Turner
45*f3087befSAndrew Turner float xm1 = x - 1;
46*f3087befSAndrew Turner return log1pf (xm1 + sqrtf (2 * xm1 + xm1 * xm1));
47*f3087befSAndrew Turner }
48*f3087befSAndrew Turner
49*f3087befSAndrew Turner TEST_SIG (S, F, 1, acosh, 1.0, 10.0)
50*f3087befSAndrew Turner TEST_ULP (acoshf, 2.30)
51*f3087befSAndrew Turner TEST_INTERVAL (acoshf, 0, 1, 100)
52*f3087befSAndrew Turner TEST_INTERVAL (acoshf, 1, 2, 10000)
53*f3087befSAndrew Turner TEST_INTERVAL (acoshf, 2, 0x1p64, 100000)
54*f3087befSAndrew Turner TEST_INTERVAL (acoshf, 0x1p64, inf, 100000)
55*f3087befSAndrew Turner TEST_INTERVAL (acoshf, -0, -inf, 10000)
56