From c7e29b02ff696f01e52c0933ff3cf5c3b9bd88fe Mon Sep 17 00:00:00 2001 From: jzmaddock Date: Thu, 16 Jun 2016 13:07:10 +0100 Subject: [PATCH] Test and allow MSVC compiled code to be used with /RTC1 /RTCc etc. --- include/boost/multiprecision/cpp_int.hpp | 27 ++++++++++++-- include/boost/multiprecision/cpp_int/add.hpp | 12 +++++++ .../boost/multiprecision/cpp_int/divide.hpp | 8 +++++ .../multiprecision/cpp_int/import_export.hpp | 6 ++-- include/boost/multiprecision/cpp_int/misc.hpp | 4 +++ .../boost/multiprecision/cpp_int/multiply.hpp | 36 +++++++++++++++++-- test/Jamfile.v2 | 3 ++ 7 files changed, 89 insertions(+), 7 deletions(-) diff --git a/include/boost/multiprecision/cpp_int.hpp b/include/boost/multiprecision/cpp_int.hpp index 1eca79d0..a294f3de 100644 --- a/include/boost/multiprecision/cpp_int.hpp +++ b/include/boost/multiprecision/cpp_int.hpp @@ -774,10 +774,10 @@ public: // template BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(SI i, typename boost::enable_if_c::value && (Checked == unchecked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval().check_in_range(std::declval()))) - : m_data(i < 0 ? static_cast(static_cast::type>(boost::multiprecision::detail::unsigned_abs(i)) & limb_mask) : static_cast(i)& limb_mask), m_sign(i < 0) {} + : m_data(i < 0 ? static_cast(static_cast::type>(boost::multiprecision::detail::unsigned_abs(i)) & limb_mask) : static_cast(i & limb_mask)), m_sign(i < 0) {} template BOOST_MP_FORCEINLINE cpp_int_base(SI i, typename boost::enable_if_c::value && (Checked == checked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval().check_in_range(std::declval()))) - : m_data(i < 0 ? (static_cast(static_cast::type>(boost::multiprecision::detail::unsigned_abs(i)) & limb_mask)) : static_cast(i)& limb_mask), m_sign(i < 0) + : m_data(i < 0 ? (static_cast(static_cast::type>(boost::multiprecision::detail::unsigned_abs(i)) & limb_mask)) : static_cast(i & limb_mask)), m_sign(i < 0) { check_in_range(i); } template BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(UI i, typename boost::enable_if_c::value && (Checked == unchecked)>::type const* = 0) BOOST_NOEXCEPT @@ -915,6 +915,20 @@ public: // // Direct construction: // +#ifdef __MSVC_RUNTIME_CHECKS + template + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(SI i, typename boost::enable_if_c::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT + : m_data(i < 0 ? (1 + ~static_cast(-i & limb_mask)) & limb_mask : static_cast(i & limb_mask)) {} + template + BOOST_MP_FORCEINLINE cpp_int_base(SI i, typename boost::enable_if_c::value && (Checked == checked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval().check_in_range(std::declval()))) + : m_data(i < 0 ? 1 + ~static_cast(-i & limb_mask) : static_cast(i & limb_mask)) { check_in_range(i); } + template + BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(UI i, typename boost::enable_if_c::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT + : m_data(static_cast(i & limb_mask)) {} + template + BOOST_MP_FORCEINLINE cpp_int_base(UI i, typename boost::enable_if_c::value && (Checked == checked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval().check_in_range(std::declval()))) + : m_data(static_cast(i & limb_mask)) { check_in_range(i); } +#else template BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(SI i, typename boost::enable_if_c::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT : m_data(i < 0 ? (1 + ~static_cast(-i)) & limb_mask : static_cast(i) & limb_mask) {} @@ -927,6 +941,7 @@ public: template BOOST_MP_FORCEINLINE cpp_int_base(UI i, typename boost::enable_if_c::value && (Checked == checked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval().check_in_range(std::declval()))) : m_data(static_cast(i)) { check_in_range(i); } +#endif template BOOST_MP_FORCEINLINE cpp_int_base(F i, typename boost::enable_if >::type const* = 0) BOOST_MP_NOEXCEPT_IF((Checked == unchecked)) : m_data(static_cast(std::fabs(i)) & limb_mask) @@ -1208,7 +1223,11 @@ private: BOOST_STATIC_ASSERT(sizeof(i) == 2 * sizeof(limb_type)); BOOST_STATIC_ASSERT(base_type::internal_limb_count >= 2); typename base_type::limb_pointer p = this->limbs(); +#ifdef __MSVC_RUNTIME_CHECKS + *p = static_cast(i & ~static_cast(0)); +#else *p = static_cast(i); +#endif p[1] = static_cast(i >> base_type::limb_bits); this->resize(p[1] ? 2 : 1, p[1] ? 2 : 1); this->sign(false); @@ -1223,7 +1242,11 @@ private: s = true; ui = static_cast(boost::multiprecision::detail::unsigned_abs(i)); typename base_type::limb_pointer p = this->limbs(); +#ifdef __MSVC_RUNTIME_CHECKS + *p = static_cast(ui & ~static_cast(0)); +#else *p = static_cast(ui); +#endif p[1] = static_cast(ui >> base_type::limb_bits); this->resize(p[1] ? 2 : 1, p[1] ? 2 : 1); this->sign(s); diff --git a/include/boost/multiprecision/cpp_int/add.hpp b/include/boost/multiprecision/cpp_int/add.hpp index 189078a8..22b8c186 100644 --- a/include/boost/multiprecision/cpp_int/add.hpp +++ b/include/boost/multiprecision/cpp_int/add.hpp @@ -49,7 +49,11 @@ inline void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BO while(pr != pr_end) { carry += static_cast(*pa) + static_cast(*pb); +#ifdef __MSVC_RUNTIME_CHECKS + *pr = static_cast(carry & ~static_cast(0)); +#else *pr = static_cast(carry); +#endif carry >>= CppInt1::limb_bits; ++pr, ++pa, ++pb; } @@ -68,7 +72,11 @@ inline void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BO break; } carry += static_cast(*pa); +#ifdef __MSVC_RUNTIME_CHECKS + *pr = static_cast(carry & ~static_cast(0)); +#else *pr = static_cast(carry); +#endif carry >>= CppInt1::limb_bits; ++pr, ++pa; } @@ -100,7 +108,11 @@ inline void add_unsigned(CppInt1& result, const CppInt2& a, const limb_type& o) for(; carry && (i < result.size()); ++i) { carry += static_cast(pa[i]); +#ifdef __MSVC_RUNTIME_CHECKS + pr[i] = static_cast(carry & ~static_cast(0)); +#else pr[i] = static_cast(carry); +#endif carry >>= CppInt1::limb_bits; } // Just copy any remaining digits: diff --git a/include/boost/multiprecision/cpp_int/divide.hpp b/include/boost/multiprecision/cpp_int/divide.hpp index 5fe6ce6a..2f83d1ba 100644 --- a/include/boost/multiprecision/cpp_int/divide.hpp +++ b/include/boost/multiprecision/cpp_int/divide.hpp @@ -227,12 +227,20 @@ void divide_unsigned_helper( for(unsigned i = 0; i < y.size(); ++i) { carry += static_cast(py[i]) * static_cast(guess); +#ifdef __MSVC_RUNTIME_CHECKS + pt[i + shift] = static_cast(carry & ~static_cast(0)); +#else pt[i + shift] = static_cast(carry); +#endif carry >>= CppInt1::limb_bits; } if(carry && !truncated_t) { +#ifdef __MSVC_RUNTIME_CHECKS + pt[t.size() - 1] = static_cast(carry & ~static_cast(0)); +#else pt[t.size() - 1] = static_cast(carry); +#endif } else if(!truncated_t) { diff --git a/include/boost/multiprecision/cpp_int/import_export.hpp b/include/boost/multiprecision/cpp_int/import_export.hpp index 42685c7c..0fe3249d 100644 --- a/include/boost/multiprecision/cpp_int/import_export.hpp +++ b/include/boost/multiprecision/cpp_int/import_export.hpp @@ -20,7 +20,7 @@ namespace boost { limb_type mask = chunk_bits >= sizeof(limb_type) * CHAR_BIT ? ~static_cast(0u) : (static_cast(1u) << chunk_bits) - 1; - limb_type value = (static_cast(bits) & mask) << shift; + limb_type value = static_cast(bits & mask) << shift; if(value) { if(val.size() == limb) @@ -132,7 +132,7 @@ namespace boost { if(byte_len % sizeof(limb_type)) ++limb_len; cpp_int_backend& result = val.backend(); - result.resize(limb_len, limb_len); // checked types may throw here if they're not large enough to hold the data! + result.resize(static_cast(limb_len), static_cast(limb_len)); // checked types may throw here if they're not large enough to hold the data! result.limbs()[result.size() - 1] = 0u; std::memcpy(result.limbs(), i, std::min(byte_len, result.size() * sizeof(limb_type))); result.normalize(); // In case data has leading zeros. @@ -149,7 +149,7 @@ namespace boost { if(byte_len % sizeof(result.limbs()[0])) ++limb_len; result.limbs()[0] = 0u; - result.resize(limb_len, limb_len); // checked types may throw here if they're not large enough to hold the data! + result.resize(static_cast(limb_len), static_cast(limb_len)); // checked types may throw here if they're not large enough to hold the data! std::memcpy(result.limbs(), i, std::min(byte_len, result.size() * sizeof(result.limbs()[0]))); result.normalize(); // In case data has leading zeros. return val; diff --git a/include/boost/multiprecision/cpp_int/misc.hpp b/include/boost/multiprecision/cpp_int/misc.hpp index 43983278..a1c98003 100644 --- a/include/boost/multiprecision/cpp_int/misc.hpp +++ b/include/boost/multiprecision/cpp_int/misc.hpp @@ -326,7 +326,11 @@ inline double_limb_type integer_gcd_reduce(double_limb_type u, double_limb_type break; } v -= u; +#ifdef __MSVC_RUNTIME_CHECKS + while((v & 1u) == 0) +#else while((static_cast(v) & 1u) == 0) +#endif v >>= 1; } while(true); return u; diff --git a/include/boost/multiprecision/cpp_int/multiply.hpp b/include/boost/multiprecision/cpp_int/multiply.hpp index f82f7bdd..d3e324db 100644 --- a/include/boost/multiprecision/cpp_int/multiply.hpp +++ b/include/boost/multiprecision/cpp_int/multiply.hpp @@ -36,7 +36,11 @@ inline typename enable_if_c(*pa) * static_cast(val); +#ifdef __MSVC_RUNTIME_CHECKS + *p = static_cast(carry & ~static_cast(0)); +#else *p = static_cast(carry); +#endif carry >>= cpp_int_backend::limb_bits; ++p, ++pa; } @@ -144,7 +148,11 @@ inline typename enable_if_c(pa[i]) * static_cast(pb[j]); BOOST_ASSERT(!std::numeric_limits::is_specialized || ((std::numeric_limits::max)() - carry >= pr[i+j])); carry += pr[i + j]; +#ifdef __MSVC_RUNTIME_CHECKS + pr[i + j] = static_cast(carry & ~static_cast(0)); +#else pr[i + j] = static_cast(carry); +#endif carry >>= cpp_int_backend::limb_bits; BOOST_ASSERT(carry <= (cpp_int_backend::max_limb_value)); } @@ -353,6 +361,16 @@ BOOST_MP_FORCEINLINE typename enable_if_c< limb_type* pr = result.limbs(); double_limb_type carry = w * y; +#ifdef __MSVC_RUNTIME_CHECKS + pr[0] = static_cast(carry & ~static_cast(0)); + carry >>= limb_bits; + carry += w * z + x * y; + pr[1] = static_cast(carry & ~static_cast(0)); + carry >>= limb_bits; + carry += x * z; + pr[2] = static_cast(carry & ~static_cast(0)); + pr[3] = static_cast(carry >> limb_bits); +#else pr[0] = static_cast(carry); carry >>= limb_bits; carry += w * z + x * y; @@ -361,7 +379,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c< carry += x * z; pr[2] = static_cast(carry); pr[3] = static_cast(carry >> limb_bits); - +#endif result.sign(s); result.normalize(); } @@ -387,6 +405,20 @@ BOOST_MP_FORCEINLINE typename enable_if_c< limb_type* pr = result.limbs(); double_limb_type carry = w * y; +#ifdef __MSVC_RUNTIME_CHECKS + pr[0] = static_cast(carry & ~static_cast(0)); + carry >>= limb_bits; + carry += w * z; + pr[1] = static_cast(carry & ~static_cast(0)); + carry >>= limb_bits; + pr[2] = static_cast(carry & ~static_cast(0)); + carry = x * y + pr[1]; + pr[1] = static_cast(carry & ~static_cast(0)); + carry >>= limb_bits; + carry += pr[2] + x * z; + pr[2] = static_cast(carry & ~static_cast(0)); + pr[3] = static_cast(carry >> limb_bits); +#else pr[0] = static_cast(carry); carry >>= limb_bits; carry += w * z; @@ -399,7 +431,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c< carry += pr[2] + x * z; pr[2] = static_cast(carry); pr[3] = static_cast(carry >> limb_bits); - +#endif result.sign(false); result.normalize(); } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 22d0fa43..93c3e41f 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -36,6 +36,9 @@ project : requirements gcc:-Wall gcc:-Wextra intel:SLOW_COMPILER + msvc,off:-RTC1 + msvc,off:-RTCc + msvc,off:_ALLOW_RTCc_IN_STL ; local enable-specfun = [ MATCH (--enable-specfun) : [ modules.peek : ARGV ] ] ;