-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[libc][math][c23] implement C23 math function tanpif
#147192
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
c8ef
wants to merge
1
commit into
llvm:main
Choose a base branch
from
c8ef:tanpif
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@llvm/pr-subscribers-libc Author: Connector Switch (c8ef) ChangesThe smoke test and exhaustive test pass on x86_64 Linux. Full diff: https://github.com/llvm/llvm-project/pull/147192.diff 12 Files Affected:
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 9e042cd4a8acb..cff5b7f8312d6 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -625,6 +625,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.tan
libc.src.math.tanf
libc.src.math.tanhf
+ libc.src.math.tanpif
libc.src.math.totalorder
libc.src.math.totalorderf
libc.src.math.totalorderl
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 59c248871f83a..ea31d858dbc44 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -657,6 +657,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.tan
libc.src.math.tanf
libc.src.math.tanhf
+ libc.src.math.tanpif
libc.src.math.totalorder
libc.src.math.totalorderf
libc.src.math.totalorderl
diff --git a/libc/docs/headers/math/index.rst b/libc/docs/headers/math/index.rst
index 3cb41a6871b94..9679c4a6c807f 100644
--- a/libc/docs/headers/math/index.rst
+++ b/libc/docs/headers/math/index.rst
@@ -349,7 +349,7 @@ Higher Math Functions
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| tanh | |check| | | | |check| | | 7.12.5.6 | F.10.2.6 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
-| tanpi | | | | |check| | | 7.12.4.14 | F.10.1.14 |
+| tanpi | |check| | | | |check| | | 7.12.4.14 | F.10.1.14 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| tgamma | | | | | | 7.12.8.4 | F.10.5.4 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
diff --git a/libc/include/math.yaml b/libc/include/math.yaml
index 11bead0745954..3044ec3437ff8 100644
--- a/libc/include/math.yaml
+++ b/libc/include/math.yaml
@@ -2524,6 +2524,12 @@ functions:
arguments:
- type: _Float16
guard: LIBC_TYPES_HAS_FLOAT16
+ - name: tanpif
+ standards:
+ - stdc
+ return_type: float
+ arguments:
+ - type: float
- name: tanpif16
standards:
- stdc
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index b27b0d2b523f8..455ad3456573a 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -519,6 +519,8 @@ add_math_entrypoint_object(tanf16)
add_math_entrypoint_object(tanh)
add_math_entrypoint_object(tanhf)
add_math_entrypoint_object(tanhf16)
+
+add_math_entrypoint_object(tanpif)
add_math_entrypoint_object(tanpif16)
add_math_entrypoint_object(tgamma)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index fd1e6c0d648aa..a379110853012 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -606,6 +606,21 @@ add_entrypoint_object(
libc.src.__support.macros.properties.types
)
+add_entrypoint_object(
+ tanpif
+ SRCS
+ tanpif.cpp
+ HDRS
+ ../tanpif.h
+ DEPENDS
+ .sincosf_utils
+ libc.src.__support.FPUtil.except_value_utils
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.macros.optimization
+)
+
add_entrypoint_object(
tanpif16
SRCS
diff --git a/libc/src/math/generic/tanpif.cpp b/libc/src/math/generic/tanpif.cpp
new file mode 100644
index 0000000000000..ff1984d325d91
--- /dev/null
+++ b/libc/src/math/generic/tanpif.cpp
@@ -0,0 +1,106 @@
+//===-- Single-precision tanpi function -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/tanpif.h"
+#include "sincosf_utils.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/except_value_utils.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+
+namespace LIBC_NAMESPACE_DECL {
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+constexpr size_t N_EXCEPTS = 3;
+
+constexpr fputil::ExceptValues<float, N_EXCEPTS> TANPIF_EXCEPTS{{
+ // (input, RZ output, RU offset, RD offset, RN offset)
+ {0x38F26685, 0x39BE6182, 1, 0, 0},
+ {0x3E933802, 0x3FA267DD, 1, 0, 0},
+ {0x3F3663FF, 0xBFA267DD, 0, 1, 0},
+}};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+LLVM_LIBC_FUNCTION(float, tanpif, (float x)) {
+ using FPBits = typename fputil::FPBits<float>;
+ FPBits xbits(x);
+
+ uint32_t x_u = xbits.uintval();
+ uint32_t x_abs = x_u & 0x7fff'ffffU;
+ double xd = static_cast<double>(xbits.get_val());
+
+ // Handle exceptional values
+ if (LIBC_UNLIKELY(x_abs <= 0x3F3663FF)) {
+ if (LIBC_UNLIKELY(x_abs == 0U))
+ return x;
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ bool x_sign = x_u >> 31;
+
+ if (auto r = TANPIF_EXCEPTS.lookup_odd(x_abs, x_sign);
+ LIBC_UNLIKELY(r.has_value()))
+ return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ }
+
+ // Numbers greater or equal to 2^23 are always integers, or infinity, or NaN
+ if (LIBC_UNLIKELY(x_abs >= 0x4B00'0000)) {
+ // x is inf or NaN.
+ if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
+ if (x_abs == 0x7f80'0000U) {
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
+ }
+
+ return x + FPBits::quiet_nan().get_val();
+ }
+
+ return FPBits::zero(xbits.sign()).get_val();
+ }
+
+ // Range reduction:
+ // For |x| > 1/32, we perform range reduction as follows:
+ // Find k and y such that:
+ // x = (k + y) * 1/32
+ // k is an integer
+ // |y| < 0.5
+ //
+ // This is done by performing:
+ // k = round(x * 32)
+ // y = x * 32 - k
+ //
+ // Once k and y are computed, we then deduce the answer by the formula:
+ // tan(x) = sin(x) / cos(x)
+ // = (sin_y * cos_k + cos_y * sin_k) / (cos_y * cos_k - sin_y * sin_k)
+ double sin_k, cos_k, sin_y, cosm1_y;
+ sincospif_eval(xd, sin_k, cos_k, sin_y, cosm1_y);
+
+ if (LIBC_UNLIKELY(sin_y == 0 && cos_k == 0)) {
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_DIVBYZERO);
+
+ int32_t x_mp5_u = static_cast<int32_t>(x - 0.5);
+ return ((x_mp5_u & 0x1) ? -1 : 1) * FPBits::inf().get_val();
+ }
+
+ using fputil::multiply_add;
+ return fputil::cast<float>(
+ multiply_add(sin_y, cos_k, multiply_add(cosm1_y, sin_k, sin_k)) /
+ multiply_add(sin_y, -sin_k, multiply_add(cosm1_y, cos_k, cos_k)));
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/tanpif.h b/libc/src/math/tanpif.h
new file mode 100644
index 0000000000000..59e6dcfa9ff73
--- /dev/null
+++ b/libc/src/math/tanpif.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for tanpif ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_TANPIF_H
+#define LLVM_LIBC_SRC_MATH_TANPIF_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float tanpif(float x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_TANPIF_H
diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt
index 551f449c9c8db..1a23a335b2fff 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -122,6 +122,22 @@ add_fp_unittest(
-lpthread
)
+add_fp_unittest(
+ tanpif_test
+ NO_RUN_POSTBUILD
+ NEED_MPFR
+ SUITE
+ libc_math_exhaustive_tests
+ SRCS
+ tanpif_test.cpp
+ DEPENDS
+ .exhaustive_test
+ libc.src.math.tanpif
+ libc.src.__support.FPUtil.fp_bits
+ LINK_LIBRARIES
+ -lpthread
+)
+
add_fp_unittest(
erff_test
NO_RUN_POSTBUILD
diff --git a/libc/test/src/math/exhaustive/tanpif_test.cpp b/libc/test/src/math/exhaustive/tanpif_test.cpp
new file mode 100644
index 0000000000000..44a8a06f52374
--- /dev/null
+++ b/libc/test/src/math/exhaustive/tanpif_test.cpp
@@ -0,0 +1,33 @@
+//===-- Exhaustive test for tanpif ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "exhaustive_test.h"
+#include "src/math/tanpif.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+using LlvmLibcTanpifExhaustiveTest =
+ LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Tanpi,
+ LIBC_NAMESPACE::tanpif>;
+
+// Range: [0, Inf];
+static constexpr uint32_t POS_START = 0x0000'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
+
+TEST_F(LlvmLibcTanpifExhaustiveTest, PostiveRange) {
+ test_full_range_all_roundings(POS_START, POS_STOP);
+}
+
+// Range: [-Inf, 0];
+static constexpr uint32_t NEG_START = 0xb000'0000U;
+static constexpr uint32_t NEG_STOP = 0xff80'0000U;
+
+TEST_F(LlvmLibcTanpifExhaustiveTest, NegativeRange) {
+ test_full_range_all_roundings(NEG_START, NEG_STOP);
+}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 599939cbec4b5..4aafe03d1d08b 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -134,6 +134,17 @@ add_fp_unittest(
libc.src.math.tanf16
)
+add_fp_unittest(
+ tanpif_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ tanpif_test.cpp
+ DEPENDS
+ libc.src.errno.errno
+ libc.src.math.tanpif
+)
+
add_fp_unittest(
tanpif16_test
SUITE
diff --git a/libc/test/src/math/smoke/tanpif_test.cpp b/libc/test/src/math/smoke/tanpif_test.cpp
new file mode 100644
index 0000000000000..e122f57a2fe0f
--- /dev/null
+++ b/libc/test/src/math/smoke/tanpif_test.cpp
@@ -0,0 +1,36 @@
+//===-- Unittests for tanpif ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/libc_errno.h"
+#include "src/math/tanpif.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcTanpifTest = LIBC_NAMESPACE::testing::FPTest<float>;
+
+TEST_F(LlvmLibcTanpifTest, SpecialNumbers) {
+ libc_errno = 0;
+
+ EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::tanpif(sNaN), FE_INVALID);
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::tanpif(aNaN));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ(zero, LIBC_NAMESPACE::tanpif(zero));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ(neg_zero, LIBC_NAMESPACE::tanpif(neg_zero));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::tanpif(inf));
+ EXPECT_MATH_ERRNO(EDOM);
+
+ EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::tanpif(neg_inf));
+ EXPECT_MATH_ERRNO(EDOM);
+}
|
3 tasks
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The smoke test and exhaustive test pass on x86_64 Linux.
Closes #94895.