diff --git a/include/boost/charconv/detail/config.hpp b/include/boost/charconv/detail/config.hpp index 9ccfb0d6..9feb609f 100644 --- a/include/boost/charconv/detail/config.hpp +++ b/include/boost/charconv/detail/config.hpp @@ -188,4 +188,18 @@ static_assert((BOOST_CHARCONV_ENDIAN_BIG_BYTE || BOOST_CHARCONV_ENDIAN_LITTLE_BY # define BOOST_CHARCONV_HAS_BRAINFLOAT16 #endif +// Check for PPC64LE with IEEE long double (which is an alias to __float128) +// See: https://github.com/boostorg/boost/issues/1035 +// +// IBM128 has 106 Mantissa Digits whereas IEEE128 has 113 +// https://developers.redhat.com/articles/2023/05/16/benefits-fedora-38-long-double-transition-ppc64le# +#if (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)) && (defined(__LONG_DOUBLE_IEEE128__) || LDBL_MANT_DIG == 113) + +#define BOOST_CHARCONV_LDBL_IS_FLOAT128 +#define BOOST_CHARCONV_UNSUPPORTED_LONG_DOUBLE +static_assert(std::is_same::value, "__float128 should be an alias to long double. Please open an issue at: https://github.com/boostorg/charconv"); + +#endif + + #endif // BOOST_CHARCONV_DETAIL_CONFIG_HPP diff --git a/src/from_chars.cpp b/src/from_chars.cpp index 2c01e73c..0c313fad 100644 --- a/src/from_chars.cpp +++ b/src/from_chars.cpp @@ -229,7 +229,7 @@ boost::charconv::from_chars_result boost::charconv::from_chars_erange(const char return r; } -#elif !defined(BOOST_CHARCONV_UNSUPPORTED_LONG_DOUBLE) +#elif !defined(BOOST_CHARCONV_UNSUPPORTED_LONG_DOUBLE) && !defined(BOOST_CHARCONV_LDBL_IS_FLOAT128) boost::charconv::from_chars_result boost::charconv::from_chars_erange(const char* first, const char* last, long double& value, boost::charconv::chars_format fmt) noexcept { diff --git a/src/to_chars.cpp b/src/to_chars.cpp index ab0c77d7..24ddf0c6 100644 --- a/src/to_chars.cpp +++ b/src/to_chars.cpp @@ -602,7 +602,7 @@ boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* la return boost::charconv::detail::to_chars_float_impl(first, last, static_cast(value), fmt, precision); } -#elif !defined(BOOST_CHARCONV_UNSUPPORTED_LONG_DOUBLE) +#elif !defined(BOOST_CHARCONV_UNSUPPORTED_LONG_DOUBLE) && !defined(BOOST_CHARCONV_LDBL_IS_FLOAT128) boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, long double value, boost::charconv::chars_format fmt) noexcept diff --git a/src/to_chars_float_impl.hpp b/src/to_chars_float_impl.hpp index 4c74e04d..d1be9723 100644 --- a/src/to_chars_float_impl.hpp +++ b/src/to_chars_float_impl.hpp @@ -770,7 +770,7 @@ to_chars_result to_chars_float_impl(char* first, char* last, Real value, chars_f return boost::charconv::detail::to_chars_hex(first, last, value, precision); } -#if (BOOST_CHARCONV_LDBL_BITS == 80 || BOOST_CHARCONV_LDBL_BITS == 128) +#if (BOOST_CHARCONV_LDBL_BITS == 80 || BOOST_CHARCONV_LDBL_BITS == 128) && !defined(BOOST_CHARCONV_LDBL_IS_FLOAT128) template <> to_chars_result to_chars_float_impl(char* first, char* last, long double value, chars_format fmt, int precision) noexcept