summaryrefslogtreecommitdiff
path: root/libc/utils/MPFRWrapper/MPFRUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libc/utils/MPFRWrapper/MPFRUtils.cpp')
-rw-r--r--libc/utils/MPFRWrapper/MPFRUtils.cpp102
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