12
12
#include " src/__support/CPP/string_view.h"
13
13
#include " src/__support/FPUtil/FPBits.h"
14
14
#include " src/__support/FPUtil/fpbits_str.h"
15
+ #include " src/__support/macros/properties/types.h"
15
16
#include " test/UnitTest/FPMatcher.h"
16
17
17
18
#include " hdr/math_macros.h"
@@ -30,6 +31,12 @@ namespace mpfr {
30
31
// precision compared to the floating point precision.
31
32
template <typename T> struct ExtraPrecision ;
32
33
34
+ #ifdef LIBC_TYPES_HAS_FLOAT16
35
+ template <> struct ExtraPrecision <float16> {
36
+ static constexpr unsigned int VALUE = 128 ;
37
+ };
38
+ #endif
39
+
33
40
template <> struct ExtraPrecision <float > {
34
41
static constexpr unsigned int VALUE = 128 ;
35
42
};
@@ -85,9 +92,16 @@ class MPFRNumber {
85
92
86
93
// We use explicit EnableIf specializations to disallow implicit
87
94
// conversions. Implicit conversions can potentially lead to loss of
88
- // precision.
95
+ // precision. We exceptionally allow implicit conversions from float16
96
+ // to float, as the MPFR API does not support float16, thus requiring
97
+ // conversion to a higher-precision format.
89
98
template <typename XType,
90
- cpp::enable_if_t <cpp::is_same_v<float , XType>, int > = 0 >
99
+ cpp::enable_if_t <cpp::is_same_v<float , XType>
100
+ #ifdef LIBC_TYPES_HAS_FLOAT16
101
+ || cpp::is_same_v<float16, XType>
102
+ #endif
103
+ ,
104
+ int > = 0 >
91
105
explicit MPFRNumber (XType x,
92
106
unsigned int precision = ExtraPrecision<XType>::VALUE,
93
107
RoundingMode rounding = RoundingMode::Nearest)
@@ -529,8 +543,8 @@ class MPFRNumber {
529
543
// If the control reaches here, it means that this number and input are
530
544
// of the same sign but different exponent. In such a case, ULP error is
531
545
// calculated as sum of two parts.
532
- thisAsT = std::abs (thisAsT);
533
- input = std::abs (input);
546
+ thisAsT = FPBits<T> (thisAsT). abs (). get_val ( );
547
+ input = FPBits<T> (input). abs (). get_val ( );
534
548
T min = thisAsT > input ? input : thisAsT;
535
549
T max = thisAsT > input ? thisAsT : input;
536
550
int minExponent = FPBits<T>(min).get_exponent ();
@@ -585,6 +599,14 @@ template <> long double MPFRNumber::as<long double>() const {
585
599
return mpfr_get_ld (value, mpfr_rounding);
586
600
}
587
601
602
+ #ifdef LIBC_TYPES_HAS_FLOAT16
603
+ template <> float16 MPFRNumber::as<float16>() const {
604
+ // TODO: Either prove that this cast won't cause double-rounding errors, or
605
+ // find a better way to get a float16.
606
+ return static_cast <float16>(mpfr_get_d (value, mpfr_rounding));
607
+ }
608
+ #endif
609
+
588
610
namespace internal {
589
611
590
612
template <typename InputType>
@@ -763,6 +785,10 @@ template void explain_unary_operation_single_output_error<double>(
763
785
Operation op, double , double , double , RoundingMode);
764
786
template void explain_unary_operation_single_output_error<long double >(
765
787
Operation op, long double , long double , double , RoundingMode);
788
+ #ifdef LIBC_TYPES_HAS_FLOAT16
789
+ template void explain_unary_operation_single_output_error<float16>(
790
+ Operation op, float16, float16, double , RoundingMode);
791
+ #endif
766
792
767
793
template <typename T>
768
794
void explain_unary_operation_two_outputs_error (
@@ -942,6 +968,11 @@ template bool compare_unary_operation_single_output<double>(Operation, double,
942
968
RoundingMode);
943
969
template bool compare_unary_operation_single_output<long double >(
944
970
Operation, long double , long double , double , RoundingMode);
971
+ #ifdef LIBC_TYPES_HAS_FLOAT16
972
+ template bool compare_unary_operation_single_output<float16>(Operation, float16,
973
+ float16, double ,
974
+ RoundingMode);
975
+ #endif
945
976
946
977
template <typename T>
947
978
bool compare_unary_operation_two_outputs (Operation op, T input,
0 commit comments