Currently, gcc is rejecting to compile constexpr operations on fixed cpp_ints wider than double_limb_type. It says that the current initialized field is m_double_first_limb, even after we initialize m_data:
Here
|
constexpr data_type(double_limb_type i) : m_double_first_limb(i) |
|
{ |
|
#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION |
|
if (BOOST_MP_IS_CONST_EVALUATED(m_double_first_limb)) |
|
{ |
|
data_type t(static_cast<limb_type>(i & max_limb_value), static_cast<limb_type>(i >> limb_bits)); |
And here
|
constexpr data_type(double_limb_type i) : m_double_first_limb(i) |
|
{ |
|
#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION |
|
if (BOOST_MP_IS_CONST_EVALUATED(m_double_first_limb)) |
|
{ |
|
data_type t(static_cast<limb_type>(i & max_limb_value), static_cast<limb_type>(i >> limb_bits)); |
There's also this one, but it will only be an issue with constexpr dynamic allocations, I can fix it here or I can fix it at my PR #654. I also think the BOOST_MP_ENDIAN_LITTLE_BYTE check will not be needed anymore as the split will be explicit as in the other cases
|
#if BOOST_MP_ENDIAN_LITTLE_BYTE |
|
constexpr data_type(double_limb_type i) noexcept : double_first(i) |
|
{} |
|
constexpr data_type(signed_double_limb_type i) noexcept : double_first(static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i))) {} |
|
#endif |
Below is a minimal reproducible example
#include <boost/multiprecision/cpp_int.hpp>
template <int Bits>
inline constexpr auto repro = [] constexpr noexcept {
namespace mp = boost::multiprecision;
using ubits_t = mp::number<
mp::cpp_int_backend<Bits, Bits, mp::unsigned_magnitude, mp::unchecked, void>,
// also happens for mp::et_on
mp::et_off
>;
ubits_t x = static_cast<unsigned __int128>(0);
// ubits_t x = 0U; // does not fail
// x *= x; // multiplication also fails
x += x;
return x;
}();
// DOES NOT FAIL
// static_assert(repro<128> == 0);
// FAIL
static_assert(repro<129> == 0);
// static_assert(repro<192> == 0);
// static_assert(repro<512> == 0);
Here's a link to compiler explorer. You can see that this is GCC only as clang works fine.
The solution is a simple change on how the cpp_ints are constructed on the m_double_first_limb (initialize m_data instead of m_double_first_limb on all cases). I can open a PR (with regression tests) if needed (I have a working version here that I used to locate the issue).
Currently, gcc is rejecting to compile constexpr operations on fixed
cpp_ints wider thandouble_limb_type. It says that the current initialized field ism_double_first_limb, even after we initializem_data:Here
multiprecision/include/boost/multiprecision/cpp_int.hpp
Lines 583 to 588 in df89bfd
And here
multiprecision/include/boost/multiprecision/cpp_int.hpp
Lines 776 to 781 in df89bfd
There's also this one, but it will only be an issue with constexpr dynamic allocations, I can fix it here or I can fix it at my PR #654. I also think the
BOOST_MP_ENDIAN_LITTLE_BYTEcheck will not be needed anymore as the split will be explicit as in the other casesmultiprecision/include/boost/multiprecision/cpp_int.hpp
Lines 231 to 235 in df89bfd
Below is a minimal reproducible example
Here's a link to compiler explorer. You can see that this is GCC only as clang works fine.
The solution is a simple change on how the
cpp_ints are constructed on them_double_first_limb(initializem_datainstead ofm_double_first_limbon all cases). I can open a PR (with regression tests) if needed (I have a working version here that I used to locate the issue).