mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-19 00:56:41 +00:00
[libc] Add MPFR testing infra for float128. (#119499)
This commit is contained in:
parent
979e9361f0
commit
4eec286b51
@ -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;
|
||||
};
|
||||
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
43
libc/test/src/math/sqrtf128_test.cpp
Normal file
43
libc/test/src/math/sqrtf128_test.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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 {
|
||||
@ -47,9 +54,19 @@ 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
|
||||
// same precision as the inputs.
|
||||
@ -134,6 +151,19 @@ public:
|
||||
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,
|
||||
@ -647,7 +677,7 @@ public:
|
||||
// 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.
|
||||
@ -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>
|
||||
@ -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(
|
||||
@ -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,
|
||||
@ -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);
|
||||
@ -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);
|
||||
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user