Skip to content

Commit 8ef8dd4

Browse files
committed
implement tanpif
1 parent c358979 commit 8ef8dd4

File tree

12 files changed

+248
-1
lines changed

12 files changed

+248
-1
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,7 @@ set(TARGET_LIBM_ENTRYPOINTS
625625
libc.src.math.tan
626626
libc.src.math.tanf
627627
libc.src.math.tanhf
628+
libc.src.math.tanpif
628629
libc.src.math.totalorder
629630
libc.src.math.totalorderf
630631
libc.src.math.totalorderl

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,7 @@ set(TARGET_LIBM_ENTRYPOINTS
657657
libc.src.math.tan
658658
libc.src.math.tanf
659659
libc.src.math.tanhf
660+
libc.src.math.tanpif
660661
libc.src.math.totalorder
661662
libc.src.math.totalorderf
662663
libc.src.math.totalorderl

libc/docs/headers/math/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ Higher Math Functions
349349
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
350350
| tanh | |check| | | | |check| | | 7.12.5.6 | F.10.2.6 |
351351
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
352-
| tanpi | | | | |check| | | 7.12.4.14 | F.10.1.14 |
352+
| tanpi | |check| | | | |check| | | 7.12.4.14 | F.10.1.14 |
353353
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
354354
| tgamma | | | | | | 7.12.8.4 | F.10.5.4 |
355355
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+

libc/include/math.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2524,6 +2524,12 @@ functions:
25242524
arguments:
25252525
- type: _Float16
25262526
guard: LIBC_TYPES_HAS_FLOAT16
2527+
- name: tanpif
2528+
standards:
2529+
- stdc
2530+
return_type: float
2531+
arguments:
2532+
- type: float
25272533
- name: tanpif16
25282534
standards:
25292535
- stdc

libc/src/math/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,8 @@ add_math_entrypoint_object(tanf16)
519519
add_math_entrypoint_object(tanh)
520520
add_math_entrypoint_object(tanhf)
521521
add_math_entrypoint_object(tanhf16)
522+
523+
add_math_entrypoint_object(tanpif)
522524
add_math_entrypoint_object(tanpif16)
523525

524526
add_math_entrypoint_object(tgamma)

libc/src/math/generic/CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,21 @@ add_entrypoint_object(
606606
libc.src.__support.macros.properties.types
607607
)
608608

609+
add_entrypoint_object(
610+
tanpif
611+
SRCS
612+
tanpif.cpp
613+
HDRS
614+
../tanpif.h
615+
DEPENDS
616+
.sincosf_utils
617+
libc.src.__support.FPUtil.except_value_utils
618+
libc.src.__support.FPUtil.fenv_impl
619+
libc.src.__support.FPUtil.fp_bits
620+
libc.src.__support.FPUtil.multiply_add
621+
libc.src.__support.macros.optimization
622+
)
623+
609624
add_entrypoint_object(
610625
tanpif16
611626
SRCS

libc/src/math/generic/tanpif.cpp

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//===-- Single-precision tanpi function -----------------------------------===//
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/math/tanpif.h"
10+
#include "sincosf_utils.h"
11+
#include "src/__support/FPUtil/FEnvImpl.h"
12+
#include "src/__support/FPUtil/FPBits.h"
13+
#include "src/__support/FPUtil/cast.h"
14+
#include "src/__support/FPUtil/except_value_utils.h"
15+
#include "src/__support/FPUtil/multiply_add.h"
16+
#include "src/__support/common.h"
17+
#include "src/__support/macros/config.h"
18+
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
19+
20+
namespace LIBC_NAMESPACE_DECL {
21+
22+
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
23+
constexpr size_t N_EXCEPTS = 3;
24+
25+
constexpr fputil::ExceptValues<float, N_EXCEPTS> TANPIF_EXCEPTS{{
26+
// (input, RZ output, RU offset, RD offset, RN offset)
27+
{0x38F26685, 0x39BE6182, 1, 0, 0},
28+
{0x3E933802, 0x3FA267DD, 1, 0, 0},
29+
{0x3F3663FF, 0xBFA267DD, 0, 1, 0},
30+
}};
31+
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
32+
33+
LLVM_LIBC_FUNCTION(float, tanpif, (float x)) {
34+
using FPBits = typename fputil::FPBits<float>;
35+
FPBits xbits(x);
36+
37+
uint32_t x_u = xbits.uintval();
38+
uint32_t x_abs = x_u & 0x7fff'ffffU;
39+
double xd = static_cast<double>(xbits.get_val());
40+
41+
// Handle exceptional values
42+
if (LIBC_UNLIKELY(x_abs <= 0x3F3663FF)) {
43+
if (LIBC_UNLIKELY(x_abs == 0U))
44+
return x;
45+
46+
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
47+
bool x_sign = x_u >> 31;
48+
49+
if (auto r = TANPIF_EXCEPTS.lookup_odd(x_abs, x_sign);
50+
LIBC_UNLIKELY(r.has_value()))
51+
return r.value();
52+
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
53+
}
54+
55+
// Numbers greater or equal to 2^23 are always integers, or infinity, or NaN
56+
if (LIBC_UNLIKELY(x_abs >= 0x4B00'0000)) {
57+
// x is inf or NaN.
58+
if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
59+
if (xbits.is_signaling_nan()) {
60+
fputil::raise_except_if_required(FE_INVALID);
61+
return FPBits::quiet_nan().get_val();
62+
}
63+
64+
if (x_abs == 0x7f80'0000U) {
65+
fputil::set_errno_if_required(EDOM);
66+
fputil::raise_except_if_required(FE_INVALID);
67+
}
68+
69+
return x + FPBits::quiet_nan().get_val();
70+
}
71+
72+
return FPBits::zero(xbits.sign()).get_val();
73+
}
74+
75+
// Range reduction:
76+
// For |x| > 1/32, we perform range reduction as follows:
77+
// Find k and y such that:
78+
// x = (k + y) * 1/32
79+
// k is an integer
80+
// |y| < 0.5
81+
//
82+
// This is done by performing:
83+
// k = round(x * 32)
84+
// y = x * 32 - k
85+
//
86+
// Once k and y are computed, we then deduce the answer by the formula:
87+
// tan(x) = sin(x) / cos(x)
88+
// = (sin_y * cos_k + cos_y * sin_k) / (cos_y * cos_k - sin_y * sin_k)
89+
double sin_k, cos_k, sin_y, cosm1_y;
90+
sincospif_eval(xd, sin_k, cos_k, sin_y, cosm1_y);
91+
92+
if (LIBC_UNLIKELY(sin_y == 0 && cos_k == 0)) {
93+
fputil::set_errno_if_required(EDOM);
94+
fputil::raise_except_if_required(FE_DIVBYZERO);
95+
96+
int32_t x_mp5_u = static_cast<int32_t>(x - 0.5);
97+
return ((x_mp5_u & 0x1) ? -1 : 1) * FPBits::inf().get_val();
98+
}
99+
100+
using fputil::multiply_add;
101+
return fputil::cast<float>(
102+
multiply_add(sin_y, cos_k, multiply_add(cosm1_y, sin_k, sin_k)) /
103+
multiply_add(sin_y, -sin_k, multiply_add(cosm1_y, cos_k, cos_k)));
104+
}
105+
106+
} // namespace LIBC_NAMESPACE_DECL

libc/src/math/tanpif.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for tanpif ------------------------*- C++ -*-===//
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+
#ifndef LLVM_LIBC_SRC_MATH_TANPIF_H
10+
#define LLVM_LIBC_SRC_MATH_TANPIF_H
11+
12+
#include "src/__support/macros/config.h"
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
16+
float tanpif(float x);
17+
18+
} // namespace LIBC_NAMESPACE_DECL
19+
20+
#endif // LLVM_LIBC_SRC_MATH_TANPIF_H

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,22 @@ add_fp_unittest(
122122
-lpthread
123123
)
124124

125+
add_fp_unittest(
126+
tanpif_test
127+
NO_RUN_POSTBUILD
128+
NEED_MPFR
129+
SUITE
130+
libc_math_exhaustive_tests
131+
SRCS
132+
tanpif_test.cpp
133+
DEPENDS
134+
.exhaustive_test
135+
libc.src.math.tanpif
136+
libc.src.__support.FPUtil.fp_bits
137+
LINK_LIBRARIES
138+
-lpthread
139+
)
140+
125141
add_fp_unittest(
126142
erff_test
127143
NO_RUN_POSTBUILD
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===-- Exhaustive test for tanpif ----------------------------------------===//
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 "exhaustive_test.h"
10+
#include "src/math/tanpif.h"
11+
#include "utils/MPFRWrapper/MPFRUtils.h"
12+
13+
namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
14+
15+
using LlvmLibcTanpifExhaustiveTest =
16+
LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Tanpi,
17+
LIBC_NAMESPACE::tanpif>;
18+
19+
// Range: [0, Inf];
20+
static constexpr uint32_t POS_START = 0x0000'0000U;
21+
static constexpr uint32_t POS_STOP = 0x7f80'0000U;
22+
23+
TEST_F(LlvmLibcTanpifExhaustiveTest, PostiveRange) {
24+
test_full_range_all_roundings(POS_START, POS_STOP);
25+
}
26+
27+
// Range: [-Inf, 0];
28+
static constexpr uint32_t NEG_START = 0xb000'0000U;
29+
static constexpr uint32_t NEG_STOP = 0xff80'0000U;
30+
31+
TEST_F(LlvmLibcTanpifExhaustiveTest, NegativeRange) {
32+
test_full_range_all_roundings(NEG_START, NEG_STOP);
33+
}

0 commit comments

Comments
 (0)