aboutsummaryrefslogtreecommitdiff
path: root/pl/math/acoshf_2u8.c
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2023-01-25 20:51:23 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-01-25 20:51:23 +0000
commit8783f524beaad825ac1bddeb93cef35b5f793513 (patch)
tree945eb1832687ad5eb97c433013617dbe107718e5 /pl/math/acoshf_2u8.c
parent0bc581b0e4f509c96bffa7af329087ae2b4bfb97 (diff)
parent62662f115a17a5548402fcd02f3b7e1b9b38e087 (diff)
downloadarm-optimized-routines-8783f524beaad825ac1bddeb93cef35b5f793513.tar.gz
Upgrade ARM-software/optimized-routines to v23.01 am: 62662f115a
Original change: https://android-review.googlesource.com/c/platform/external/arm-optimized-routines/+/2402215 Change-Id: Ic29e1a6f8a0485f6317699bfda38fb79e7022ee1 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
Diffstat (limited to 'pl/math/acoshf_2u8.c')
-rw-r--r--pl/math/acoshf_2u8.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/pl/math/acoshf_2u8.c b/pl/math/acoshf_2u8.c
new file mode 100644
index 0000000..c9cded7
--- /dev/null
+++ b/pl/math/acoshf_2u8.c
@@ -0,0 +1,63 @@
+/*
+ * Single-precision acosh(x) function.
+ *
+ * Copyright (c) 2022-2023, Arm Limited.
+ * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
+ */
+
+#include "math_config.h"
+#include "pl_sig.h"
+#include "pl_test.h"
+
+#define Ln2 (0x1.62e4p-1f)
+#define MinusZero 0x80000000
+#define SquareLim 0x5f800000 /* asuint(0x1p64). */
+#define Two 0x40000000
+
+/* Single-precision log from math/. */
+float
+optr_aor_log_f32 (float);
+
+/* Single-precision log(1+x) from pl/math. */
+float
+log1pf (float);
+
+/* acoshf approximation using a variety of approaches on different intervals:
+
+ x >= 2^64: We cannot square x without overflow. For huge x, sqrt(x*x - 1) is
+ close enough to x that we can calculate the result by ln(2x) == ln(x) +
+ ln(2). The greatest error in the region is 0.94 ULP:
+ acoshf(0x1.15f706p+92) got 0x1.022e14p+6 want 0x1.022e16p+6.
+
+ x > 2: Calculate the result directly using definition of asinh(x) = ln(x +
+ sqrt(x*x - 1)). Greatest error in this region is 1.30 ULP:
+ acoshf(0x1.249d8p+1) got 0x1.77e1aep+0 want 0x1.77e1bp+0.
+
+ 0 <= x <= 2: Calculate the result using log1p. For x < 1, acosh(x) is
+ undefined. For 1 <= x <= 2, the greatest error is 2.78 ULP:
+ acoshf(0x1.07887p+0) got 0x1.ef9e9cp-3 want 0x1.ef9ea2p-3. */
+float
+acoshf (float x)
+{
+ uint32_t ix = asuint (x);
+
+ if (unlikely (ix >= MinusZero))
+ return __math_invalidf (x);
+
+ if (unlikely (ix >= SquareLim))
+ return optr_aor_log_f32 (x) + Ln2;
+
+ if (ix > Two)
+ return optr_aor_log_f32 (x + sqrtf (x * x - 1));
+
+ float xm1 = x - 1;
+ return log1pf (xm1 + sqrtf (2 * xm1 + xm1 * xm1));
+}
+
+PL_SIG (S, F, 1, acosh, 1.0, 10.0)
+PL_TEST_ULP (acoshf, 2.30)
+PL_TEST_INTERVAL (acoshf, 0, 1, 100)
+PL_TEST_INTERVAL (acoshf, 1, 2, 10000)
+PL_TEST_INTERVAL (acoshf, 2, 0x1p64, 100000)
+PL_TEST_INTERVAL (acoshf, 0x1p64, inf, 100000)
+PL_TEST_INTERVAL (acoshf, -0, -inf, 10000)