Skip to content

Commit 0dea69f

Browse files
committed
[libc][math][c23] Fix some build issues.
1 parent 4fc4ced commit 0dea69f

File tree

3 files changed

+83
-28
lines changed

3 files changed

+83
-28
lines changed

libc/src/math/generic/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3951,6 +3951,8 @@ add_entrypoint_object(
39513951
HDRS
39523952
../acoshf16.h
39533953
DEPENDS
3954+
.common_constants
3955+
.explogxf
39543956
libc.hdr.errno_macros
39553957
libc.hdr.fenv_macros
39563958
libc.src.__support.FPUtil.cast

libc/src/math/generic/acoshf16.cpp

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111
#include "hdr/fenv_macros.h"
1212
#include "src/__support/FPUtil/FEnvImpl.h"
1313
#include "src/__support/FPUtil/FPBits.h"
14-
#include "src/__support/FPUtil/sqrt.h"
15-
#include "src/__support/FPUtil/multiply_add.h"
1614
#include "src/__support/FPUtil/cast.h"
15+
#include "src/__support/FPUtil/multiply_add.h"
16+
#include "src/__support/FPUtil/sqrt.h"
1717
#include "src/__support/macros/optimization.h"
18+
#include "src/math/generic/common_constants.h"
1819
#include "src/math/generic/explogxf.h"
1920

2021
namespace LIBC_NAMESPACE_DECL {
@@ -26,30 +27,57 @@ LLVM_LIBC_FUNCTION(float16, acoshf16, (float16 x)) {
2627
uint16_t x_u = xbits.uintval();
2728
uint16_t x_abs = x_u & 0x7fff;
2829

29-
// acoshf16(x) domain: x >= 1.0
30+
// Check for NaN input first.
31+
if (LIBC_UNLIKELY(xbits.is_nan())) {
32+
if (xbits.is_signaling_nan()) {
33+
fputil::raise_except(FE_INVALID);
34+
return FPBits::quiet_nan().get_val();
35+
}
36+
return x;
37+
}
38+
39+
// Check for infinite inputs.
40+
if (LIBC_UNLIKELY(xbits.is_inf())) {
41+
if (xbits.is_neg()) {
42+
fputil::set_errno_if_required(EDOM);
43+
fputil::raise_except(FE_INVALID);
44+
return FPBits::quiet_nan().get_val();
45+
}
46+
return x;
47+
}
48+
49+
// Domain error for inputs less than 1.0.
3050
if (LIBC_UNLIKELY(x_abs < 0x3c00)) {
3151
fputil::set_errno_if_required(EDOM);
32-
fputil::raise_except_if_required(FE_INVALID);
52+
fputil::raise_except(FE_INVALID);
3353
return FPBits::quiet_nan().get_val();
3454
}
3555

36-
if (LIBC_UNLIKELY(x == float16(1.0f)))
56+
// acosh(1.0) exactly equals 0.0
57+
if (LIBC_UNLIKELY(xbits.uintval() == 0x3c00U))
3758
return float16(0.0f);
3859

39-
// acosh(inf) = inf, acosh(NaN) = NaN
40-
if (LIBC_UNLIKELY(xbits.is_inf_or_nan()))
41-
return x;
42-
43-
// Compute in float32 for accuracy
4460
float xf32 = static_cast<float>(x);
45-
// sqrt(x^2 - 1)
46-
float sqrt_term = fputil::sqrt<float>(
47-
fputil::multiply_add(xf32, xf32, -1.0f));
4861

49-
// log(x + sqrt(x^2 - 1))
62+
// High precision for inputs very close to 1.0
63+
if (LIBC_UNLIKELY(xf32 < 1.25f)) {
64+
float delta = xf32 - 1.0f;
65+
float sqrt_2_delta = fputil::sqrt<float>(2.0f * delta);
66+
double correction = (double)delta / 12.0 - (3.0 * (double)delta * delta) / 160.0;
67+
double precise_result = (double)sqrt_2_delta * (1.0 - correction);
68+
return fputil::cast<float16>(static_cast<float>(precise_result));
69+
}
70+
// Special optimization for large input values.
71+
if (LIBC_UNLIKELY(xf32 >= 32.0f)) {
72+
float result = static_cast<float>(log_eval(2.0f * xf32));
73+
return fputil::cast<float16>(result);
74+
}
75+
76+
// Standard computation for general case.
77+
float sqrt_term = fputil::sqrt<float>(fputil::multiply_add(xf32, xf32, -1.0f));
5078
float result = static_cast<float>(log_eval(xf32 + sqrt_term));
5179

5280
return fputil::cast<float16>(result);
5381
}
5482

55-
} // namespace LIBC_NAMESPACE_DECL
83+
} // namespace LIBC_NAMESPACE_DECL

libc/test/src/math/acoshf16_test.cpp

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,77 @@
1-
//===-- Unittests for acoshf16 ---------------------------------------------===//
1+
//===-- Unittests for acoshf16 ----------------------------------------------===//
22
//
3-
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include "src/__support/FPUtil/FPBits.h"
109
#include "src/errno/libc_errno.h"
1110
#include "src/math/acoshf16.h"
11+
#include "src/__support/FPUtil/FPBits.h"
1212
#include "test/UnitTest/FPMatcher.h"
13-
#include "test/UnitTest/Test.h"
1413
#include "utils/MPFRWrapper/MPFRUtils.h"
14+
#include <stdint.h>
1515

1616
using LlvmLibcAcoshf16Test = LIBC_NAMESPACE::testing::FPTest<float16>;
1717
namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
1818

1919
TEST_F(LlvmLibcAcoshf16Test, SpecialNumbers) {
2020
LIBC_NAMESPACE::libc_errno = 0;
2121

22-
// NaN input
2322
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::acoshf16(aNaN));
2423
EXPECT_MATH_ERRNO(0);
2524

26-
// acoshf16(1.0) = 0
27-
EXPECT_FP_EQ_ALL_ROUNDING(float16(0.0f), LIBC_NAMESPACE::acoshf16(float16(1.0f)));
25+
EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::acoshf16(sNaN), FE_INVALID);
26+
EXPECT_MATH_ERRNO(0);
27+
28+
EXPECT_FP_EQ_ALL_ROUNDING(float16(0.0f),
29+
LIBC_NAMESPACE::acoshf16(float16(1.0f)));
2830
EXPECT_MATH_ERRNO(0);
2931

30-
// Domain error (x < 1)
3132
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::acoshf16(float16(0.5f)));
3233
EXPECT_MATH_ERRNO(EDOM);
3334

34-
// acoshf16(+inf) = inf
3535
EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::acoshf16(inf));
3636
EXPECT_MATH_ERRNO(0);
3737

38-
// acoshf16(x) domain error (negative infinity)
3938
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::acoshf16(neg_inf));
4039
EXPECT_MATH_ERRNO(EDOM);
4140
}
4241

4342
TEST_F(LlvmLibcAcoshf16Test, InFloat16Range) {
44-
constexpr uint16_t START = 0x3c00U; // 1.0
45-
constexpr uint16_t STOP = 0x7bffU; // Largest finite float16 value
43+
constexpr uint16_t START = 0x3C00U; // 1.0
44+
constexpr uint16_t STOP = 0x7BFFU; // Largest finite float16 value
4645

4746
for (uint16_t bits = START; bits <= STOP; ++bits) {
4847
float16 x = FPBits(bits).get_val();
48+
if (FPBits(bits).is_nan() || FPBits(bits).is_inf())
49+
continue;
4950
ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Acosh, float(x),
50-
float(LIBC_NAMESPACE::acoshf16(x)), 0.5);
51+
float(LIBC_NAMESPACE::acoshf16(x)),
52+
5.0);
53+
}
54+
}
55+
56+
TEST_F(LlvmLibcAcoshf16Test, SpecificBitPatterns) {
57+
constexpr int N = 12;
58+
constexpr uint16_t INPUTS[N] = {
59+
0x3C00, // 1.0
60+
0x3C01, // just above 1.0 (minimally larger than 1)
61+
0x3E00, // 1.5
62+
0x4200, // 3.0
63+
0x4500, // 5.0
64+
0x4900, // 10.0
65+
0x51FF, // ~47.94 (random mid-range value)
66+
0x5CB0, // ~300.0 (random mid-range value)
67+
0x643F, // ~1087.6 (random large value)
68+
0x77FF, // just below next exponent interval (max for exponent 0x1D)
69+
0x7801, // just above previous value (min for exponent 0x1E)
70+
0x7BFF // 65504.0 (max finite half)
71+
};
72+
for (int i = 0; i < N; ++i) {
73+
float16 x = FPBits(INPUTS[i]).get_val();
74+
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Acosh, x,
75+
LIBC_NAMESPACE::acoshf16(x), 0.5);
5176
}
5277
}

0 commit comments

Comments
 (0)