diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -280,6 +280,7 @@ libc.src.math.nextafter libc.src.math.nextafterf libc.src.math.nextafterl + libc.src.math.pow libc.src.math.remainderf libc.src.math.remainder libc.src.math.remainderl diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -282,6 +282,7 @@ libc.src.math.nextafter libc.src.math.nextafterf libc.src.math.nextafterl + libc.src.math.pow libc.src.math.remainderf libc.src.math.remainder libc.src.math.remainderl diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt --- a/libc/config/windows/entrypoints.txt +++ b/libc/config/windows/entrypoints.txt @@ -182,6 +182,7 @@ libc.src.math.nextafter libc.src.math.nextafterf libc.src.math.nextafterl + libc.src.math.pow libc.src.math.remainderf libc.src.math.remainder libc.src.math.remainderl diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -477,6 +477,8 @@ FunctionSpec<"nextafter", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"nextafterl", RetValSpec, [ArgSpec, ArgSpec]>, + FunctionSpec<"pow", RetValSpec, [ArgSpec, ArgSpec]>, + FunctionSpec<"coshf", RetValSpec, [ArgSpec]>, FunctionSpec<"sinhf", RetValSpec, [ArgSpec]>, FunctionSpec<"tanhf", RetValSpec, [ArgSpec]>, diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -171,6 +171,8 @@ add_math_entrypoint_object(nextafterf) add_math_entrypoint_object(nextafterl) +add_math_entrypoint_object(pow) + add_math_entrypoint_object(remainder) add_math_entrypoint_object(remainderf) add_math_entrypoint_object(remainderl) diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -1368,3 +1368,15 @@ -O3 ) +add_entrypoint_object( + pow + SRCS + pow.cpp + HDRS + ../pow.h + DEPENDS + .expf + .logf + COMPILE_OPTIONS + -O3 +) diff --git a/libc/src/math/generic/pow.cpp b/libc/src/math/generic/pow.cpp new file mode 100644 --- /dev/null +++ b/libc/src/math/generic/pow.cpp @@ -0,0 +1,24 @@ +//===-- Implementation of pow 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/pow.h" +#include "src/math/expf.h" +#include "src/math/logf.h" + +#include "src/__support/common.h" + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(double, pow, (double x, double y)) { + // Place-holder implementation for double precision pow function. + // TODO: Implement correctly rounded pow function for double precision. + return static_cast( + expf(static_cast(y) * logf(static_cast(x)))); +} + +} // namespace __llvm_libc diff --git a/libc/src/math/pow.h b/libc/src/math/pow.h new file mode 100644 --- /dev/null +++ b/libc/src/math/pow.h @@ -0,0 +1,18 @@ +//===-- Implementation header for pow ---------------------------*- 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_POW_H +#define LLVM_LIBC_SRC_MATH_POW_H + +namespace __llvm_libc { + +double pow(double x, double y); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_MATH_POW_H diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt --- a/libc/test/src/math/CMakeLists.txt +++ b/libc/test/src/math/CMakeLists.txt @@ -1521,6 +1521,19 @@ libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + pow_test + NEED_MPFR + SUITE + libc_math_unittests + SRCS + pow_test.cpp + DEPENDS + libc.include.errno + libc.src.errno.errno + libc.src.math.pow +) + add_subdirectory(generic) add_subdirectory(exhaustive) add_subdirectory(differential_testing) diff --git a/libc/test/src/math/pow_test.cpp b/libc/test/src/math/pow_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/math/pow_test.cpp @@ -0,0 +1,37 @@ +//===-- Unittests for pow -------------------------------------------------===// +// +// 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/pow.h" +#include "utils/MPFRWrapper/MPFRUtils.h" +#include "utils/UnitTest/FPMatcher.h" +#include "utils/UnitTest/Test.h" +#include + +#include +#include + +using FPBits = __llvm_libc::fputil::FPBits; + +namespace mpfr = __llvm_libc::testing::mpfr; + +DECLARE_SPECIAL_CONSTANTS(double) + +TEST(LlvmLibcAsinTest, SpecialNumbers) { + errno = 0; + + EXPECT_FP_EQ(aNaN, __llvm_libc::pow(aNaN, aNaN)); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ(1.0, __llvm_libc::pow(1.0, 1.0)); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ(1.0, __llvm_libc::pow(1.0, 2.0)); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ(inf, __llvm_libc::pow(2.0, inf)); +}