Skip to content

Commit 6c54d4b

Browse files
committed
[libc][math][c23] Update for comments.
1 parent bb40bb4 commit 6c54d4b

File tree

3 files changed

+42
-19
lines changed

3 files changed

+42
-19
lines changed

libc/src/math/generic/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3951,7 +3951,6 @@ add_entrypoint_object(
39513951
HDRS
39523952
../acoshf16.h
39533953
DEPENDS
3954-
.common_constants
39553954
.explogxf
39563955
libc.hdr.errno_macros
39573956
libc.hdr.fenv_macros

libc/src/math/generic/acoshf16.cpp

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,27 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "src/math/acoshf16.h"
10+
#include "hdr/errno_macros.h"
11+
#include "hdr/fenv_macros.h"
1012
#include "src/__support/FPUtil/FEnvImpl.h"
1113
#include "src/__support/FPUtil/FPBits.h"
1214
#include "src/__support/FPUtil/cast.h"
1315
#include "src/__support/FPUtil/except_value_utils.h"
14-
#include "src/__support/FPUtil/generic/sqrt.h"
1516
#include "src/__support/FPUtil/multiply_add.h"
17+
#include "src/__support/FPUtil/sqrt.h"
1618
#include "src/__support/macros/optimization.h"
1719
#include "src/math/generic/explogxf.h"
1820

1921
namespace LIBC_NAMESPACE_DECL {
2022

2123
static constexpr size_t N_EXCEPTS = 2;
22-
static constexpr fputil::ExceptValues<float16, N_EXCEPTS> ACOSHF16_EXCEPTS{
23-
{// (input, RZ output, RU offset, RD offset, RN offset)
24-
{0x41B7, 0x3ED8, 1, 0, 0},
25-
{0x3CE4, 0x393E, 1, 0, 1}}};
24+
static constexpr fputil::ExceptValues<float16, N_EXCEPTS> ACOSHF16_EXCEPTS{{
25+
// (input, RZ output, RU offset, RD offset, RN offset)
26+
// x = 0x1.6ep+1, acoshf16(x) = 0x1.dbp+0 (RZ)
27+
{0x41B7, 0x3ED8, 1, 0, 0},
28+
// x = 0x1.c8p+0, acoshf16(x) = 0x1.27cp-1 (RZ)
29+
{0x3CE4, 0x393E, 1, 0, 1},
30+
}};
2631

2732
LLVM_LIBC_FUNCTION(float16, acoshf16, (float16 x)) {
2833
using FPBits = fputil::FPBits<float16>;
@@ -58,29 +63,48 @@ LLVM_LIBC_FUNCTION(float16, acoshf16, (float16 x)) {
5863

5964
// acosh(1.0) exactly equals 0.0
6065
if (LIBC_UNLIKELY(x_u == 0x3c00U))
61-
return float16(0.0f);
66+
return FPBits::zero().get_val();
6267

6368
if (auto r = ACOSHF16_EXCEPTS.lookup(xbits.uintval());
6469
LIBC_UNLIKELY(r.has_value()))
6570
return r.value();
6671

67-
float xf32 = x;
72+
float xf = x;
6873
// High precision for inputs very close to 1.0
69-
if (LIBC_UNLIKELY(xf32 < 1.25f)) {
70-
float delta = xf32 - 1.0f;
74+
// For inputs close to 1 (1 <= x < 1.25), use polynomial approximation:
75+
//
76+
// Step-by-step derivation:
77+
// 1. Let y = acosh(x), thus x = cosh(y).
78+
//
79+
// 2. Rewrite cosh identity using exponential form:
80+
// cosh(y) = (e^y + e^{-y}) / 2
81+
// For y close to 0, let y = sqrt(2 * delta), thus:
82+
// x = cosh(y) ≈ 1 + delta (since cosh(0) = 1, and delta is small)
83+
// thus delta = x - 1.
84+
//
85+
// 3: Express y in terms of delta (for small delta):
86+
// y ≈ sqrt(2 * delta)
87+
//
88+
// 4: Expand acosh(1 + delta) using a Taylor expansion around delta = 0:
89+
// acosh(1 + delta) ≈ sqrt(2 * delta) * P(delta), where P(delta)
90+
// is a polynomial approximation obtained by fitting the function
91+
// precisely in the interval [0, 0.25].
92+
//
93+
// Because delta = x - 1 and 0 <= delta < 0.25, the polynomial approximation
94+
// remains numerically stable and accurate in this domain, ensuring high
95+
// precision.
96+
if (LIBC_UNLIKELY(xf < 1.25f)) {
97+
float delta = xf - 1.0f;
7198
float sqrt_2_delta = fputil::sqrt<float>(2.0 * delta);
72-
float x2 = delta;
73-
float pe =
74-
fputil::polyeval(x2, 0x1.000000p+0f, -0x1.55551ap-4f, 0x1.33160cp-6f,
75-
-0x1.6890f4p-8f, 0x1.8f3a62p-10f);
99+
float pe = fputil::polyeval(delta, 0x1p+0f, -0x1.55551ap-4f, 0x1.33160cp-6f,
100+
-0x1.6890f4p-8f, 0x1.8f3a62p-10f);
76101
float approx = sqrt_2_delta * pe;
77102
return fputil::cast<float16>(approx);
78103
}
79104

80-
// Standard computation for general case.
81-
float sqrt_term =
82-
fputil::sqrt<float>(fputil::multiply_add(xf32, xf32, -1.0f));
83-
float result = static_cast<float>(log_eval(xf32 + sqrt_term));
105+
// acosh(x) = log(x + sqrt(x^2 - 1))
106+
float sqrt_term = fputil::sqrt<float>(fputil::multiply_add(xf, xf, -1.0f));
107+
float result = static_cast<float>(log_eval(xf + sqrt_term));
84108

85109
return fputil::cast<float16>(result);
86110
}

libc/test/src/math/smoke/acoshf16_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ TEST_F(LlvmLibcAcoshf16Test, SpecialNumbers) {
2121
EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::acoshf16(sNaN), FE_INVALID);
2222
EXPECT_MATH_ERRNO(0);
2323

24-
EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::acoshf16(zero));
24+
EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::acoshf16(zero), FE_INVALID);
2525
EXPECT_MATH_ERRNO(EDOM);
2626

2727
EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::acoshf16(neg_zero));

0 commit comments

Comments
 (0)