Skip to content

Commit 4eec286

Browse files
authored
[libc] Add MPFR testing infra for float128. (#119499)
1 parent 979e936 commit 4eec286

File tree

6 files changed

+164
-10
lines changed

6 files changed

+164
-10
lines changed

libc/src/__support/complex_type.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ template <> struct make_complex<float16> {
3636
using type = cfloat16;
3737
};
3838
#endif
39-
#if defined(LIBC_TYPES_HAS_CFLOAT128) && \
40-
!defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
39+
#ifdef LIBC_TYPES_CFLOAT128_IS_NOT_COMPLEX_LONG_DOUBLE
4140
template <> struct make_complex<float128> {
4241
using type = cfloat128;
4342
};
@@ -62,8 +61,7 @@ template <> struct make_real<cfloat16> {
6261
using type = float16;
6362
};
6463
#endif
65-
#if defined(LIBC_TYPES_HAS_CFLOAT128) && \
66-
!defined(LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE)
64+
#ifdef LIBC_TYPES_CFLOAT128_IS_NOT_COMPLEX_LONG_DOUBLE
6765
template <> struct make_real<cfloat128> {
6866
using type = float128;
6967
};

libc/src/__support/macros/properties/complex_types.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,9 @@
2222
// LIBC_TYPES_HAS_CFLOAT128 and 'cfloat128' type are provided by
2323
// "include/llvm-libc-types/cfloat128.h"
2424

25+
#if defined(LIBC_TYPES_HAS_CFLOAT128) && \
26+
!defined(LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE)
27+
#define LIBC_TYPES_CFLOAT128_IS_NOT_COMPLEX_LONG_DOUBLE
28+
#endif
29+
2530
#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_CTYPES_H

libc/src/__support/macros/properties/types.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@
3131
#define LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
3232
#endif
3333

34+
#if defined(LIBC_TYPES_HAS_FLOAT128) && \
35+
!defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
36+
#define LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
37+
#endif
38+
3439
// int64 / uint64 support
3540
#if defined(UINT64_MAX)
3641
#define LIBC_TYPES_HAS_INT64

libc/test/src/math/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1549,6 +1549,19 @@ add_fp_unittest(
15491549
libc.src.math.sqrtf16
15501550
)
15511551

1552+
add_fp_unittest(
1553+
sqrtf128_test
1554+
NEED_MPFR
1555+
SUITE
1556+
libc-math-unittests
1557+
SRCS
1558+
sqrtf128_test.cpp
1559+
HDRS
1560+
SqrtTest.h
1561+
DEPENDS
1562+
libc.src.math.sqrtf128
1563+
)
1564+
15521565
add_fp_unittest(
15531566
generic_sqrtf_test
15541567
NEED_MPFR

libc/test/src/math/sqrtf128_test.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//===-- Unittests for sqrtf128 --------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "SqrtTest.h"
10+
11+
#include "src/math/sqrtf128.h"
12+
13+
#include "src/__support/integer_literals.h"
14+
15+
LIST_SQRT_TESTS(float128, LIBC_NAMESPACE::sqrtf128)
16+
17+
TEST_F(LlvmLibcSqrtTest, SpecialInputs) {
18+
constexpr float128 INPUTS[] = {
19+
0x0.000000dee2f5b6a26c8f07f05442p-16382q,
20+
0x0.000000c86d174c5ad8ae54a548e7p-16382q,
21+
0x0.000020ab15cfe0b8e488e128f535p-16382q,
22+
0x0.0000219e97732a9970f2511989bap-16382q,
23+
0x0.000026e477546ae99ef57066f9fdp-16382q,
24+
0x0.00002d0f88d27a496b3e533f5067p-16382q,
25+
0x1.0000000000000000000000000001p+0q,
26+
0x1.0000000000000000000000000003p+0q,
27+
0x1.0000000000000000000000000005p+0q,
28+
0x1.2af17a4ae6f93d11310c49c11b59p+0q,
29+
0x1.c4f5074269525063a26051a0ad27p+0q,
30+
0x1.035cb5f298a801dc4be9b1f8cd97p+1q,
31+
0x1.274be02380427e709beab4dedeb4p+1q,
32+
0x1.64e797cfdbaa3f7e2f33279dbc6p+1q,
33+
0x1.d78d8352b48608b510bfd5c75315p+1q,
34+
0x1.fffffffffffffffffffffffffffbp+1q,
35+
0x1.fffffffffffffffffffffffffffdp+1q,
36+
0x1.ffffffffffffffffffffffffffffp+1q,
37+
};
38+
39+
for (auto input : INPUTS) {
40+
ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Sqrt, input,
41+
LIBC_NAMESPACE::sqrtf128(input), 0.5);
42+
}
43+
}

libc/utils/MPFRWrapper/MPFRUtils.cpp

Lines changed: 96 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@
2222

2323
#include "mpfr_inc.h"
2424

25+
#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
26+
extern "C" {
27+
int mpfr_set_float128(mpfr_ptr, float128, mpfr_rnd_t);
28+
float128 mpfr_get_float128(mpfr_srcptr, mpfr_rnd_t);
29+
}
30+
#endif
31+
2532
template <typename T> using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
2633

2734
namespace LIBC_NAMESPACE_DECL {
@@ -47,8 +54,18 @@ template <> struct ExtraPrecision<double> {
4754
};
4855

4956
template <> struct ExtraPrecision<long double> {
57+
#ifdef LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128
58+
static constexpr unsigned int VALUE = 512;
59+
#else
5060
static constexpr unsigned int VALUE = 256;
61+
#endif
62+
};
63+
64+
#if defined(LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE)
65+
template <> struct ExtraPrecision<float128> {
66+
static constexpr unsigned int VALUE = 512;
5167
};
68+
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
5269

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

154+
#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
155+
template <typename XType,
156+
cpp::enable_if_t<cpp::is_same_v<float128, XType>, int> = 0>
157+
explicit MPFRNumber(XType x,
158+
unsigned int precision = ExtraPrecision<XType>::VALUE,
159+
RoundingMode rounding = RoundingMode::Nearest)
160+
: mpfr_precision(precision),
161+
mpfr_rounding(get_mpfr_rounding_mode(rounding)) {
162+
mpfr_init2(value, mpfr_precision);
163+
mpfr_set_float128(value, x, mpfr_rounding);
164+
}
165+
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
166+
137167
template <typename XType,
138168
cpp::enable_if_t<cpp::is_integral_v<XType>, int> = 0>
139169
explicit MPFRNumber(XType x,
@@ -647,7 +677,7 @@ class MPFRNumber {
647677
// These functions are useful for debugging.
648678
template <typename T> T as() const;
649679

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

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

803+
#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
804+
template <> float128 MPFRNumber::as<float128>() const {
805+
return mpfr_get_float128(value, mpfr_rounding);
806+
}
807+
808+
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
809+
773810
namespace internal {
774811

775812
template <typename InputType>
@@ -997,7 +1034,27 @@ template void explain_unary_operation_single_output_error(Operation op, double,
9971034
template void explain_unary_operation_single_output_error(Operation op,
9981035
long double, float16,
9991036
double, RoundingMode);
1000-
#endif
1037+
#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
1038+
template void explain_unary_operation_single_output_error(Operation op,
1039+
float128, float16,
1040+
double, RoundingMode);
1041+
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
1042+
#endif // LIBC_TYPES_HAS_FLOAT16
1043+
1044+
#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
1045+
template void explain_unary_operation_single_output_error(Operation op,
1046+
float128, float128,
1047+
double, RoundingMode);
1048+
template void explain_unary_operation_single_output_error(Operation op,
1049+
float128, float,
1050+
double, RoundingMode);
1051+
template void explain_unary_operation_single_output_error(Operation op,
1052+
float128, double,
1053+
double, RoundingMode);
1054+
template void explain_unary_operation_single_output_error(Operation op,
1055+
float128, long double,
1056+
double, RoundingMode);
1057+
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
10011058

10021059
template <typename T>
10031060
void explain_unary_operation_two_outputs_error(
@@ -1228,7 +1285,25 @@ template bool compare_unary_operation_single_output(Operation, double, float16,
12281285
template bool compare_unary_operation_single_output(Operation, long double,
12291286
float16, double,
12301287
RoundingMode);
1231-
#endif
1288+
#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
1289+
template bool compare_unary_operation_single_output(Operation, float128,
1290+
float16, double,
1291+
RoundingMode);
1292+
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
1293+
#endif // LIBC_TYPES_HAS_FLOAT16
1294+
1295+
#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
1296+
template bool compare_unary_operation_single_output(Operation, float128,
1297+
float128, double,
1298+
RoundingMode);
1299+
template bool compare_unary_operation_single_output(Operation, float128, float,
1300+
double, RoundingMode);
1301+
template bool compare_unary_operation_single_output(Operation, float128, double,
1302+
double, RoundingMode);
1303+
template bool compare_unary_operation_single_output(Operation, float128,
1304+
long double, double,
1305+
RoundingMode);
1306+
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
12321307

12331308
template <typename T>
12341309
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) {
13981473
template bool round_to_long<float>(float, long &);
13991474
template bool round_to_long<double>(double, long &);
14001475
template bool round_to_long<long double>(long double, long &);
1476+
14011477
#ifdef LIBC_TYPES_HAS_FLOAT16
14021478
template bool round_to_long<float16>(float16, long &);
1403-
#endif
1479+
#endif // LIBC_TYPES_HAS_FLOAT16
1480+
1481+
#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
1482+
template bool round_to_long<float128>(float128, long &);
1483+
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
14041484

14051485
template <typename T> bool round_to_long(T x, RoundingMode mode, long &result) {
14061486
MPFRNumber mpfr(x);
@@ -1410,9 +1490,14 @@ template <typename T> bool round_to_long(T x, RoundingMode mode, long &result) {
14101490
template bool round_to_long<float>(float, RoundingMode, long &);
14111491
template bool round_to_long<double>(double, RoundingMode, long &);
14121492
template bool round_to_long<long double>(long double, RoundingMode, long &);
1493+
14131494
#ifdef LIBC_TYPES_HAS_FLOAT16
14141495
template bool round_to_long<float16>(float16, RoundingMode, long &);
1415-
#endif
1496+
#endif // LIBC_TYPES_HAS_FLOAT16
1497+
1498+
#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
1499+
template bool round_to_long<float128>(float128, RoundingMode, long &);
1500+
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
14161501

14171502
template <typename T> T round(T x, RoundingMode mode) {
14181503
MPFRNumber mpfr(x);
@@ -1423,9 +1508,14 @@ template <typename T> T round(T x, RoundingMode mode) {
14231508
template float round<float>(float, RoundingMode);
14241509
template double round<double>(double, RoundingMode);
14251510
template long double round<long double>(long double, RoundingMode);
1511+
14261512
#ifdef LIBC_TYPES_HAS_FLOAT16
14271513
template float16 round<float16>(float16, RoundingMode);
1428-
#endif
1514+
#endif // LIBC_TYPES_HAS_FLOAT16
1515+
1516+
#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
1517+
template float128 round<float128>(float128, RoundingMode);
1518+
#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
14291519

14301520
} // namespace mpfr
14311521
} // namespace testing

0 commit comments

Comments
 (0)