Fix bounded variable precision cpp_int's.

1) Removed some constexpr optimizations which were causing the code to fail to spot that truncation/overflow had occurred.
2) Change min/max code for numeric_limits to work for bounded variable precision types (this needs more work as the current code relies on being able to create a fixed-precision allocator-free type of equivalent width.
3) Add tests for bounded variable precision integers.
See: https://svn.boost.org/trac/boost/ticket/12798
This commit is contained in:
jzmaddock
2017-02-03 19:39:28 +00:00
parent e108817e69
commit cd2bbcba5b
6 changed files with 36 additions and 7 deletions

View File

@@ -84,7 +84,7 @@ inline void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BO
{
// We overflowed, need to add one more limb:
result.resize(x + 1, x + 1);
if(CppInt1::variable || (result.size() > x))
if(result.size() > x)
result.limbs()[x] = static_cast<limb_type>(carry);
}
result.normalize();
@@ -126,7 +126,7 @@ inline void add_unsigned(CppInt1& result, const CppInt2& a, const limb_type& o)
// We overflowed, need to add one more limb:
unsigned x = result.size();
result.resize(x + 1, x + 1);
if(CppInt1::variable || (result.size() > x))
if(result.size() > x)
result.limbs()[x] = static_cast<limb_type>(carry);
}
result.normalize();

View File

@@ -220,7 +220,7 @@ void divide_unsigned_helper(
//
double_limb_type carry = 0;
t.resize(y.size() + shift + 1, y.size() + shift);
bool truncated_t = !CppInt1::variable && (t.size() != y.size() + shift + 1);
bool truncated_t = (t.size() != y.size() + shift + 1);
typename CppInt1::limb_pointer pt = t.limbs();
for(unsigned i = 0; i < shift; ++i)
pt[i] = 0;

View File

@@ -23,7 +23,7 @@ inline boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinB
{
// Bounded and signed.
typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> result_type;
typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, Allocator>, ExpressionTemplates> ui_type;
typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MaxBits, MaxBits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked>, ExpressionTemplates> ui_type;
static const result_type val = -result_type(~ui_type(0));
return val;
}
@@ -62,7 +62,7 @@ inline boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinB
{
// Bounded and signed.
typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> result_type;
typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, Allocator>, ExpressionTemplates> ui_type;
typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MaxBits, MaxBits, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked>, ExpressionTemplates> ui_type;
static const result_type val = ~ui_type(0);
return val;
}

View File

@@ -48,7 +48,7 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
{
unsigned i = result.size();
result.resize(i + 1, i + 1);
if(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::variable || (result.size() > i))
if(result.size() > i)
result.limbs()[i] = static_cast<limb_type>(carry);
}
result.sign(a.sign());
@@ -157,7 +157,7 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
BOOST_ASSERT(carry <= (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value));
}
resize_for_carry(result, as + bs); // May throw if checking is enabled
if(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::variable || (i + bs < result.size()))
if(i + bs < result.size())
pr[i + bs] = static_cast<limb_type>(carry);
carry = 0;
}