33 changes: 33 additions & 0 deletions libc/test/src/math/exhaustive/cospif_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//===-- Exhaustive test for cospif ----------------------------------------===//
//
// 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/cospif.h"
#include "utils/MPFRWrapper/MPFRUtils.h"

namespace mpfr = LIBC_NAMESPACE::testing::mpfr;

using LlvmLibcCospifExhaustiveTest =
LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Cospi,
LIBC_NAMESPACE::cospif>;

static constexpr uint32_t POS_START = 0x0000'0000U;
static constexpr uint32_t POS_STOP = 0x7f80'0000U;

// Range: [0, Inf]
TEST_F(LlvmLibcCospifExhaustiveTest, 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(LlvmLibcCospifExhaustiveTest, NegativeRange) {
test_full_range_all_roundings(NEG_START, NEG_STOP);
}
11 changes: 11 additions & 0 deletions libc/test/src/math/smoke/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ add_fp_unittest(
DEPENDS
libc.src.errno.errno
libc.src.math.cosf
)

add_fp_unittest(
cospif_test
SUITE
libc-math-smoke-tests
SRCS
cospif_test.cpp
DEPENDS
libc.src.errno.errno
libc.src.math.cospif
libc.src.__support.CPP.array
libc.src.__support.FPUtil.fp_bits
)
Expand Down
34 changes: 34 additions & 0 deletions libc/test/src/math/smoke/cospif_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//===-- Unittests for cospif ----------------------------------------------===//
//
// 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/errno/libc_errno.h"
#include "src/math/cospif.h"
#include "test/UnitTest/FPMatcher.h"

#include <stdint.h>

using LlvmLibcCospifTest = LIBC_NAMESPACE::testing::FPTest<float>;

TEST_F(LlvmLibcCospifTest, SpecialNumbers) {
LIBC_NAMESPACE::libc_errno = 0;

EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::cospif(aNaN));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::cospif(0.0f));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::cospif(-0.0f));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::cospif(inf));
EXPECT_MATH_ERRNO(EDOM);

EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::cospif(neg_inf));
EXPECT_MATH_ERRNO(EDOM);
}
35 changes: 35 additions & 0 deletions libc/utils/MPFRWrapper/MPFRUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,39 @@ class MPFRNumber {
return result;
}

MPFRNumber cospi() const {
MPFRNumber result(*this);

#if MPFR_VERSION_MAJOR > 4 || \
(MPFR_VERSION_MAJOR == 4 && MPFR_VERSION_MINOR >= 2)
mpfr_cospi(result.value, value, mpfr_rounding);
return result;
#else
MPFRNumber value_frac(*this);
mpfr_frac(value_frac.value, value, MPFR_RNDN);

if (mpfr_cmp_si(value_frac.value, 0.0) == 0) {
mpz_t integer_part;
mpz_init(integer_part);
mpfr_get_z(integer_part, value, MPFR_RNDN);

if (mpz_tstbit(integer_part, 0)) {
mpfr_set_si(result.value, -1.0, MPFR_RNDN); // odd
} else {
mpfr_set_si(result.value, 1.0, MPFR_RNDN); // even
}
return result;
}

MPFRNumber value_pi(0.0, 1280);
mpfr_const_pi(value_pi.value, MPFR_RNDN);
mpfr_mul(value_pi.value, value_pi.value, value, MPFR_RNDN);
mpfr_cos(result.value, value_pi.value, mpfr_rounding);

return result;
#endif
}

MPFRNumber erf() const {
MPFRNumber result(*this);
mpfr_erf(result.value, value, mpfr_rounding);
Expand Down Expand Up @@ -675,6 +708,8 @@ unary_operation(Operation op, InputType input, unsigned int precision,
return mpfrInput.cos();
case Operation::Cosh:
return mpfrInput.cosh();
case Operation::Cospi:
return mpfrInput.cospi();
case Operation::Erf:
return mpfrInput.erf();
case Operation::Exp:
Expand Down
1 change: 1 addition & 0 deletions libc/utils/MPFRWrapper/MPFRUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ enum class Operation : int {
Ceil,
Cos,
Cosh,
Cospi,
Erf,
Exp,
Exp2,
Expand Down