16 changes: 16 additions & 0 deletions libc/test/src/math/exhaustive/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -325,3 +325,19 @@ add_fp_unittest(
-lpthread
)

add_fp_unittest(
asinf_test
NO_RUN_POSTBUILD
NEED_MPFR
SUITE
libc_math_exhaustive_tests
SRCS
asinf_test.cpp
DEPENDS
.exhaustive_test
libc.include.math
libc.src.math.asinf
libc.src.__support.FPUtil.fp_bits
LINK_LIBRARIES
-lpthread
)
78 changes: 78 additions & 0 deletions libc/test/src/math/exhaustive/asinf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//===-- Exhaustive test for asinf -----------------------------------------===//
//
// 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/asinf.h"
#include "utils/MPFRWrapper/MPFRUtils.h"

#include <thread>

using FPBits = __llvm_libc::fputil::FPBits<float>;

namespace mpfr = __llvm_libc::testing::mpfr;

struct LlvmLibcAsinfExhaustiveTest : 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::Asin, x,
__llvm_libc::asinf(x), 0.5, rounding);
// if (!result) break;
} while (bits++ < stop);
return result;
}
};

static const int NUM_THREADS = std::thread::hardware_concurrency();

// Range: [0, Inf];
static const uint32_t POS_START = 0x0000'0000U;
static const uint32_t POS_STOP = 0x7f80'0000U;
/

TEST_F(LlvmLibcAsinfExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
}

TEST_F(LlvmLibcAsinfExhaustiveTest, PostiveRangeRoundUp) {
test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
}

TEST_F(LlvmLibcAsinfExhaustiveTest, PostiveRangeRoundDown) {
test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
}

TEST_F(LlvmLibcAsinfExhaustiveTest, PostiveRangeRoundTowardZero) {
test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
}

// Range: [-Inf, 0];
static const uint32_t NEG_START = 0x8000'0000U;
static const uint32_t NEG_STOP = 0xff80'0000U;

TEST_F(LlvmLibcAsinfExhaustiveTest, NegativeRangeRoundNearestTieToEven) {
test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Nearest);
}

TEST_F(LlvmLibcAsinfExhaustiveTest, NegativeRangeRoundUp) {
test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Upward);
}

TEST_F(LlvmLibcAsinfExhaustiveTest, NegativeRangeRoundDown) {
test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Downward);
}

TEST_F(LlvmLibcAsinfExhaustiveTest, NegativeRangeRoundTowardZero) {
test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::TowardZero);
}
16 changes: 16 additions & 0 deletions libc/utils/MPFRWrapper/MPFRUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,20 @@ class MPFRNumber {
return *this;
}

bool is_nan() const { return mpfr_nan_p(value); }

MPFRNumber abs() const {
MPFRNumber result(*this);
mpfr_abs(result.value, value, mpfr_rounding);
return result;
}

MPFRNumber asin() const {
MPFRNumber result(*this);
mpfr_asin(result.value, value, mpfr_rounding);
return result;
}

MPFRNumber atan() const {
MPFRNumber result(*this);
mpfr_atan(result.value, value, mpfr_rounding);
Expand Down Expand Up @@ -436,6 +444,12 @@ class MPFRNumber {
if (thisAsT == input)
return T(0.0);

if (is_nan()) {
if (fputil::FPBits<T>(input).is_nan())
return T(0.0);
return T(fputil::FPBits<T>::inf());
}

int thisExponent = fputil::FPBits<T>(thisAsT).get_exponent();
int inputExponent = fputil::FPBits<T>(input).get_exponent();
// Adjust the exponents for denormal numbers.
Expand Down Expand Up @@ -512,6 +526,8 @@ unary_operation(Operation op, InputType input, unsigned int precision,
switch (op) {
case Operation::Abs:
return mpfrInput.abs();
case Operation::Asin:
return mpfrInput.asin();
case Operation::Atan:
return mpfrInput.atan();
case Operation::Atanh:
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 @@ -25,6 +25,7 @@ enum class Operation : int {
// and output floating point numbers are of the same kind.
BeginUnaryOperationsSingleOutput,
Abs,
Asin,
Atan,
Atanh,
Ceil,
Expand Down