|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r83080 - in trunk: boost/multiprecision/cpp_int libs/multiprecision/test
From: john_at_[hidden]
Date: 2013-02-22 05:37:36
Author: johnmaddock
Date: 2013-02-22 05:37:36 EST (Fri, 22 Feb 2013)
New Revision: 83080
URL: http://svn.boost.org/trac/boost/changeset/83080
Log:
Fix bug in subtraction of a limb_type.
Fix bug in division/modulus algorithms that results in incorrect sign when source and destination overlap.
Tweak performance of GCD algorithms.
Add test cases for bug reports.
Fixes #8133.
Fixes #8126.
Text files modified:
trunk/boost/multiprecision/cpp_int/add.hpp | 2
trunk/boost/multiprecision/cpp_int/divide.hpp | 18 +++++++++----
trunk/boost/multiprecision/cpp_int/misc.hpp | 12 ++++++++-
trunk/libs/multiprecision/test/test_cpp_int.cpp | 50 ++++++++++++++++++++++++---------------
4 files changed, 54 insertions(+), 28 deletions(-)
Modified: trunk/boost/multiprecision/cpp_int/add.hpp
==============================================================================
--- trunk/boost/multiprecision/cpp_int/add.hpp (original)
+++ trunk/boost/multiprecision/cpp_int/add.hpp 2013-02-22 05:37:36 EST (Fri, 22 Feb 2013)
@@ -211,7 +211,7 @@
result.resize(a.size(), a.size());
typename CppInt1::limb_pointer pr = result.limbs();
typename CppInt2::const_limb_pointer pa = a.limbs();
- if(*pa > b)
+ if(*pa >= b)
{
*pr = *pa - b;
if(&result != &a)
Modified: trunk/boost/multiprecision/cpp_int/divide.hpp
==============================================================================
--- trunk/boost/multiprecision/cpp_int/divide.hpp (original)
+++ trunk/boost/multiprecision/cpp_int/divide.hpp 2013-02-22 05:37:36 EST (Fri, 22 Feb 2013)
@@ -116,7 +116,6 @@
if(result)
{
*result = px[0] / py[0];
- result->sign(x.sign() != y.sign());
}
r = px[0] % py[0];
return;
@@ -131,7 +130,6 @@
if(result)
{
*result = a / b;
- result->sign(x.sign() != y.sign());
}
r = a % b;
return;
@@ -452,8 +450,9 @@
const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
{
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
+ bool s = a.sign() != b.sign();
divide_unsigned_helper(&result, a, b, r);
- result.sign(a.sign() != b.sign());
+ result.sign(s);
}
template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
@@ -464,7 +463,9 @@
limb_type& b)
{
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
+ bool s = a.sign();
divide_unsigned_helper(&result, a, b, r);
+ result.sign(s);
}
template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
@@ -475,9 +476,9 @@
signed_limb_type& b)
{
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> r;
+ bool s = a.sign() != (b < 0);
divide_unsigned_helper(&result, a, static_cast<limb_type>(std::abs(b)), r);
- if(b < 0)
- result.negate();
+ result.sign(s);
}
template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
@@ -520,8 +521,9 @@
const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b)
{
+ bool s = a.sign();
divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>* >(0), a, b, result);
- result.sign(a.sign());
+ result.sign(s);
}
template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
@@ -530,7 +532,9 @@
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a, limb_type b)
{
+ bool s = a.sign();
divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>* >(0), a, b, result);
+ result.sign(s);
}
template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
@@ -540,7 +544,9 @@
const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a,
signed_limb_type b)
{
+ bool s = a.sign();
divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>* >(0), a, static_cast<limb_type>(std::abs(b)), result);
+ result.sign(s);
}
template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
Modified: trunk/boost/multiprecision/cpp_int/misc.hpp
==============================================================================
--- trunk/boost/multiprecision/cpp_int/misc.hpp (original)
+++ trunk/boost/multiprecision/cpp_int/misc.hpp 2013-02-22 05:37:36 EST (Fri, 22 Feb 2013)
@@ -379,9 +379,16 @@
{
/* Now u and v are both odd, so diff(u, v) is even.
Let u = min(u, v), v = diff(u, v)/2. */
- if(u.size() == 1)
+ if(u.size() <= 2)
{
- v = integer_gcd_reduce(*u.limbs(), v);
+ if(u.size() == 1)
+ v = integer_gcd_reduce(*u.limbs(), v);
+ else
+ {
+ double_limb_type i;
+ i = u.limbs()[0] | (static_cast<double_limb_type>(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
+ v = static_cast<limb_type>(integer_gcd_reduce(i, static_cast<double_limb_type>(v)));
+ }
break;
}
eval_subtract(u, v);
@@ -431,6 +438,7 @@
if(b.size() == 1)
{
eval_gcd(result, a, *b.limbs());
+ return;
}
int shift;
Modified: trunk/libs/multiprecision/test/test_cpp_int.cpp
==============================================================================
--- trunk/libs/multiprecision/test/test_cpp_int.cpp (original)
+++ trunk/libs/multiprecision/test/test_cpp_int.cpp 2013-02-22 05:37:36 EST (Fri, 22 Feb 2013)
@@ -387,6 +387,37 @@
BOOST_CHECK_EQUAL(q, a);
BOOST_CHECK_EQUAL(r, 1);
}
+ // Bug https://svn.boost.org/trac/boost/ticket/8126:
+ test_type a("-4294967296");
+ test_type b("4294967296");
+ test_type c("-1");
+ a = (a / b);
+ BOOST_CHECK_EQUAL(a, -1);
+ a = -4294967296;
+ a = (a / b) * c;
+ BOOST_CHECK_EQUAL(a, 1);
+ a = -23;
+ b = 23;
+ a = (a / b) * c;
+ BOOST_CHECK_EQUAL(a, 1);
+ a = -23;
+ a = (a / b) / c;
+ BOOST_CHECK_EQUAL(a, 1);
+ a = test_type("-26607734784073568386365259775");
+ b = test_type("8589934592");
+ a = a / b;
+ BOOST_CHECK_EQUAL(a, test_type("-3097548007973652377"));
+ // Bug https://svn.boost.org/trac/boost/ticket/8133:
+ a = test_type("0x12345600012434ffffffffffffffffffffffff");
+ unsigned ui = 0xffffffff;
+ a = a - ui;
+ BOOST_CHECK_EQUAL(a, test_type("0x12345600012434ffffffffffffffff00000000"));
+ a = test_type("0x12345600012434ffffffffffffffffffffffff");
+#ifndef BOOST_NO_LONG_LONG
+ unsigned long long ull = 0xffffffffffffffffuLL;
+ a = a - ull;
+ BOOST_CHECK_EQUAL(a, test_type("0x12345600012434ffffffff0000000000000000"));
+#endif
}
void test()
@@ -470,25 +501,6 @@
}
}
- //
- // Specific bug report tests come last:
- //
- // Bug https://svn.boost.org/trac/boost/ticket/8126:
- test_type a("-4294967296");
- test_type b("4294967296");
- test_type c("-1");
- a = (a / b);
- BOOST_CHECK_EQUAL(a, -1);
- a = -4294967296;
- a = (a / b) * c;
- BOOST_CHECK_EQUAL(a, 1);
- a = -23;
- b = 23;
- a = (a / b) * c;
- BOOST_CHECK_EQUAL(a, 1);
- a = -23;
- a = (a / b) / c;
- BOOST_CHECK_EQUAL(a, 1);
}
};
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk