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+
2532template <typename T> using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
2633
2734namespace LIBC_NAMESPACE_DECL {
@@ -47,8 +54,18 @@ template <> struct ExtraPrecision<double> {
4754};
4855
4956template <> 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+
773810namespace internal {
774811
775812template <typename InputType>
@@ -997,7 +1034,27 @@ template void explain_unary_operation_single_output_error(Operation op, double,
9971034template 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
10021059template <typename T>
10031060void explain_unary_operation_two_outputs_error (
@@ -1228,7 +1285,25 @@ template bool compare_unary_operation_single_output(Operation, double, float16,
12281285template 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
12331308template <typename T>
12341309bool compare_unary_operation_two_outputs (Operation op, T input,
@@ -1398,9 +1473,14 @@ template <typename T> bool round_to_long(T x, long &result) {
13981473template bool round_to_long<float >(float , long &);
13991474template bool round_to_long<double >(double , long &);
14001475template bool round_to_long<long double >(long double , long &);
1476+
14011477#ifdef LIBC_TYPES_HAS_FLOAT16
14021478template 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
14051485template <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) {
14101490template bool round_to_long<float >(float , RoundingMode, long &);
14111491template bool round_to_long<double >(double , RoundingMode, long &);
14121492template bool round_to_long<long double >(long double , RoundingMode, long &);
1493+
14131494#ifdef LIBC_TYPES_HAS_FLOAT16
14141495template 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
14171502template <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) {
14231508template float round<float >(float , RoundingMode);
14241509template double round<double >(double , RoundingMode);
14251510template long double round<long double >(long double , RoundingMode);
1511+
14261512#ifdef LIBC_TYPES_HAS_FLOAT16
14271513template 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