Path: blob/main/contrib/arm-optimized-routines/math/aarch64/experimental/acosh_3u.c
48378 views
/*1* Double-precision acosh(x) function.2*3* Copyright (c) 2022-2024, Arm Limited.4* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception5*/67#include "mathlib.h"8#include "math_config.h"9#include "test_sig.h"10#include "test_defs.h"1112#define Ln2 (0x1.62e42fefa39efp-1)13#define MinusZero (0x8000000000000000)14#define SquareLim (0x5fe0000000000000) /* asuint64(0x1.0p511). */15#define Two (0x4000000000000000) /* asuint64(2.0). */1617/* acosh approximation using a variety of approaches on different intervals:1819acosh(x) = ln(x + sqrt(x * x - 1)).2021x >= 2^511: We cannot square x without overflow. For huge x, sqrt(x*x - 1)22is close enough to x that we can calculate the result by ln(2x) == ln(x) +23ln(2). The greatest observed error in this region is 0.98 ULP:24acosh(0x1.1b9bf42923d1dp+853) got 0x1.28066a11a7c7fp+925want 0x1.28066a11a7c8p+9.2627x > 2: Calculate the result directly using definition of acosh(x). Greatest28observed error in this region is 1.33 ULP:29acosh(0x1.1e45d14bfcfa2p+1) got 0x1.71a06f50c34b5p+030want 0x1.71a06f50c34b6p+0.31320 <= x <= 2: Calculate the result using log1p. For x < 1, acosh(x) is33undefined. For 1 <= x <= 2, the largest observed error is 2.69 ULP:34acosh(0x1.073528248093p+0) got 0x1.e4d9bd20684f3p-335want 0x1.e4d9bd20684f6p-3. */36double37acosh (double x)38{39uint64_t ix = asuint64 (x);4041if (unlikely (ix >= MinusZero))42return __math_invalid (x);4344if (unlikely (ix >= SquareLim))45return log (x) + Ln2;4647if (ix >= Two)48return log (x + sqrt (x * x - 1));4950double xm1 = x - 1;51return log1p (xm1 + sqrt (2 * xm1 + xm1 * xm1));52}5354TEST_SIG (S, D, 1, acosh, 1.0, 10.0)55TEST_ULP (acosh, 2.19)56TEST_INTERVAL (acosh, 0, 1, 10000)57TEST_INTERVAL (acosh, 1, 2, 100000)58TEST_INTERVAL (acosh, 2, 0x1p511, 100000)59TEST_INTERVAL (acosh, 0x1p511, inf, 100000)60TEST_INTERVAL (acosh, -0, -inf, 10000)616263