[libc-commits] [libc] fcb9d7e - [libc][math] Added coshf function.
Kirill Okhotnikov via libc-commits
libc-commits at lists.llvm.org
Fri Jul 29 07:57:38 PDT 2022
Author: Kirill Okhotnikov
Date: 2022-07-29T16:57:28+02:00
New Revision: fcb9d7e2cf17b41327d3e3d1a07c8b6fea4e6fb5
URL: https://github.com/llvm/llvm-project/commit/fcb9d7e2cf17b41327d3e3d1a07c8b6fea4e6fb5
DIFF: https://github.com/llvm/llvm-project/commit/fcb9d7e2cf17b41327d3e3d1a07c8b6fea4e6fb5.diff
LOG: [libc][math] Added coshf function.
Differential Revision: https://reviews.llvm.org/D129275
Added:
libc/src/math/coshf.h
libc/src/math/generic/coshf.cpp
libc/test/src/math/coshf_test.cpp
libc/test/src/math/exhaustive/coshf_test.cpp
Modified:
libc/config/darwin/arm/entrypoints.txt
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/x86_64/entrypoints.txt
libc/config/windows/entrypoints.txt
libc/spec/stdc.td
libc/src/__support/FPUtil/FPBits.h
libc/src/math/CMakeLists.txt
libc/src/math/generic/CMakeLists.txt
libc/test/src/math/CMakeLists.txt
libc/test/src/math/exhaustive/CMakeLists.txt
libc/utils/MPFRWrapper/MPFRUtils.cpp
libc/utils/MPFRWrapper/MPFRUtils.h
Removed:
################################################################################
diff --git a/libc/config/darwin/arm/entrypoints.txt b/libc/config/darwin/arm/entrypoints.txt
index 173b8d80eda13..2c7887f54fca4 100644
--- a/libc/config/darwin/arm/entrypoints.txt
+++ b/libc/config/darwin/arm/entrypoints.txt
@@ -111,6 +111,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.ceil
libc.src.math.ceilf
libc.src.math.ceill
+ libc.src.math.coshf
libc.src.math.cosf
libc.src.math.expf
libc.src.math.exp2f
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 377d306b2b86f..271f24eb10605 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -130,6 +130,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.ceil
libc.src.math.ceilf
libc.src.math.ceill
+ libc.src.math.coshf
libc.src.math.cosf
libc.src.math.expf
libc.src.math.exp2f
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 686d4de0a17ee..1485e1a3954a5 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -136,6 +136,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.ceilf
libc.src.math.ceill
libc.src.math.cos
+ libc.src.math.coshf
libc.src.math.cosf
libc.src.math.expf
libc.src.math.exp2f
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index 4fbbd5ffd705f..ce359d84aa294 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -114,6 +114,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.ceill
libc.src.math.cos
libc.src.math.cosf
+ libc.src.math.coshf
libc.src.math.expf
libc.src.math.exp2f
libc.src.math.expm1f
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index b998c0da3aa20..3a3494b7bb778 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -470,6 +470,8 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"nextafterf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
FunctionSpec<"nextafter", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"nextafterl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+
+ FunctionSpec<"coshf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
]
>;
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index d2717e5792d40..c8a9546a73a87 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -153,8 +153,8 @@ template <typename T> struct FPBits {
static constexpr FPBits<T> neg_zero() { return zero(true); }
- static constexpr FPBits<T> inf() {
- FPBits<T> bits;
+ static constexpr FPBits<T> inf(bool sign = false) {
+ FPBits<T> bits(sign ? FloatProp::SIGN_MASK : UIntType(0));
bits.set_unbiased_exponent(MAX_EXPONENT);
return bits;
}
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index c3376310e9d46..32d2a16daba9a 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -76,6 +76,7 @@ add_math_entrypoint_object(copysignl)
add_math_entrypoint_object(cos)
add_math_entrypoint_object(cosf)
+add_math_entrypoint_object(coshf)
add_math_entrypoint_object(expf)
diff --git a/libc/src/math/coshf.h b/libc/src/math/coshf.h
new file mode 100644
index 0000000000000..558dc220a0380
--- /dev/null
+++ b/libc/src/math/coshf.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for coshf -------------------------*- 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_COSHF_H
+#define LLVM_LIBC_SRC_MATH_COSHF_H
+
+namespace __llvm_libc {
+
+float coshf(float x);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_MATH_COSHF_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index f9b10e7f97f02..91a4a0328545a 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -1128,3 +1128,22 @@ add_entrypoint_object(
COMPILE_OPTIONS
-O3
)
+
+add_entrypoint_object(
+ coshf
+ SRCS
+ coshf.cpp
+ HDRS
+ ../coshf.h
+ expxf.h
+ DEPENDS
+ .common_constants
+ libc.src.__support.FPUtil.fputil
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.FPUtil.nearest_integer
+ libc.src.__support.FPUtil.polyeval
+ libc.include.math
+ COMPILE_OPTIONS
+ -O3
+)
+
diff --git a/libc/src/math/generic/coshf.cpp b/libc/src/math/generic/coshf.cpp
new file mode 100644
index 0000000000000..ce1f8085adeb9
--- /dev/null
+++ b/libc/src/math/generic/coshf.cpp
@@ -0,0 +1,54 @@
+//===-- Single-precision cosh 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/coshf.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/math/generic/expxf.h"
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(float, coshf, (float x)) {
+ using FPBits = typename fputil::FPBits<float>;
+ FPBits xbits(x);
+ xbits.set_sign(false);
+ x = xbits.get_val();
+
+ uint32_t x_u = xbits.uintval();
+
+ // |x| <= 2^-26
+ if (unlikely(x_u <= 0x3280'0000U)) {
+ return 1.0f + x;
+ }
+
+ // When |x| >= 90, or x is inf or nan
+ if (unlikely(x_u >= 0x42b4'0000U)) {
+ if (xbits.is_inf_or_nan())
+ return x + FPBits::inf().get_val();
+
+ int rounding = fputil::get_round();
+ if (unlikely(rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO))
+ return FPBits(FPBits::MAX_NORMAL).get_val();
+
+ errno = ERANGE;
+
+ return x + FPBits::inf().get_val();
+ }
+ auto ep_p = exp_eval<-1>(x);
+ auto ep_m = exp_eval<-1>(-x);
+ // 0.5 * exp(x) = ep_p.mult_exp * (ep_p.r + 1)
+ // = ep_p.mult_exp * ep_p.r + ep_p.mult_exp
+ // 0.5 * exp(-x) = ep_m.mult_exp * (ep_m.r + 1)
+ // = ep_m.mult_exp * ep_m.r + ep_m.mult_exp
+ // cos(x) = 0.5 * exp(x) + 0.5 * expm1(-x)
+ double ep = fputil::multiply_add(ep_p.mult_exp, ep_p.r, ep_p.mult_exp) +
+ fputil::multiply_add(ep_m.mult_exp, ep_m.r, ep_m.mult_exp);
+ return ep;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 266e5a41970f7..92916569f683d 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -1314,6 +1314,22 @@ add_fp_unittest(
libc.src.__support.FPUtil.fputil
)
+add_fp_unittest(
+ coshf_test
+ NEED_MPFR
+ SUITE
+ libc_math_unittests
+ SRCS
+ coshf_test.cpp
+ HDRS
+ sdcomp26094.h
+ DEPENDS
+ libc.include.errno
+ libc.src.math.coshf
+ libc.src.__support.CPP.array
+ libc.src.__support.FPUtil.fputil
+)
+
add_subdirectory(generic)
add_subdirectory(exhaustive)
add_subdirectory(
diff erential_testing)
diff --git a/libc/test/src/math/coshf_test.cpp b/libc/test/src/math/coshf_test.cpp
new file mode 100644
index 0000000000000..48ccf46aacce6
--- /dev/null
+++ b/libc/test/src/math/coshf_test.cpp
@@ -0,0 +1,78 @@
+//===-- Unittests for coshf -----------------------------------------------===//
+//
+// 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/CPP/Array.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/math/coshf.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+#include "utils/UnitTest/FPMatcher.h"
+#include "utils/UnitTest/Test.h"
+#include <math.h>
+
+#include <errno.h>
+#include <stdint.h>
+
+using FPBits = __llvm_libc::fputil::FPBits<float>;
+
+namespace mpfr = __llvm_libc::testing::mpfr;
+
+DECLARE_SPECIAL_CONSTANTS(float)
+
+TEST(LlvmLibcCoshfTest, SpecialNumbers) {
+ errno = 0;
+
+ EXPECT_FP_EQ(aNaN, __llvm_libc::coshf(aNaN));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ(inf, __llvm_libc::coshf(inf));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ(inf, __llvm_libc::coshf(neg_inf));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ(1.0f, __llvm_libc::coshf(0.0f));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ(1.0f, __llvm_libc::coshf(-0.0f));
+ EXPECT_MATH_ERRNO(0);
+}
+
+TEST(LlvmLibcCoshfTest, Overflow) {
+ errno = 0;
+ EXPECT_FP_EQ(inf, __llvm_libc::coshf(float(FPBits(0x7f7fffffU))));
+ EXPECT_MATH_ERRNO(ERANGE);
+
+ EXPECT_FP_EQ(inf, __llvm_libc::coshf(float(FPBits(0x42cffff8U))));
+ EXPECT_MATH_ERRNO(ERANGE);
+
+ EXPECT_FP_EQ(inf, __llvm_libc::coshf(float(FPBits(0x42d00008U))));
+ EXPECT_MATH_ERRNO(ERANGE);
+}
+
+TEST(LlvmLibcCoshfTest, InFloatRange) {
+ constexpr uint32_t COUNT = 1000000;
+ constexpr uint32_t STEP = UINT32_MAX / COUNT;
+ for (uint32_t i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
+ float x = float(FPBits(v));
+ if (isnan(x) || isinf(x))
+ continue;
+ ASSERT_MPFR_MATCH(mpfr::Operation::Cosh, x, __llvm_libc::coshf(x), 0.5);
+ }
+}
+
+TEST(LlvmLibcCoshfTest, SmallValues) {
+ float x = float(FPBits(0x17800000U));
+ float result = __llvm_libc::coshf(x);
+ EXPECT_MPFR_MATCH(mpfr::Operation::Cosh, x, result, 0.5);
+ EXPECT_FP_EQ(1.0f, result);
+
+ x = float(FPBits(0x0040000U));
+ result = __llvm_libc::coshf(x);
+ EXPECT_MPFR_MATCH(mpfr::Operation::Cosh, x, result, 0.5);
+ EXPECT_FP_EQ(1.0f, result);
+}
diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt
index a114267f27252..909c4585f9cca 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -201,3 +201,21 @@ add_fp_unittest(
libc.src.__support.FPUtil.fputil
libc.src.__support.FPUtil.generic.fmod
)
+
+add_fp_unittest(
+ coshf_test
+ NO_RUN_POSTBUILD
+ NEED_MPFR
+ SUITE
+ libc_math_exhaustive_tests
+ SRCS
+ coshf_test.cpp
+ DEPENDS
+ .exhaustive_test
+ libc.include.math
+ libc.src.math.coshf
+ libc.src.__support.FPUtil.fputil
+ LINK_LIBRARIES
+ -lpthread
+)
+
diff --git a/libc/test/src/math/exhaustive/coshf_test.cpp b/libc/test/src/math/exhaustive/coshf_test.cpp
new file mode 100644
index 0000000000000..9bb211238b6ea
--- /dev/null
+++ b/libc/test/src/math/exhaustive/coshf_test.cpp
@@ -0,0 +1,55 @@
+//===-- Exhaustive test for coshf -----------------------------------------===//
+//
+// 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/__support/FPUtil/FPBits.h"
+#include "src/math/coshf.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+#include "utils/UnitTest/FPMatcher.h"
+
+#include <thread>
+
+using FPBits = __llvm_libc::fputil::FPBits<float>;
+
+namespace mpfr = __llvm_libc::testing::mpfr;
+
+struct LlvmLibcCoshfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
+ bool check(uint32_t start, uint32_t stop,
+ mpfr::RoundingMode rounding) override {
+ mpfr::ForceRoundingMode r(rounding);
+ uint32_t bits = start;
+ bool result = true;
+ do {
+ FPBits xbits(bits);
+ float x = float(xbits);
+ result &= EXPECT_MPFR_MATCH(mpfr::Operation::Cosh, x,
+ __llvm_libc::coshf(x), 0.5, rounding);
+ } while (bits++ < stop);
+ return result;
+ }
+};
+
+// Range: [0, 90];
+static constexpr uint32_t POS_START = 0x0000'0000U;
+static constexpr uint32_t POS_STOP = 0x42b4'0000U;
+
+TEST_F(LlvmLibcCoshfExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
+ test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
+}
+
+TEST_F(LlvmLibcCoshfExhaustiveTest, PostiveRangeRoundUp) {
+ test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
+}
+
+TEST_F(LlvmLibcCoshfExhaustiveTest, PostiveRangeRoundDown) {
+ test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
+}
+
+TEST_F(LlvmLibcCoshfExhaustiveTest, PostiveRangeRoundTowardZero) {
+ test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
+}
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index 906784a894aff..abd975a60d725 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -194,6 +194,12 @@ class MPFRNumber {
return result;
}
+ MPFRNumber cosh() const {
+ MPFRNumber result(*this);
+ mpfr_cosh(result.value, value, mpfr_rounding);
+ return result;
+ }
+
MPFRNumber exp() const {
MPFRNumber result(*this);
mpfr_exp(result.value, value, mpfr_rounding);
@@ -481,6 +487,8 @@ unary_operation(Operation op, InputType input, unsigned int precision,
return mpfrInput.ceil();
case Operation::Cos:
return mpfrInput.cos();
+ case Operation::Cosh:
+ return mpfrInput.cosh();
case Operation::Exp:
return mpfrInput.exp();
case Operation::Exp2:
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.h b/libc/utils/MPFRWrapper/MPFRUtils.h
index fa98bc1951213..34c9ae6e11926 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.h
+++ b/libc/utils/MPFRWrapper/MPFRUtils.h
@@ -27,6 +27,7 @@ enum class Operation : int {
Abs,
Ceil,
Cos,
+ Cosh,
Exp,
Exp2,
Expm1,
More information about the libc-commits
mailing list