diff options
Diffstat (limited to 'libc/utils/MPFRWrapper/MPFRUtils.cpp')
| -rw-r--r-- | libc/utils/MPFRWrapper/MPFRUtils.cpp | 102 |
1 files changed, 96 insertions, 6 deletions
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp index 00592c5cb15f..0dac497bb779 100644 --- a/libc/utils/MPFRWrapper/MPFRUtils.cpp +++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp @@ -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,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 @@ -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 |
