|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r77303 - in sandbox/big_number: boost/multiprecision libs/multiprecision/performance libs/multiprecision/test
From: john_at_[hidden]
Date: 2012-03-11 12:43:33
Author: johnmaddock
Date: 2012-03-11 12:43:31 EDT (Sun, 11 Mar 2012)
New Revision: 77303
URL: http://svn.boost.org/trac/boost/changeset/77303
Log:
Fix several division algorithm bugs.
Add cpp_rational to performance tests.
Add modular arithmetic test to test cases.
Text files modified:
sandbox/big_number/boost/multiprecision/cpp_int.hpp | 39 ++++++++++++++++++++++++++-------------
sandbox/big_number/libs/multiprecision/performance/performance_test.cpp | 15 ++++++++-------
sandbox/big_number/libs/multiprecision/test/test_cpp_int.cpp | 18 ++++++++++++++++++
3 files changed, 52 insertions(+), 20 deletions(-)
Modified: sandbox/big_number/boost/multiprecision/cpp_int.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/cpp_int.hpp (original)
+++ sandbox/big_number/boost/multiprecision/cpp_int.hpp 2012-03-11 12:43:31 EDT (Sun, 11 Mar 2012)
@@ -1061,9 +1061,9 @@
double_limb_type carry = 0;
std::memset(pr, 0, result.size() * sizeof(limb_type));
- unsigned inner_limit = result.size() - as;
for(unsigned i = 0; i < as; ++i)
{
+ unsigned inner_limit = (std::min)(result.size() - i, b.size());
for(unsigned j = 0; j < inner_limit; ++j)
{
BOOST_ASSERT(i+j < result.size());
@@ -1262,10 +1262,6 @@
do
{
//
- // Update r_order, this can't run past the end as r must be non-zero at this point:
- //
- r_order = r.size() - 1;
- //
// Calculate our best guess for how many times y divides into r:
//
limb_type guess;
@@ -1329,6 +1325,7 @@
//
double_limb_type carry = 0;
t.resize(y.size() + shift + 1);
+ bool truncated_t = !cpp_int_backend<MinBits, Signed, Allocator>::variable && (t.size() != y.size() + shift + 1);
typename cpp_int_backend<MinBits, Signed, Allocator>::limb_pointer pt = t.limbs();
for(unsigned i = 0; i < shift; ++i)
pt[i] = 0;
@@ -1338,11 +1335,11 @@
pt[i + shift] = static_cast<limb_type>(carry);
carry >>= cpp_int_backend<MinBits, Signed, Allocator>::limb_bits;
}
- if(carry)
+ if(carry && !truncated_t)
{
pt[t.size() - 1] = static_cast<limb_type>(carry);
}
- else
+ else if(!truncated_t)
{
t.resize(t.size() - 1);
}
@@ -1365,15 +1362,21 @@
while(pr[result.size() - 1] == 0)
result.resize(result.size() - 1);
}
+ //
+ // Update r_order:
+ //
+ r_order = r.size() - 1;
+ if(r_order < y_order)
+ break;
}
- // Termination condition is really just a check that r > y, but with two common
- // short-circuit cases handled first:
- while((r_order > y_order) || (prem[r_order] > py[y_order]) || (r.compare_unsigned(y) > 0));
+ // Termination condition is really just a check that r > y, but with a common
+ // short-circuit case handled first:
+ while((r_order > y_order) || (r.compare_unsigned(y) >= 0));
//
// We now just have to normalise the result:
//
- if(r_neg)
+ if(r_neg && get_sign(r))
{
// We have one too many in the result:
decrement(result);
@@ -1480,19 +1483,29 @@
--r_order;
pr[r_order] = static_cast<limb_type>(b);
pres[r_order] = static_cast<limb_type>(a / y);
+ if(r_order && pr[r_order] == 0)
+ {
+ --r_order; // No remainder, division was exact.
+ r.resize(r.size() - 1);
+ }
}
else
{
pres[r_order] = pr[r_order] / y;
pr[r_order] %= y;
+ if(r_order && pr[r_order] == 0)
+ {
+ --r_order; // No remainder, division was exact.
+ r.resize(r.size() - 1);
+ }
}
}
// Termination condition is really just a check that r > y, but with two common
// short-circuit cases handled first:
while(r_order || (pr[r_order] > y));
- if(pres[result.size() - 1] == 0)
- result.resize(result.size() - 1);
+ result.normalize();
+ r.normalize();
result.sign(x.sign());
r.sign(x.sign());
Modified: sandbox/big_number/libs/multiprecision/performance/performance_test.cpp
==============================================================================
--- sandbox/big_number/libs/multiprecision/performance/performance_test.cpp (original)
+++ sandbox/big_number/libs/multiprecision/performance/performance_test.cpp 2012-03-11 12:43:31 EDT (Sun, 11 Mar 2012)
@@ -12,7 +12,7 @@
#if !defined(TEST_MPF) && !defined(TEST_MPZ) && \
!defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPQ) \
&& !defined(TEST_TOMMATH) && !defined(TEST_TOMMATH_BOOST_RATIONAL) && !defined(TEST_MPZ_BOOST_RATIONAL)\
- && !defined(TEST_FIXED_INT) && !defined(TEST_CPP_INT)
+ && !defined(TEST_FIXED_INT) && !defined(TEST_CPP_INT) && !defined(TEST_CPP_INT_RATIONAL)
# define TEST_MPF
# define TEST_MPZ
# define TEST_MPQ
@@ -22,6 +22,7 @@
# define TEST_TOMMATH
# define TEST_FIXED_INT
# define TEST_CPP_INT
+# define TEST_CPP_INT_RATIONAL
#ifdef _MSC_VER
#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!")
@@ -575,14 +576,12 @@
test<boost::multiprecision::mpf_float_500>("gmp_float", 500);
#endif
#ifdef TEST_MPZ
- test<boost::multiprecision::mpz_int>("gmp_int", 64);
test<boost::multiprecision::mpz_int>("gmp_int", 128);
test<boost::multiprecision::mpz_int>("gmp_int", 256);
test<boost::multiprecision::mpz_int>("gmp_int", 512);
test<boost::multiprecision::mpz_int>("gmp_int", 1024);
#endif
#ifdef TEST_CPP_INT
- test<boost::multiprecision::cpp_int>("cpp_int", 64);
test<boost::multiprecision::cpp_int>("cpp_int", 128);
test<boost::multiprecision::cpp_int>("cpp_int", 256);
test<boost::multiprecision::cpp_int>("cpp_int", 512);
@@ -593,15 +592,19 @@
test<boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<512, true, void> > >("cpp_int(fixed)", 512);
test<boost::multiprecision::mp_number<boost::multiprecision::cpp_int_backend<1024, true, void> > >("cpp_int(fixed)", 1024);
#endif
+#ifdef TEST_CPP_INT_RATIONAL
+ test<boost::multiprecision::cpp_rational>("cpp_rational", 128);
+ test<boost::multiprecision::cpp_rational>("cpp_rational", 256);
+ test<boost::multiprecision::cpp_rational>("cpp_rational", 512);
+ test<boost::multiprecision::cpp_rational>("cpp_rational", 1024);
+#endif
#ifdef TEST_MPQ
- test<boost::multiprecision::mpq_rational>("mpq_rational", 64);
test<boost::multiprecision::mpq_rational>("mpq_rational", 128);
test<boost::multiprecision::mpq_rational>("mpq_rational", 256);
test<boost::multiprecision::mpq_rational>("mpq_rational", 512);
test<boost::multiprecision::mpq_rational>("mpq_rational", 1024);
#endif
#ifdef TEST_TOMMATH
- test<boost::multiprecision::mp_int>("tommath_int", 64);
test<boost::multiprecision::mp_int>("tommath_int", 128);
test<boost::multiprecision::mp_int>("tommath_int", 256);
test<boost::multiprecision::mp_int>("tommath_int", 512);
@@ -610,7 +613,6 @@
//
// These are actually too slow to test!!!
//
- test<boost::multiprecision::mp_rational>("mp_rational", 64);
test<boost::multiprecision::mp_rational>("mp_rational", 128);
test<boost::multiprecision::mp_rational>("mp_rational", 256);
test<boost::multiprecision::mp_rational>("mp_rational", 512);
@@ -618,7 +620,6 @@
*/
#endif
#ifdef TEST_FIXED_INT
- test<boost::multiprecision::mp_number<boost::multiprecision::fixed_int<64, true> > >("fixed_int", 64);
test<boost::multiprecision::mp_int128_t>("fixed_int", 128);
test<boost::multiprecision::mp_int256_t>("fixed_int", 256);
test<boost::multiprecision::mp_int512_t>("fixed_int", 512);
Modified: sandbox/big_number/libs/multiprecision/test/test_cpp_int.cpp
==============================================================================
--- sandbox/big_number/libs/multiprecision/test/test_cpp_int.cpp (original)
+++ sandbox/big_number/libs/multiprecision/test/test_cpp_int.cpp 2012-03-11 12:43:31 EDT (Sun, 11 Mar 2012)
@@ -137,6 +137,24 @@
BOOST_CHECK_EQUAL(mpz_int(lcm(-c, -d)).str(), test_type(lcm(-c1, -d1)).str());
BOOST_CHECK_EQUAL(mpz_int(gcd(a, -b)).str(), test_type(gcd(a1, -b1)).str());
BOOST_CHECK_EQUAL(mpz_int(lcm(c, -d)).str(), test_type(lcm(c1, -d1)).str());
+
+ if(std::numeric_limits<test_type>::is_modulo)
+ {
+ static mpz_int m = mpz_int(1) << std::numeric_limits<test_type>::digits;
+ mpz_int t(a);
+ test_type t1(a1);
+ for(unsigned i = 0; i < 10; ++i)
+ {
+ t *= a;
+ t %= m;
+ t += a;
+ t %= m;
+ t1 *= a1;
+ t1 += a1;
+ }
+ BOOST_CHECK_EQUAL(t.str(), t1.str());
+ }
+
if(last_error_count != boost::detail::test_errors())
{
last_error_count = boost::detail::test_errors();
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