Skip to content

[libc] Add MPFR testing infra for float128. #119499

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

Merged
merged 2 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions libc/src/__support/complex_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ template <> struct make_complex<float16> {
using type = cfloat16;
};
#endif
#if defined(LIBC_TYPES_HAS_CFLOAT128) && \
!defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
#ifdef LIBC_TYPES_CFLOAT128_IS_NOT_COMPLEX_LONG_DOUBLE
template <> struct make_complex<float128> {
using type = cfloat128;
};
Expand All @@ -62,8 +61,7 @@ template <> struct make_real<cfloat16> {
using type = float16;
};
#endif
#if defined(LIBC_TYPES_HAS_CFLOAT128) && \
!defined(LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE)
#ifdef LIBC_TYPES_CFLOAT128_IS_NOT_COMPLEX_LONG_DOUBLE
template <> struct make_real<cfloat128> {
using type = float128;
};
Expand Down
5 changes: 5 additions & 0 deletions libc/src/__support/macros/properties/complex_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,9 @@
// LIBC_TYPES_HAS_CFLOAT128 and 'cfloat128' type are provided by
// "include/llvm-libc-types/cfloat128.h"

#if defined(LIBC_TYPES_HAS_CFLOAT128) && \
!defined(LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE)
#define LIBC_TYPES_CFLOAT128_IS_NOT_COMPLEX_LONG_DOUBLE
#endif

#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_CTYPES_H
5 changes: 5 additions & 0 deletions libc/src/__support/macros/properties/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
#define LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
#endif

#if defined(LIBC_TYPES_HAS_FLOAT128) && \
!defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
#define LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
#endif

// int64 / uint64 support
#if defined(UINT64_MAX)
#define LIBC_TYPES_HAS_INT64
Expand Down
13 changes: 13 additions & 0 deletions libc/test/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1549,6 +1549,19 @@ add_fp_unittest(
libc.src.math.sqrtf16
)

add_fp_unittest(
sqrtf128_test
NEED_MPFR
SUITE
libc-math-unittests
SRCS
sqrtf128_test.cpp
HDRS
SqrtTest.h
DEPENDS
libc.src.math.sqrtf128
)

add_fp_unittest(
generic_sqrtf_test
NEED_MPFR
Expand Down
43 changes: 43 additions & 0 deletions libc/test/src/math/sqrtf128_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//===-- Unittests for sqrtf128 --------------------------------------------===//
//
// 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 "SqrtTest.h"

#include "src/math/sqrtf128.h"

#include "src/__support/integer_literals.h"

LIST_SQRT_TESTS(float128, LIBC_NAMESPACE::sqrtf128)

TEST_F(LlvmLibcSqrtTest, SpecialInputs) {
constexpr float128 INPUTS[] = {
0x0.000000dee2f5b6a26c8f07f05442p-16382q,
0x0.000000c86d174c5ad8ae54a548e7p-16382q,
0x0.000020ab15cfe0b8e488e128f535p-16382q,
0x0.0000219e97732a9970f2511989bap-16382q,
0x0.000026e477546ae99ef57066f9fdp-16382q,
0x0.00002d0f88d27a496b3e533f5067p-16382q,
0x1.0000000000000000000000000001p+0q,
0x1.0000000000000000000000000003p+0q,
0x1.0000000000000000000000000005p+0q,
0x1.2af17a4ae6f93d11310c49c11b59p+0q,
0x1.c4f5074269525063a26051a0ad27p+0q,
0x1.035cb5f298a801dc4be9b1f8cd97p+1q,
0x1.274be02380427e709beab4dedeb4p+1q,
0x1.64e797cfdbaa3f7e2f33279dbc6p+1q,
0x1.d78d8352b48608b510bfd5c75315p+1q,
0x1.fffffffffffffffffffffffffffbp+1q,
0x1.fffffffffffffffffffffffffffdp+1q,
0x1.ffffffffffffffffffffffffffffp+1q,
};

for (auto input : INPUTS) {
ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Sqrt, input,
LIBC_NAMESPACE::sqrtf128(input), 0.5);
}
}
102 changes: 96 additions & 6 deletions libc/utils/MPFRWrapper/MPFRUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@

#include "mpfr_inc.h"

#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
extern "C" {
int mpfr_set_float128(mpfr_ptr, float128, mpfr_rnd_t);
float128 mpfr_get_float128(mpfr_srcptr, mpfr_rnd_t);
}
#endif

template <typename T> using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;

namespace LIBC_NAMESPACE_DECL {
Expand All @@ -47,8 +54,18 @@ template <> struct ExtraPrecision<double> {
};

template <> struct ExtraPrecision<long double> {
#ifdef LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128
static constexpr unsigned int VALUE = 512;
#else
static constexpr unsigned int VALUE = 256;
#endif
};

#if defined(LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE)
template <> struct ExtraPrecision<float128> {
static constexpr unsigned int VALUE = 512;
};
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE

// If the ulp tolerance is less than or equal to 0.5, we would check that the
// result is rounded correctly with respect to the rounding mode by using the
Expand Down Expand Up @@ -134,6 +151,19 @@ class MPFRNumber {
mpfr_set_ld(value, x, mpfr_rounding);
}

#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
template <typename XType,
cpp::enable_if_t<cpp::is_same_v<float128, XType>, int> = 0>
explicit MPFRNumber(XType x,
unsigned int precision = ExtraPrecision<XType>::VALUE,
RoundingMode rounding = RoundingMode::Nearest)
: mpfr_precision(precision),
mpfr_rounding(get_mpfr_rounding_mode(rounding)) {
mpfr_init2(value, mpfr_precision);
mpfr_set_float128(value, x, mpfr_rounding);
}
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE

template <typename XType,
cpp::enable_if_t<cpp::is_integral_v<XType>, int> = 0>
explicit MPFRNumber(XType x,
Expand Down Expand Up @@ -647,7 +677,7 @@ class MPFRNumber {
// These functions are useful for debugging.
template <typename T> T as() const;

void dump(const char *msg) const { mpfr_printf("%s%.128Rf\n", msg, value); }
void dump(const char *msg) const { mpfr_printf("%s%.128g\n", msg, value); }

// Return the ULP (units-in-the-last-place) difference between the
// stored MPFR and a floating point number.
Expand Down Expand Up @@ -770,6 +800,13 @@ template <> float16 MPFRNumber::as<float16>() const {
}
#endif

#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
template <> float128 MPFRNumber::as<float128>() const {
return mpfr_get_float128(value, mpfr_rounding);
}

#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE

namespace internal {

template <typename InputType>
Expand Down Expand Up @@ -997,7 +1034,27 @@ template void explain_unary_operation_single_output_error(Operation op, double,
template void explain_unary_operation_single_output_error(Operation op,
long double, float16,
double, RoundingMode);
#endif
#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
template void explain_unary_operation_single_output_error(Operation op,
float128, float16,
double, RoundingMode);
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
#endif // LIBC_TYPES_HAS_FLOAT16

#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
template void explain_unary_operation_single_output_error(Operation op,
float128, float128,
double, RoundingMode);
template void explain_unary_operation_single_output_error(Operation op,
float128, float,
double, RoundingMode);
template void explain_unary_operation_single_output_error(Operation op,
float128, double,
double, RoundingMode);
template void explain_unary_operation_single_output_error(Operation op,
float128, long double,
double, RoundingMode);
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE

template <typename T>
void explain_unary_operation_two_outputs_error(
Expand Down Expand Up @@ -1228,7 +1285,25 @@ template bool compare_unary_operation_single_output(Operation, double, float16,
template bool compare_unary_operation_single_output(Operation, long double,
float16, double,
RoundingMode);
#endif
#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
template bool compare_unary_operation_single_output(Operation, float128,
float16, double,
RoundingMode);
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
#endif // LIBC_TYPES_HAS_FLOAT16

#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
template bool compare_unary_operation_single_output(Operation, float128,
float128, double,
RoundingMode);
template bool compare_unary_operation_single_output(Operation, float128, float,
double, RoundingMode);
template bool compare_unary_operation_single_output(Operation, float128, double,
double, RoundingMode);
template bool compare_unary_operation_single_output(Operation, float128,
long double, double,
RoundingMode);
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE

template <typename T>
bool compare_unary_operation_two_outputs(Operation op, T input,
Expand Down Expand Up @@ -1398,9 +1473,14 @@ template <typename T> bool round_to_long(T x, long &result) {
template bool round_to_long<float>(float, long &);
template bool round_to_long<double>(double, long &);
template bool round_to_long<long double>(long double, long &);

#ifdef LIBC_TYPES_HAS_FLOAT16
template bool round_to_long<float16>(float16, long &);
#endif
#endif // LIBC_TYPES_HAS_FLOAT16

#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
template bool round_to_long<float128>(float128, long &);
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE

template <typename T> bool round_to_long(T x, RoundingMode mode, long &result) {
MPFRNumber mpfr(x);
Expand All @@ -1410,9 +1490,14 @@ template <typename T> bool round_to_long(T x, RoundingMode mode, long &result) {
template bool round_to_long<float>(float, RoundingMode, long &);
template bool round_to_long<double>(double, RoundingMode, long &);
template bool round_to_long<long double>(long double, RoundingMode, long &);

#ifdef LIBC_TYPES_HAS_FLOAT16
template bool round_to_long<float16>(float16, RoundingMode, long &);
#endif
#endif // LIBC_TYPES_HAS_FLOAT16

#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
template bool round_to_long<float128>(float128, RoundingMode, long &);
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE

template <typename T> T round(T x, RoundingMode mode) {
MPFRNumber mpfr(x);
Expand All @@ -1423,9 +1508,14 @@ template <typename T> T round(T x, RoundingMode mode) {
template float round<float>(float, RoundingMode);
template double round<double>(double, RoundingMode);
template long double round<long double>(long double, RoundingMode);

#ifdef LIBC_TYPES_HAS_FLOAT16
template float16 round<float16>(float16, RoundingMode);
#endif
#endif // LIBC_TYPES_HAS_FLOAT16

#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
template float128 round<float128>(float128, RoundingMode);
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE

} // namespace mpfr
} // namespace testing
Expand Down
Loading