Opened 5 years ago
Last modified 5 years ago
#13360 new Bugs
std::numeric_limits<multiprecision::float128> methods fail to compile in C++11 mode
Reported by: | Owned by: | John Maddock | |
---|---|---|---|
Milestone: | To Be Determined | Component: | multiprecision |
Version: | Boost 1.66.0 | Severity: | Regression |
Keywords: | Cc: | b7.10110111@… |
Description
The following code compiles fine in C++03 mode, but fails in C++11 mode. This happens in boost 1.66.0, but didn't happen in 1.63.0.
#include <boost/multiprecision/float128.hpp> int main() { std::numeric_limits<boost::multiprecision::float128>::min(); }
Similar problem with some other methods — those which return without explicit construction of number_type
.
I'm compiling with g++ using the following command line:
g++ -std=c++11 boost-test.cpp -o boost-test -fext-numeric-literals -lquadmath
The compiler prints the following error:
In file included from boost-test.cpp:1:0: /usr/include/boost/multiprecision/float128.hpp: In instantiation of ‘static std::numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::number_type std::numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::min() [with boost::multiprecision::expression_template_option ExpressionTemplates = (boost::multiprecision::expression_template_option)0u; std::numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::number_type = boost::multiprecision::number<boost::multiprecision::backends::float128_backend, (boost::multiprecision::expression_template_option)0u>]’: boost-test.cpp:4:59: required from here /usr/include/boost/multiprecision/float128.hpp:645:55: error: could not convert ‘3.3621031431120935062626778173217526e-4932’ from ‘__float128’ to ‘std::numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, (boost::multiprecision::expression_template_option)0u> >::number_type {aka boost::multiprecision::number<boost::multiprecision::backends::float128_backend, (boost::multiprecision::expression_template_option)0u>}’ static number_type (min)() BOOST_NOEXCEPT { return 3.36210314311209350626267781732175260e-4932Q; } ^
Change History (4)
comment:1 by , 5 years ago
comment:2 by , 5 years ago
Not sure if this is the core problem, but what if we use the following constructs instead of quad literals?
using ldlims=std::numeric_limits<long double>; constexpr auto max=__float128(ldlims::max())+ __float128(0x1.ffffffffffffp+16383L)*0x1.p-64; constexpr auto min=__float128(ldlims::min()); constexpr auto denorm_min=__float128(ldlims::denorm_min())*0x1.p-49; constexpr auto epsilon=__float128(ldlims::epsilon())*0x1.p-49;
These compile and work perfectly well with GCC (one of them, denorm_min
, wasn't even implemented in boost, but is also doable, as shown above).
comment:3 by , 5 years ago
Cc: | added |
---|
comment:4 by , 5 years ago
Actually, if we want to remain compatible to non-x87 FPUs, supporting IEEE754 binary64 as double
, then we can do it this way:
constexpr auto max=(__float128(0x1.fffffffffffffp+1023) + 0x1.ffffffffffffp+970 + 0x1.ffcp+921) * 0x1p+1023 * 0x1p+1023 * 0x1p+1023 * 0x1p+1023 * 0x1p+1023 * 0x1p+1023 * 0x1p+1023 * 0x1p+1023 * 0x1p+1023 * 0x1p+1023 * 0x1p+1023 * 0x1p+1023 * 0x1p+1023 * 0x1p+1023 * 0x1p+1023 * 0x1p+15; constexpr auto min=__float128(0x1p-1022) * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-30; constexpr auto denorm_min=__float128(0x1p-1022) * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-1022 * 0x1p-142; constexpr auto epsilon=__float128(0x1p-112); assert(max==std::numeric_limits<boost::multiprecision::float128>::max()); assert(min==std::numeric_limits<boost::multiprecision::float128>::min()); assert(epsilon==std::numeric_limits<boost::multiprecision::float128>::epsilon());
This is the by-product of fixing other issues, and I don't think we can fix it, except to say that using -std=gnu++11 works just fine.
The issue is that float128 literals are disabled with -std=c++11 but not -std=c++03 or -std=gnu++11. We can detect the -std=gnu++11 case and enable float128 support in that situation, but we can't detect that -fext-numeric-literals has been used with std=c++11 so float128 support is disabled in the library.
I'll look into trying to support this case with more config macros, but it might be easier to just issue better error messages when including the header in this situation.
Merry Christmas!