Add rvalue reference support.

Add LINPACK benchmark test.
Update arithmetic tests to work with types other than big_number.
Fix precision of ostream& operator<<.

[SVN r73649]
This commit is contained in:
John Maddock
2011-08-11 11:28:11 +00:00
parent 0fa9745248
commit 30fbb4d528
5 changed files with 1345 additions and 21 deletions

View File

@@ -190,13 +190,6 @@ public:
BOOST_ASSERT(proto::value(*this) == this);
m_backend = canonical_value(v);
}
/*
big_number(unsigned digits10, typename enable_if_c<false == Backend::is_fixed>::type* dummy = 0)
: base_type(digits10)
{
proto::value(*this) = this;
BOOST_ASSERT(proto::value(*this) == this);
}*/
big_number(const big_number& e, unsigned digits10) : m_backend(e.m_backend, digits10)
{
proto::value(*this) = this;
@@ -240,6 +233,19 @@ public:
do_assign(e, typename proto::tag_of<Exp>::type());
}
#ifndef BOOST_NO_RVALUE_REFERENCES
big_number(big_number&& r) : m_backend(r.m_backend)
{
proto::value(*this) = this;
BOOST_ASSERT(proto::value(*this) == this);
}
big_number& operator=(big_number&& r)
{
m_backend.swap(r.m_backend);
return *this;
}
#endif
template <class Exp>
big_number& operator+=(const detail::big_number_exp<Exp>& e)
{
@@ -367,9 +373,9 @@ public:
//
// String conversion functions:
//
std::string str()const
std::string str(unsigned digits = 0)const
{
return m_backend.str();
return m_backend.str(digits);
}
//
// Default precision:
@@ -1160,7 +1166,7 @@ inline typename boost::enable_if<detail::is_valid_comparison<Exp1, Exp2>, bool>:
template <class Backend>
std::ostream& operator << (std::ostream& os, const big_number<Backend>& r)
{
return os << r.str();
return os << r.str(static_cast<unsigned>(os.precision()));
}
template <class Backend>

View File

@@ -33,11 +33,25 @@ struct gmp_real_imp
{
mpf_init_set(m_data, o.m_data);
}
#ifndef BOOST_NO_RVALUE_REFERENCES
gmp_real_imp(gmp_real_imp&& o)
{
m_data[0] = o.m_data[0];
o.m_data[0]._mp_d = 0;
}
#endif
gmp_real_imp& operator = (const gmp_real_imp& o)
{
mpf_set(m_data, o.m_data);
return *this;
}
#ifndef BOOST_NO_RVALUE_REFERENCES
gmp_real_imp& operator = (gmp_real_imp&& o)
{
mpf_swap(m_data, o.m_data);
return *this;
}
#endif
gmp_real_imp& operator = (boost::uintmax_t i)
{
boost::uintmax_t mask = ((1uLL << std::numeric_limits<unsigned>::digits) - 1);
@@ -233,13 +247,13 @@ struct gmp_real_imp
{
mpf_swap(m_data, o.m_data);
}
std::string str()const
std::string str(unsigned digits)const
{
mp_exp_t e;
void *(*alloc_func_ptr) (size_t);
void *(*realloc_func_ptr) (void *, size_t, size_t);
void (*free_func_ptr) (void *, size_t);
const char* ps = mpf_get_str (0, &e, 10, 0, m_data);
const char* ps = mpf_get_str (0, &e, 10, digits, m_data);
std::string s("0.");
if(ps[0] == '-')
{
@@ -258,7 +272,8 @@ struct gmp_real_imp
}
~gmp_real_imp()
{
mpf_clear(m_data);
if(m_data[0]._mp_d)
mpf_clear(m_data);
}
void negate()
{
@@ -299,13 +314,21 @@ struct gmp_real : public detail::gmp_real_imp<digits10>
mpf_init2(this->m_data, ((digits10 + 1) * 1000L) / 301L);
}
gmp_real(const gmp_real& o) : gmp_real_imp(o) {}
#ifndef BOOST_NO_RVALUE_REFERENCES
gmp_real(gmp_real&& o) : gmp_real_imp(o) {}
#endif
gmp_real& operator=(const gmp_real& o)
{
*static_cast<detail::gmp_real_imp<digits10>*>(this) = static_cast<detail::gmp_real_imp<digits10> const&>(o);
return *this;
}
#ifndef BOOST_NO_RVALUE_REFERENCES
gmp_real& operator=(gmp_real&& o)
{
*static_cast<detail::gmp_real_imp<digits10>*>(this) = static_cast<detail::gmp_real_imp<digits10>&&>(o);
return *this;
}
#endif
template <class V>
gmp_real& operator=(const V& v)
{
@@ -326,6 +349,9 @@ struct gmp_real<0> : public detail::gmp_real_imp<0>
mpf_init2(this->m_data, ((digits10 + 1) * 1000L) / 301L);
}
gmp_real(const gmp_real& o) : gmp_real_imp(o) {}
#ifndef BOOST_NO_RVALUE_REFERENCES
gmp_real(gmp_real&& o) : gmp_real_imp(o) {}
#endif
gmp_real(const gmp_real& o, unsigned digits10)
{
mpf_init2(this->m_data, ((digits10 + 1) * 1000L) / 301L);
@@ -337,7 +363,13 @@ struct gmp_real<0> : public detail::gmp_real_imp<0>
*static_cast<detail::gmp_real_imp<0>*>(this) = static_cast<detail::gmp_real_imp<0> const&>(o);
return *this;
}
#ifndef BOOST_NO_RVALUE_REFERENCES
gmp_real& operator=(gmp_real&& o)
{
*static_cast<detail::gmp_real_imp<0>*>(this) = static_cast<detail::gmp_real_imp<0> &&>(o);
return *this;
}
#endif
template <class V>
gmp_real& operator=(const V& v)
{
@@ -706,7 +738,7 @@ struct gmp_int
{
mpz_swap(m_data, o.m_data);
}
std::string str()const
std::string str(unsigned)const
{
void *(*alloc_func_ptr) (size_t);
void *(*realloc_func_ptr) (void *, size_t, size_t);

View File

@@ -252,7 +252,7 @@ struct big_number_backend_real_architype
std::cout << "Swapping (" << m_value << " with " << o.m_value << ")" << std::endl;
std::swap(m_value, o.m_value);
}
std::string str()const
std::string str(unsigned)const
{
std::string s(boost::lexical_cast<std::string>(m_value));
std::cout << "Converting to string (" << s << ")" << std::endl;

File diff suppressed because it is too large Load Diff

View File

@@ -4,10 +4,8 @@
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
#include <boost/detail/lightweight_test.hpp>
#include <boost/math/concepts/big_number_architypes.hpp>
#include <boost/math/big_number/gmp.hpp>
#if !defined(TEST_MPF50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ)
#if !defined(TEST_MPF50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_E_FLOAT)
# define TEST_MPF50
# define TEST_MPF
# define TEST_BACKEND
@@ -22,6 +20,17 @@
#endif
#if defined(TEST_MPF50) || defined(TEST_MPF) || defined(TEST_MPZ)
#include <boost/math/big_number/gmp.hpp>
#endif
#ifdef TEST_BACKEND
#include <boost/math/concepts/big_number_architypes.hpp>
#endif
#ifdef TEST_E_FLOAT
#include <boost/math/big_number.hpp>
#include <boost/math/bindings/e_float.hpp>
#endif
template <class Real>
void test_integer_ops(const boost::mpl::false_&){}
@@ -83,9 +92,12 @@ void test_real_ops(const boost::mpl::true_&)
BOOST_TEST(ceil(Real(5) / 2) == 3);
BOOST_TEST(floor(Real(-5) / 2) == -3);
BOOST_TEST(ceil(Real(-5) / 2) == -2);
#ifndef TEST_E_FLOAT
BOOST_TEST(trunc(Real(5) / 2) == 2);
BOOST_TEST(trunc(Real(-5) / 2) == -2);
#endif
#ifndef TEST_E_FLOAT
//
// ldexp and frexp, these pretty much have to implemented by each backend:
//
@@ -100,6 +112,7 @@ void test_real_ops(const boost::mpl::true_&)
r = frexp(v, &exp);
BOOST_TEST(r == 0.5);
BOOST_TEST(exp == -8);
#endif
}
template <class Real, class Num>
@@ -347,8 +360,10 @@ void test()
ac = a * ac;
BOOST_TEST(ac == 8*8);
ac = a;
#ifndef TEST_E_FLOAT
ac = ac + "8";
BOOST_TEST(ac == 16);
#endif
ac = a;
ac += +a;
BOOST_TEST(ac == 16);
@@ -362,8 +377,10 @@ void test()
ac += b*c;
BOOST_TEST(ac == 8 + 64 * 500);
ac = a;
#ifndef TEST_E_FLOAT
ac = ac - "8";
BOOST_TEST(ac == 0);
#endif
ac = a;
ac -= +a;
BOOST_TEST(ac == 0);
@@ -382,8 +399,12 @@ void test()
ac = a;
ac -= ac * b;
BOOST_TEST(ac == 8 - 8 * 64);
#ifndef TEST_E_FLOAT
ac = a * "8";
BOOST_TEST(ac == 64);
#else
ac = a * 8;
#endif
ac *= +a;
BOOST_TEST(ac == 64 * 8);
ac = a;
@@ -398,8 +419,10 @@ void test()
ac = a;
ac *= b + c;
BOOST_TEST(ac == 8 * (64 + 500));
#ifndef TEST_E_FLOAT
ac = b / "8";
BOOST_TEST(ac == 8);
#endif
ac = b;
ac /= +a;
BOOST_TEST(ac == 8);
@@ -412,8 +435,10 @@ void test()
ac = b;
ac /= a + Real(0);
BOOST_TEST(ac == 8);
#ifndef TEST_E_FLOAT
ac = a + std::string("8");
BOOST_TEST(ac == 16);
#endif
//
// Comparisons:
//
@@ -484,6 +509,9 @@ int main()
#endif
#ifdef TEST_MPZ
test<boost::math::mpz_int>();
#endif
#ifdef TEST_E_FLOAT
test<boost::math::ef::e_float>();
#endif
return boost::report_errors();
}