Skip to content

Commit 9269370

Browse files
committed
add unit tests for atanpif16
1 parent 1a5d472 commit 9269370

File tree

3 files changed

+86
-8
lines changed

3 files changed

+86
-8
lines changed

libc/src/math/generic/atanpif16.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ LLVM_LIBC_FUNCTION(float16, atanpif16, (float16 x)) {
9191

9292
double x_abs = fputil::cast<double>(xbits.abs().get_val());
9393

94-
// Polynomial coefficients for atan(x)/pi Taylor series
95-
// Generated using SymPy: series(atan(x)/pi, x, 0, 21)
94+
// polynomial coefficients for atan(x)/pi taylor series
95+
// generated using sympy: series(atan(x)/pi, x, 0, 21)
9696
constexpr double POLY_COEFFS[] = {
9797
0x1.45f306dc9c889p-2, // x^1: 1/pi
9898
-0x1.b2995e7b7b60bp-4, // x^3: -1/(3*pi)
@@ -121,9 +121,9 @@ LLVM_LIBC_FUNCTION(float16, atanpif16, (float16 x)) {
121121
return signed_result(result);
122122
}
123123

124-
// Case 2: 0.5 < |x| <= 1 - Use double-angle reduction
124+
// case 2: 0.5 < |x| <= 1 - use double-angle reduction
125125
// atan(x) = 2 * atan(x / (1 + sqrt(1 + x^2)))
126-
// So atanpi(x) = 2 * atanpi(x') where x' = x / (1 + sqrt(1 + x^2))
126+
// so atanpi(x) = 2 * atanpi(x') where x' = x / (1 + sqrt(1 + x^2))
127127
if (x_abs <= 1.0) {
128128
double x2 = x_abs * x_abs;
129129
double sqrt_term = fputil::sqrt<double>(1.0 + x2);
@@ -132,16 +132,16 @@ LLVM_LIBC_FUNCTION(float16, atanpif16, (float16 x)) {
132132
return signed_result(result);
133133
}
134134

135-
// Case 3: |x| > 1 - Use reciprocal transformation
135+
// case 3: |x| > 1 - use reciprocal transformation
136136
// atan(x) = pi/2 - atan(1/x) for x > 0
137-
// So atanpi(x) = 1/2 - atanpi(1/x)
137+
// so atanpi(x) = 1/2 - atanpi(1/x)
138138
double x_recip = 1.0 / x_abs;
139139
double result;
140140

141141
// if 1/|x| > 0.5, we need to apply Case 2 transformation to 1/|x|
142142
if (x_recip > 0.5) {
143-
double x_recip2 = x_recip * x_recip;
144-
double sqrt_term = fputil::sqrt<double>(1.0 + x_recip2);
143+
double xx_recip = x_recip * x_recip;
144+
double sqrt_term = fputil::sqrt<double>(1.0 + xx_recip);
145145
double x_prime = x_recip / (1.0 + sqrt_term);
146146
result = fputil::multiply_add(-2.0, atanpi_eval(x_prime), 0.5);
147147
} else {

libc/test/src/math/smoke/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3947,6 +3947,18 @@ add_fp_unittest(
39473947
libc.src.__support.FPUtil.fp_bits
39483948
)
39493949

3950+
add_fp_unittest(
3951+
atanpif16_test
3952+
NEED_MPFR
3953+
SUITE
3954+
libc-math-unittests
3955+
SRCS
3956+
atanpif16_test.cpp
3957+
DEPENDS
3958+
libc.src.math.atanpif16
3959+
libc.src.errno.errno
3960+
)
3961+
39503962
add_fp_unittest(
39513963
asinhf_test
39523964
SUITE
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//===-- Unittests for atanpif16 -------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/errno/libc_errno.h"
10+
#include "src/math/atanpif16.h"
11+
#include "test/UnitTest/FPMatcher.h"
12+
13+
using LlvmLibcAtanpif16Test = LIBC_NAMESPACE::testing::FPTest<float16>;
14+
15+
TEST_F(LlvmLibcAtanpif16Test, SpecialNumbers) {
16+
// zero
17+
EXPECT_FP_EQ(zero, LIBC_NAMESPACE::atanpif16(zero));
18+
EXPECT_FP_EQ(neg_zero, LIBC_NAMESPACE::atanpif16(neg_zero));
19+
20+
// NaN inputs
21+
EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
22+
LIBC_NAMESPACE::atanpif16(FPBits::quiet_nan().get_val()));
23+
24+
EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
25+
LIBC_NAMESPACE::atanpif16(FPBits::signaling_nan().get_val()));
26+
27+
// infinity inputs -> should return +/-0.5
28+
EXPECT_FP_EQ(0.5f16, LIBC_NAMESPACE::atanpif16(inf));
29+
EXPECT_FP_EQ(-0.5f16, LIBC_NAMESPACE::atanpif16(neg_inf));
30+
}
31+
32+
33+
TEST_F(LlvmLibcAtanpif16Test, SymmetryProperty) {
34+
// Test that atanpi(-x) = -atanpi(x)
35+
constexpr float16 TEST_VALS[] = {0.1f16, 0.25f16, 0.5f16, 0.75f16,
36+
1.0f16, 1.5f16, 2.0f16, 5.0f16,
37+
10.0f16, 50.0f16, 100.0f16, 1000.0f16};
38+
39+
for (float16 x : TEST_VALS) {
40+
FPBits neg_x_bits(x);
41+
neg_x_bits.set_sign(Sign::NEG);
42+
float16 neg_x = neg_x_bits.get_val();
43+
44+
float16 pos_result = LIBC_NAMESPACE::atanpif16(x);
45+
float16 neg_result = LIBC_NAMESPACE::atanpif16(neg_x);
46+
47+
EXPECT_FP_EQ(pos_result, FPBits(neg_result).abs().get_val());
48+
}
49+
}
50+
51+
TEST_F(LlvmLibcAtanpif16Test, MonotonicityProperty) {
52+
// Test that atanpi is monotonically increasing
53+
constexpr float16 TEST_VALS[] = {-1000.0f16, -100.0f16, -10.0f16, -2.0f16,
54+
-1.0f16, -0.5f16, -0.1f16, 0.0f16,
55+
0.1f16, 0.5f16, 1.0f16, 2.0f16,
56+
10.0f16, 100.0f16, 1000.0f16};
57+
58+
for (size_t i = 0; i < sizeof(TEST_VALS) / sizeof(TEST_VALS[0]) - 1; ++i) {
59+
float16 x1 = TEST_VALS[i];
60+
float16 x2 = TEST_VALS[i + 1];
61+
float16 result1 = LIBC_NAMESPACE::atanpif16(x1);
62+
float16 result2 = LIBC_NAMESPACE::atanpif16(x2);
63+
64+
EXPECT_TRUE(result1 < result2);
65+
}
66+
}

0 commit comments

Comments
 (0)