Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r75425 - in sandbox/big_number: boost/multiprecision boost/multiprecision/detail boost/multiprecision/detail/functions libs/multiprecision/doc libs/multiprecision/test
From: john_at_[hidden]
Date: 2011-11-09 12:37:42


Author: johnmaddock
Date: 2011-11-09 12:37:40 EST (Wed, 09 Nov 2011)
New Revision: 75425
URL: http://svn.boost.org/trac/boost/changeset/75425

Log:
Get the rounding functions working and tested, update docs to match.
Added:
   sandbox/big_number/libs/multiprecision/test/test_round.cpp (contents, props changed)
Text files modified:
   sandbox/big_number/boost/multiprecision/detail/default_ops.hpp | 151 +++++++++++++------
   sandbox/big_number/boost/multiprecision/detail/functions/pow.hpp | 25 +++
   sandbox/big_number/boost/multiprecision/gmp.hpp | 5
   sandbox/big_number/boost/multiprecision/mp_float.hpp | 9
   sandbox/big_number/boost/multiprecision/mp_number.hpp | 6
   sandbox/big_number/boost/multiprecision/mpfr.hpp | 22 ++
   sandbox/big_number/libs/multiprecision/doc/multiprecision.qbk | 303 +++++++++++++++++++++++++++++++++++----
   sandbox/big_number/libs/multiprecision/test/Jamfile.v2 | 32 ++++
   sandbox/big_number/libs/multiprecision/test/test_log.cpp | 13 +
   9 files changed, 477 insertions(+), 89 deletions(-)

Modified: sandbox/big_number/boost/multiprecision/detail/default_ops.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/detail/default_ops.hpp (original)
+++ sandbox/big_number/boost/multiprecision/detail/default_ops.hpp 2011-11-09 12:37:40 EST (Wed, 09 Nov 2011)
@@ -382,6 +382,12 @@
 template <class T>
 inline void eval_trunc(T& result, const T& a)
 {
+ int c = eval_fpclassify(a);
+ if(c == FP_NAN || c == FP_INFINITE)
+ {
+ result = boost::math::policies::raise_rounding_error("boost::multiprecision::trunc<%1%>(%1%)", 0, mp_number<T>(a), 0, boost::math::policies::policy<>()).backend();
+ return;
+ }
    if(get_sign(a) < 0)
       eval_ceil(result, a);
    else
@@ -392,6 +398,12 @@
 inline void eval_round(T& result, const T& a)
 {
    typedef typename boost::multiprecision::detail::canonical<float, T>::type fp_type;
+ int c = eval_fpclassify(a);
+ if(c == FP_NAN || c == FP_INFINITE)
+ {
+ result = boost::math::policies::raise_rounding_error("boost::multiprecision::round<%1%>(%1%)", 0, mp_number<T>(a), 0, boost::math::policies::policy<>()).backend();
+ return;
+ }
    if(get_sign(a) < 0)
    {
       subtract(result, a, fp_type(0.5f));
@@ -420,31 +432,6 @@
 template <class T>
 typename enable_if_c<sizeof(T) == 0>::type eval_frexp();
 //
-// TODO: implement default versions of these:
-//
-template <class T>
-typename enable_if_c<sizeof(T) == 0>::type eval_exp();
-template <class T>
-typename enable_if_c<sizeof(T) == 0>::type eval_log();
-template <class T>
-typename enable_if_c<sizeof(T) == 0>::type eval_sin();
-template <class T>
-typename enable_if_c<sizeof(T) == 0>::type eval_cos();
-template <class T>
-typename enable_if_c<sizeof(T) == 0>::type eval_tan();
-template <class T>
-typename enable_if_c<sizeof(T) == 0>::type eval_asin();
-template <class T>
-typename enable_if_c<sizeof(T) == 0>::type eval_acos();
-template <class T>
-typename enable_if_c<sizeof(T) == 0>::type eval_atan();
-template <class T>
-typename enable_if_c<sizeof(T) == 0>::type eval_sinh();
-template <class T>
-typename enable_if_c<sizeof(T) == 0>::type eval_cosh();
-template <class T>
-typename enable_if_c<sizeof(T) == 0>::type eval_tanh();
-//
 // These functions are implemented in separate files, but expanded inline here,
 // DO NOT CHANGE THE ORDER OF THESE INCLUDES:
 //
@@ -527,7 +514,7 @@
 inline typename detail::mp_exp<tag, A1, A2, A3>::result_type trunc(const detail::mp_exp<tag, A1, A2, A3>& v, const Policy& pol)
 {
    typedef typename detail::mp_exp<tag, A1, A2, A3>::result_type number_type;
- return trunc(v, pol);
+ return trunc(number_type(v), pol);
 }
 
 template <class Backend, class Policy>
@@ -544,58 +531,88 @@
 {
    typedef typename detail::mp_exp<tag, A1, A2, A3>::result_type number_type;
    number_type r = trunc(v, pol);
- if(fabs(r) > (std::numeric_limits<int>::max)())
- return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, v, 0, pol).template convert_to<int>();
+ if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !boost::math::isfinite(v))
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, number_type(v), 0, pol).template convert_to<int>();
    return r.template convert_to<int>();
 }
+template <class tag, class A1, class A2, class A3>
+inline int itrunc(const detail::mp_exp<tag, A1, A2, A3>& v)
+{
+ return itrunc(v, boost::math::policies::policy<>());
+}
 template <class Backend, class Policy>
 inline int itrunc(const mp_number<Backend>& v, const Policy& pol)
 {
    mp_number<Backend> r = trunc(v, pol);
- if(fabs(r) > (std::numeric_limits<int>::max)())
+ if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !boost::math::isfinite(v))
       return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, v, 0, pol).template convert_to<int>();
    return r.template convert_to<int>();
 }
+template <class Backend>
+inline int itrunc(const mp_number<Backend>& v)
+{
+ return itrunc(v, boost::math::policies::policy<>());
+}
 template <class tag, class A1, class A2, class A3, class Policy>
 inline long ltrunc(const detail::mp_exp<tag, A1, A2, A3>& v, const Policy& pol)
 {
- typedef typename detail::mp_exp<tag, A1, A2, A3>::result_result number_type;
+ typedef typename detail::mp_exp<tag, A1, A2, A3>::result_type number_type;
    number_type r = trunc(v, pol);
- if(fabs(r) > (std::numeric_limits<long>::max)())
- return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, v, 0L, pol).template convert_to<long>();
+ if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !boost::math::isfinite(v))
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, number_type(v), 0L, pol).template convert_to<long>();
    return r.template convert_to<long>();
 }
+template <class tag, class A1, class A2, class A3>
+inline long ltrunc(const detail::mp_exp<tag, A1, A2, A3>& v)
+{
+ return ltrunc(v, boost::math::policies::policy<>());
+}
 template <class T, class Policy>
 inline long ltrunc(const mp_number<T>& v, const Policy& pol)
 {
    mp_number<T> r = trunc(v, pol);
- if(fabs(r) > (std::numeric_limits<long>::max)())
+ if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !boost::math::isfinite(v))
       return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, v, 0L, pol).template convert_to<long>();
    return r.template convert_to<long>();
 }
+template <class T>
+inline long ltrunc(const mp_number<T>& v)
+{
+ return ltrunc(v, boost::math::policies::policy<>());
+}
 #ifndef BOOST_NO_LONG_LONG
 template <class tag, class A1, class A2, class A3, class Policy>
 inline long long lltrunc(const detail::mp_exp<tag, A1, A2, A3>& v, const Policy& pol)
 {
- typedef typename detail::mp_exp<tag, A1, A2, A3>::result_result number_type;
+ typedef typename detail::mp_exp<tag, A1, A2, A3>::result_type number_type;
    number_type r = trunc(v, pol);
- if(fabs(r) > (std::numeric_limits<long long>::max)())
- return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, v, 0LL, pol).template convert_to<long long>();
+ if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !boost::math::isfinite(v))
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, number_type(v), 0LL, pol).template convert_to<long long>();
    return r.template convert_to<long long>();
 }
+template <class tag, class A1, class A2, class A3>
+inline long long lltrunc(const detail::mp_exp<tag, A1, A2, A3>& v)
+{
+ return lltrunc(v, boost::math::policies::policy<>());
+}
 template <class T, class Policy>
 inline long long lltrunc(const mp_number<T>& v, const Policy& pol)
 {
    mp_number<T> r = trunc(v, pol);
- if(fabs(r) > (std::numeric_limits<long long>::max)())
+ if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !boost::math::isfinite(v))
       return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, v, 0LL, pol).template convert_to<long long>();
    return r.template convert_to<long long>();
 }
+template <class T>
+inline long long lltrunc(const mp_number<T>& v)
+{
+ return lltrunc(v, boost::math::policies::policy<>());
+}
 #endif
 template <class tag, class A1, class A2, class A3, class Policy>
-inline typename detail::mp_exp<tag, A1, A2, A3>::result_result round(const detail::mp_exp<tag, A1, A2, A3>& v, const Policy& pol)
+inline typename detail::mp_exp<tag, A1, A2, A3>::result_type round(const detail::mp_exp<tag, A1, A2, A3>& v, const Policy& pol)
 {
- typedef typename detail::mp_exp<tag, A1, A2, A3>::result_result number_type;
+ typedef typename detail::mp_exp<tag, A1, A2, A3>::result_type number_type;
    return round(static_cast<number_type>(v), pol);
 }
 template <class T, class Policy>
@@ -610,55 +627,85 @@
 template <class tag, class A1, class A2, class A3, class Policy>
 inline int iround(const detail::mp_exp<tag, A1, A2, A3>& v, const Policy& pol)
 {
- typedef typename detail::mp_exp<tag, A1, A2, A3>::result_result number_type;
+ typedef typename detail::mp_exp<tag, A1, A2, A3>::result_type number_type;
    number_type r = round(v, pol);
- if(fabs(r) > (std::numeric_limits<int>::max)())
- return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0, pol).template convert_to<int>();
+ if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !boost::math::isfinite(v))
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0, pol).template convert_to<int>();
    return r.template convert_to<int>();
 }
+template <class tag, class A1, class A2, class A3>
+inline int iround(const detail::mp_exp<tag, A1, A2, A3>& v)
+{
+ return iround(v, boost::math::policies::policy<>());
+}
 template <class T, class Policy>
 inline int iround(const mp_number<T>& v, const Policy& pol)
 {
    mp_number<T> r = round(v, pol);
- if(fabs(r) > (std::numeric_limits<int>::max)())
+ if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !boost::math::isfinite(v))
       return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0, pol).template convert_to<int>();
    return r.template convert_to<int>();
 }
+template <class T>
+inline int iround(const mp_number<T>& v)
+{
+ return iround(v, boost::math::policies::policy<>());
+}
 template <class tag, class A1, class A2, class A3, class Policy>
 inline long lround(const detail::mp_exp<tag, A1, A2, A3>& v, const Policy& pol)
 {
- typedef typename detail::mp_exp<tag, A1, A2, A3>::result_result number_type;
+ typedef typename detail::mp_exp<tag, A1, A2, A3>::result_type number_type;
    number_type r = round(v, pol);
- if(fabs(r) > (std::numeric_limits<long>::max)())
- return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, v, 0L, pol).template convert_to<long>();
+ if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !boost::math::isfinite(v))
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, number_type(v), 0L, pol).template convert_to<long>();
    return r.template convert_to<long>();
 }
+template <class tag, class A1, class A2, class A3>
+inline long lround(const detail::mp_exp<tag, A1, A2, A3>& v)
+{
+ return lround(v, boost::math::policies::policy<>());
+}
 template <class T, class Policy>
 inline long lround(const mp_number<T>& v, const Policy& pol)
 {
    mp_number<T> r = round(v, pol);
- if(fabs(r) > (std::numeric_limits<long>::max)())
+ if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !boost::math::isfinite(v))
       return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, v, 0L, pol).template convert_to<long>();
    return r.template convert_to<long>();
 }
+template <class T>
+inline long lround(const mp_number<T>& v)
+{
+ return lround(v, boost::math::policies::policy<>());
+}
 #ifndef BOOST_NO_LONG_LONG
 template <class tag, class A1, class A2, class A3, class Policy>
 inline long long llround(const detail::mp_exp<tag, A1, A2, A3>& v, const Policy& pol)
 {
- typedef typename detail::mp_exp<tag, A1, A2, A3>::result_result number_type;
+ typedef typename detail::mp_exp<tag, A1, A2, A3>::result_type number_type;
    number_type r = round(v, pol);
- if(fabs(r) > (std::numeric_limits<long long>::max)())
- return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0LL, pol).template convert_to<long long>();
+ if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !boost::math::isfinite(v))
+ return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0LL, pol).template convert_to<long long>();
    return r.template convert_to<long long>();
 }
+template <class tag, class A1, class A2, class A3>
+inline long long llround(const detail::mp_exp<tag, A1, A2, A3>& v)
+{
+ return llround(v, boost::math::policies::policy<>());
+}
 template <class T, class Policy>
 inline long long llround(const mp_number<T>& v, const Policy& pol)
 {
    mp_number<T> r = round(v, pol);
- if(fabs(r) > (std::numeric_limits<long long>::max)())
+ if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !boost::math::isfinite(v))
       return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0LL, pol).template convert_to<long long>();
    return r.template convert_to<long long>();
 }
+template <class T>
+inline long long llround(const mp_number<T>& v)
+{
+ return llround(v, boost::math::policies::policy<>());
+}
 #endif
 
 #define UNARY_OP_FUNCTOR(func)\
@@ -917,8 +964,10 @@
 UNARY_OP_FUNCTOR(floor)
 UNARY_OP_FUNCTOR(ceil)
 UNARY_OP_FUNCTOR(trunc)
+UNARY_OP_FUNCTOR(round)
 UNARY_OP_FUNCTOR(exp)
 UNARY_OP_FUNCTOR(log)
+UNARY_OP_FUNCTOR(log10)
 UNARY_OP_FUNCTOR(cos)
 UNARY_OP_FUNCTOR(sin)
 UNARY_OP_FUNCTOR(tan)

Modified: sandbox/big_number/boost/multiprecision/detail/functions/pow.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/detail/functions/pow.hpp (original)
+++ sandbox/big_number/boost/multiprecision/detail/functions/pow.hpp 2011-11-09 12:37:40 EST (Wed, 09 Nov 2011)
@@ -385,6 +385,31 @@
    }while(lim.compare(t2) < 0);
 }
 
+template <class T>
+const T& get_constant_log10()
+{
+ static T result;
+ static bool b = false;
+ if(!b)
+ {
+ typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
+ T ten;
+ ten = ui_type(10u);
+ eval_log(result, ten);
+ }
+
+ constant_initializer<T, &get_constant_log10<T> >::do_nothing();
+
+ return result;
+}
+
+template <class T>
+void eval_log10(T& result, const T& arg)
+{
+ eval_log(result, arg);
+ divide(result, get_constant_log10<T>());
+}
+
 template<typename T>
 inline void eval_pow(T& result, const T& x, const T& a)
 {

Modified: sandbox/big_number/boost/multiprecision/gmp.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/gmp.hpp (original)
+++ sandbox/big_number/boost/multiprecision/gmp.hpp 2011-11-09 12:37:40 EST (Wed, 09 Nov 2011)
@@ -679,7 +679,10 @@
 
    if(!mpf_fits_slong_p(t.data()))
    {
- *result = (std::numeric_limits<long long>::max)();
+ if(get_sign(val) < 0)
+ *result = (std::numeric_limits<long long>::min)();
+ else
+ *result = (std::numeric_limits<long long>::max)();
       return;
    };
 

Modified: sandbox/big_number/boost/multiprecision/mp_float.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/mp_float.hpp (original)
+++ sandbox/big_number/boost/multiprecision/mp_float.hpp 2011-11-09 12:37:40 EST (Wed, 09 Nov 2011)
@@ -2583,10 +2583,15 @@
 template <unsigned Digits10>
 inline void eval_trunc(mp_float<Digits10>& result, const mp_float<Digits10>& x)
 {
- if(!x.isfinite() || x.isint())
+ if(!x.isfinite())
    {
+ result = boost::math::policies::raise_rounding_error("boost::multiprecision::trunc<%1%>(%1%)", 0, mp_number<mp_float<Digits10> >(x), 0, boost::math::policies::policy<>()).backend();
+ return;
+ }
+ else if(x.isint())
+ {
       result = x;
- return;
+ return;
    }
    result = x.extract_integer_part();
 }

Modified: sandbox/big_number/boost/multiprecision/mp_number.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/mp_number.hpp (original)
+++ sandbox/big_number/boost/multiprecision/mp_number.hpp 2011-11-09 12:37:40 EST (Wed, 09 Nov 2011)
@@ -1553,6 +1553,12 @@
    return is;
 }
 
+template <class Backend>
+inline void swap(mp_number<Backend>& a, mp_number<Backend>& b)
+{
+ a.swap(b);
+}
+
 }} // namespaces
 
 #endif

Modified: sandbox/big_number/boost/multiprecision/mpfr.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/mpfr.hpp (original)
+++ sandbox/big_number/boost/multiprecision/mpfr.hpp 2011-11-09 12:37:40 EST (Wed, 09 Nov 2011)
@@ -785,6 +785,12 @@
 template <unsigned Digits10>
 inline void eval_trunc(mpfr_float_backend<Digits10>& result, const mpfr_float_backend<Digits10>& val)
 {
+ int c = eval_fpclassify(val);
+ if(0 == mpfr_number_p(val.data()))
+ {
+ result = boost::math::policies::raise_rounding_error("boost::multiprecision::trunc<%1%>(%1%)", 0, mp_number<mpfr_float_backend<Digits10> >(val), 0, boost::math::policies::policy<>()).backend();
+ return;
+ }
    mpfr_trunc(result.data(), val.data());
 }
 template <unsigned Digits10>
@@ -849,6 +855,12 @@
 }
 
 template <unsigned Digits10>
+inline void eval_log10(mpfr_float_backend<Digits10>& result, const mpfr_float_backend<Digits10>& arg)
+{
+ mpfr_log10(result.data(), arg.data(), GMP_RNDN);
+}
+
+template <unsigned Digits10>
 inline void eval_sin(mpfr_float_backend<Digits10>& result, const mpfr_float_backend<Digits10>& arg)
 {
    mpfr_sin(result.data(), arg.data(), GMP_RNDN);
@@ -918,6 +930,16 @@
 
 namespace math{
 
+namespace tools{
+
+template <>
+inline int digits<boost::multiprecision::mpfr_float>()
+{
+ return boost::multiprecision::detail::get_default_precision();
+}
+
+}
+
 namespace lanczos{
 
 template<unsigned Digits10, class Policy>

Modified: sandbox/big_number/libs/multiprecision/doc/multiprecision.qbk
==============================================================================
--- sandbox/big_number/libs/multiprecision/doc/multiprecision.qbk (original)
+++ sandbox/big_number/libs/multiprecision/doc/multiprecision.qbk 2011-11-09 12:37:40 EST (Wed, 09 Nov 2011)
@@ -402,9 +402,21 @@
       mp_number();
       mp_number(see-below);
       mp_number& operator=(see-below);
+
       /* Other number-type operators here */
+
+ // Use in Boolean context:
+ operator ``['convertible-to-bool-type]``()const;
+ // swap:
+ void swap(mp_number& other);
+ // Sign:
+ bool is_zero()const;
+ int sign()const;
       // string conversion:
       std::string str()const;
+ // Generic conversion mechanism
+ template <class T>
+ T convert_to()const;
       // precision control:
       static unsigned default_precision();
       static void default_precision(unsigned digits10);
@@ -419,6 +431,10 @@
       const Backend& backend()const;
    };
 
+ // Swap:
+ template <class Backend>
+ void swap(mp_number<Backend>& a, mp_number<Backend>& b);
+
    // iostream support:
    template <class Backend>
    std::ostream& operator << (std::ostream& os, const mp_number<Backend>& r);
@@ -427,23 +443,31 @@
    std::istream& operator >> (std::istream& is, mp_number<Backend>& r);
 
    // Non-member function standard library support:
- ``['unmentionable-expression-template-type]`` abs (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` fabs (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` sqrt (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` floor (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` ceil (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` trunc (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` exp (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` log (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` cos (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` sin (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` tan (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` acos (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` asin (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` atan (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` cosh (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` sinh (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` tanh (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` abs (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` fabs (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` sqrt (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` floor (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` ceil (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` trunc (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` itrunc (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` ltrunc (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` lltrunc(const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` round (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` iround (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` lround (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` llround(const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` exp (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` log (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` log10 (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` cos (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` sin (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` tan (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` acos (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` asin (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` atan (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` cosh (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` sinh (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` tanh (const ``['mp_number-or-expression-template-type]``&);
 
    ``['unmentionable-expression-template-type]`` ldexp (const ``['mp_number-or-expression-template-type]``&, int);
    ``['unmentionable-expression-template-type]`` frexp (const ``['mp_number-or-expression-template-type]``&, int*);
@@ -453,6 +477,17 @@
 
    }} // namespaces
 
+ namespace boost{ namespace math{
+
+ // Boost.Math interoperability functions:
+ int fpclassify (const ``['mp_number-or-expression-template-type]``&, int);
+ bool isfinite (const ``['mp_number-or-expression-template-type]``&, int);
+ bool isnan (const ``['mp_number-or-expression-template-type]``&, int);
+ bool isinf (const ``['mp_number-or-expression-template-type]``&, int);
+ bool isnormal (const ``['mp_number-or-expression-template-type]``&, int);
+
+ }} // namespaces
+
    // numeric_limits support:
    namespace std{
 
@@ -497,11 +532,37 @@
 
 Note that type `mp_number` (and all expression templates derived from it) may be used in a Boolian context.
 
+ operator ``['convertible-to-bool-type]``()const;
+
+Returns an ['unmentionable-type] that is usable in Boolean contexts (this allows `mp_number` to be used in any
+Boolean context - if statements, conditional statements, or as an argument to a logical operator - without
+type `mp_number` being convertible to type `bool`.
+
+ void swap(mp_number& other);
+
+Swaps `*this` with `other`.
+
+ bool is_zero()const;
+
+Returns `true` is `*this` is zero, otherwise `false`.
+
+ int sign()const;
+
+Returns a value less than zero if `*this` is negative, a value greater than zero if `*this is positive, and zero
+if `*this` is zero.
+
       std::string str(unsigned precision, bool scientific = true)const;
 
 Returns the number formatted as a string, with at least /precision/ digits, and in scientific format
 if /scientific/ is true.
 
+ template <class T>
+ T convert_to()const;
+
+Provides a generic conversion mechanism to convert `*this` to type `T`. Type `T` may be any arithmetic type.
+Optionally other types may also be supported by specific `Backend` types.
+
+
       static unsigned default_precision();
       static void default_precision(unsigned digits10);
       unsigned precision()const;
@@ -525,6 +586,13 @@
 
 Returns the underlying backend instance used by *this.
 
+[h4 swap]
+
+ template <class Backend>
+ void swap(mp_number<Backend>& a, mp_number<Backend>& b);
+
+Swaps `a` and `b`.
+
 [h4 Iostream Support]
 
    template <class Backend>
@@ -538,23 +606,31 @@
 
 [h4 Non-member standard library function support]
 
- ``['unmentionable-expression-template-type]`` abs (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` fabs (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` sqrt (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` floor (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` ceil (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` trunc (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` exp (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` log (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` cos (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` sin (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` tan (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` acos (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` asin (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` atan (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` cosh (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` sinh (const ``['mp_number-or-expression-template-type]``&);
- ``['unmentionable-expression-template-type]`` tanh (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` abs (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` fabs (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` sqrt (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` floor (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` ceil (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` trunc (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` itrunc (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` ltrunc (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` lltrunc(const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` round (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` iround (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` lround (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` llround(const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` exp (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` log (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` log10 (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` cos (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` sin (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` tan (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` acos (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` asin (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` atan (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` cosh (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` sinh (const ``['mp_number-or-expression-template-type]``&);
+ ``['unmentionable-expression-template-type]`` tanh (const ``['mp_number-or-expression-template-type]``&);
 
    ``['unmentionable-expression-template-type]`` ldexp (const ``['mp_number-or-expression-template-type]``&, int);
    ``['unmentionable-expression-template-type]`` frexp (const ``['mp_number-or-expression-template-type]``&, int*);
@@ -572,6 +648,21 @@
 
 Also note that with the exception of `abs` that these functions can only be used with floating point Backend types.
 
+[h4 Boost.Math Interoperabilty Support]
+
+ namespace boost{ namespace math{
+
+ int fpclassify (const ``['mp_number-or-expression-template-type]``&, int);
+ bool isfinite (const ``['mp_number-or-expression-template-type]``&, int);
+ bool isnan (const ``['mp_number-or-expression-template-type]``&, int);
+ bool isinf (const ``['mp_number-or-expression-template-type]``&, int);
+ bool isnormal (const ``['mp_number-or-expression-template-type]``&, int);
+
+ }} // namespaces
+
+These functions behave exacts as their Boost.Math equivalents. Other Boost.Math functions and templates may also be
+specialized or overloaded to ensure interoperability.
+
 [h4 std::numeric_limits support]
 
    namespace std{
@@ -592,7 +683,149 @@
 
 [section:backendconc Backend Requirements]
 
-TODO, big boring job!!
+[template super[x]'''<superscript>'''[x]'''</superscript>''']
+
+The requirements on the `Backend` template argument to `mp_number` are split up into
+compulsary requirements, and optional requirements that are either to improve performance
+or provide optional features.
+
+In the following tables, type B is the `Backend` template arument to `mp_number`, `b` is
+a variable of B, `cb` and `cb2` are constant variables of type B, `a` is a variable of Arithmetic type,
+`s` is a variable of type `const char*`, `ui` is a variable of type `unsigned`, `bb` is a variable of type `bool`,
+`pa` is a variable of type pointer-to-arithmetc-type, `exp` is a variable of type `B::exp_type`,
+`pexp` is a variable of type `B::exp_type*`.
+
+[table Compulsary Requirements on the Backend type.
+[[Expression][Return Type][Comments]]
+[[`B::signed_types`][`mpl::list<type-list>`][A list of signed integral types that can be assigned to type B. The types shall be
+ listed in order of size, smallest first, and shall terminate in the type that is `std::intmax_t`.]]
+[[`B::unsigned_types`][`mpl::list<type-list>`][A list of unsigned integral types that can be assigned to type B. The types shall be
+ listed in order of size, smallest first, and shall terminate in the type that is `std::uintmax_t`.]]
+[[`B::real_types`][`mpl::list<type-list>`][A list of floating point types that can be assigned to type B.The types shall be
+ listed in order of size, smallest first, and shall terminate in type `long double`.]]
+[[`B::exponent_type`][A signed integral type.][The type of the exponent of type B.]]
+[[`B()`][ ][Default constructor.]]
+[[`B(cb)`][ ][Copy Constructor.]]
+[[`b = b`][`B&`][Assignment operator.]]
+[[`b = a`][`B&`][Assignment from an Arithmetic type. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`b = s`][`B&`][Assignment from a string.]]
+[[`b.swap(b)`][`void`][Swaps the contents of it's arguments.]]
+[[`cb.str(ui, bb)`][`std::string`][Returns the string representation of `b` with `ui` digits and in scientific format if `bb` is `true`.
+ If `ui` is zero, then returns as many digits as are required to reconstruct the original value.]]
+[[`b.negate()`][`void`][Negates `b`.]]
+[[`cb.compare(cb2)`][`int`][Compares `cb` and `cb2`, returns a value less than zero if `cb < cb2`, a value greater than zero if `cb > cb2` and zero
+ if `cb == cb2`.]]
+[[`cb.compare(a)`][`int`][Compares `cb` and `a`, returns a value less than zero if `cb < a`, a value greater than zero if `cb > a` and zero
+ if `cb == a`. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`add(b, cb)`][`void`][Adds `cb` to `b`.]]
+[[`subtract(b, cb)`][`void`][Subtracts `cb` from `b`.]]
+[[`multiply(b, cb)`][`void`][Multiplies `b` by `cb`.]]
+[[`divide(b, cb)`][`void`][Divides `b` by `cb`.]]
+[[`modulus(b, cb)`][`void`][Computes `b %= cb`, only required when `B` is an integer type.]]
+[[`bitwise_and(b, cb)`][`void`][Computes `b &= cb`, only required when `B` is an integer type.]]
+[[`bitwise_or(b, cb)`][`void`][Computes `b |= cb`, only required when `B` is an integer type.]]
+[[`bitwise_xor(b, cb)`][`void`][Computes `b ^= cb`, only required when `B` is an integer type.]]
+[[`complement(b, cb)`][`void`][Computes the ones-complement of `cb` and stores the result in `b`, only required when `B` is an integer type.]]
+[[`left_shift(b, ui)`][`void`][Computes `b <<= ui`, only required when `B` is an integer type.]]
+[[`right_shift(b, ui)`][`void`][Computes `b >>= ui`, only required when `B` is an integer type.]]
+[[`convert_to(pa, cb)`][`void`][Converts `cb` to the type of `*pa` and store the result in `*pa`. Type `B` shall support
+ conversion to at least types `std::intmax_t`, `std::uintmax_t` and `long long`.
+ Conversion to other arithmetic types can then be synthesised using other operations.
+ Conversions to other types are entirely optional.]]
+[[`eval_frexp(b, cb, pexp)`][`void`][Stores values in `b` and `*pexp` such that the value of `cb` is b * 2[super *pexp], only required when `B` is a floating point type.]]
+[[`eval_ldexp(b, cb, exp)`][`void`][Stores a value in `b` that is cb * 2[super exp], only required when `B` is a floating point type.]]
+[[`eval_floor(b, cb)`][`void`][Stores the floor of `cb` in `b`, only required when `B` is a floating point type.]]
+[[`eval_ceil(b, cb)`][`void`][Stores the ceiling of `cb` in `b`, only required when `B` is a floating point type.]]
+[[`eval_sqrt(b, cb)`][`void`][Stores the square root of `cb` in `b`, only required when `B` is a floating point type.]]
+]
+
+[table Optional Requirements on the Backend Type
+[[Expression][Returns][Comments]]
+[[`add(b, a)`][`void`][Adds `a` to `b`. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`subtract(b, a)`][`void`][Subtracts `a` from `b`. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`multiply(b, a)`][`void`][Multiplies `b` by `a`. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`divide(b, a)`][`void`][Divides `b` by `a`. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`modulus(b, a)`][`void`][Computes `b %= cb`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`bitwise_and(b, a)`][`void`][Computes `b &= cb`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`bitwise_or(b, a)`][`void`][Computes `b |= cb`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`bitwise_xor(b, a)`][`void`][Computes `b ^= cb`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`add(b, cb, cb2)`][`void`][Add `cb` to `cb2` and stores the result in `b`.]]
+[[`subtract(b, cb, cb2)`][`void`][Subtracts `cb2` from `cb` and stores the result in `b`.]]
+[[`multiply(b, cb, cb2)`][`void`][Multiplies `cb` by `cb2` and stores the result in `b`.]]
+[[`divide(b, cb, cb2)`][`void`][Divides `cb` by `cb2` and stores the result in `b`.]]
+[[`add(b, cb, a)`][`void`][Add `cb` to `a` and stores the result in `b`. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`subtract(b, cb, a)`][`void`][Subtracts `a` from `cb` and stores the result in `b`. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`multiply(b, cb, a)`][`void`][Multiplies `cb` by `a` and stores the result in `b`. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`divide(b, cb, a)`][`void`][Divides `cb` by `a` and stores the result in `b`. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`modulus(b, cb, cb2)`][`void`][Computes `cb % cb2` and stores the result in `b`, only required when `B` is an integer type.]]
+[[`bitwise_and(b, cb, cb2)`][`void`][Computes `cb & cb2` and stores the result in `b`, only required when `B` is an integer type.]]
+[[`bitwise_or(b, cb, cb2)`][`void`][Computes `cb | cb2` and stores the result in `b`, only required when `B` is an integer type.]]
+[[`bitwise_xor(b, cb, cb2)`][`void`][Computes `cb ^ cb2` and stores the result in `b`, only required when `B` is an integer type.]]
+[[`add(b, a, cb)`][`void`][Add `a` to `cb` and stores the result in `b`. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`subtract(b, a, cb)`][`void`][Subtracts `cb` from `a` and stores the result in `b`. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`multiply(b, a, cb)`][`void`][Multiplies `a` by `cb` and stores the result in `b`. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`divide(b, a, cb)`][`void`][Divides `a` by `cb` and stores the result in `b`. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`modulus(b, cb, a)`][`void`][Computes `cb % a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`bitwise_and(b, cb, a)`][`void`][Computes `cb & a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`bitwise_or(b, cb, a)`][`void`][Computes `cb | a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`bitwise_xor(b, cb, a)`][`void`][Computes `cb ^ a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`modulus(b, a, cb)`][`void`][Computes `cb % a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`bitwise_and(b, a, cb)`][`void`][Computes `cb & a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`bitwise_or(b, a, cb)`][`void`][Computes `cb | a` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`bitwise_xor(b, a, cb)`][`void`][Computes `a ^ cb` and stores the result in `b`, only required when `B` is an integer type. The type of `a` shall be listed in one of the type lists
+ `B::signed_types`, `B::unsigned_types` or `B::real_types`.]]
+[[`left_shift(b, cb, ui)`][`void`][Computes `cb << ui` and stores the result in `b`, only required when `B` is an integer type.]]
+[[`right_shift(b, cb, ui)`][`void`][Computes `cb >> ui` and stores the result in `b`, only required when `B` is an integer type.]]
+[[`increment(b)`][void][Increments the value of `b` by one.]]
+[[`decrement(b)`][void][Decrements the value of `b` by one.]]
+[[`is_zero(cb)`][`bool`][Returns `true` if `cb` is zero, otherwise `false`]]
+[[`get_sign(cb)`][`int`][Returns a value < zero if `cb` is negative, a value > zero if `cb` is positive, and zero if `cb` is zero.]]
+[[`eval_abs(b, cb)`][`void`][Set `b` to the absolute value of `cb`.]]
+[[`eval_fabs(b, cb)`][`void`][Set `b` to the absolute value of `cb`.]]
+[[`eval_fpclassify(cb)`][`int`][Returns one of the same values returned by `std::fpclassify`. Only required when `B` is an floating point type.]]
+[[`eval_trunc(b, cb)`][`void`][Performs the equivalent operation to `std::trunc` on argument `cb` and stores the result in `b`. Only required when `B` is an floating point type.]]
+[[`eval_round(b, cb, cb2)`][`void`][Performs the equivalent operation to `std::round` on argument `cb` and stores the result in `b`. Only required when `B` is an floating point type.]]
+[[`eval_exp(b, cb)`][`void`][Performs the equivalent operation to `std::exp` on argument `cb` and stores the result in `b`. Only required when `B` is an floating point type.]]
+[[`eval_log(b, cb)`][`void`][Performs the equivalent operation to `std::log` on argument `cb` and stores the result in `b`. Only required when `B` is an floating point type.]]
+[[`eval_log10(b, cb)`][`void`][Performs the equivalent operation to `std::log10` on argument `cb` and stores the result in `b`. Only required when `B` is an floating point type.]]
+[[`eval_sin(b, cb)`][`void`][Performs the equivalent operation to `std::sin` on argument `cb` and stores the result in `b`. Only required when `B` is an floating point type.]]
+[[`eval_cos(b, cb)`][`void`][Performs the equivalent operation to `std::cos` on argument `cb` and stores the result in `b`. Only required when `B` is an floating point type.]]
+[[`eval_tan(b, cb)`][`void`][Performs the equivalent operation to `std::exp` on argument `cb` and stores the result in `b`. Only required when `B` is an floating point type.]]
+[[`eval_asin(b, cb)`][`void`][Performs the equivalent operation to `std::asin` on argument `cb` and stores the result in `b`. Only required when `B` is an floating point type.]]
+[[`eval_acos(b, cb)`][`void`][Performs the equivalent operation to `std::acos` on argument `cb` and stores the result in `b`. Only required when `B` is an floating point type.]]
+[[`eval_atan(b, cb)`][`void`][Performs the equivalent operation to `std::atan` on argument `cb` and stores the result in `b`. Only required when `B` is an floating point type.]]
+[[`eval_sinh(b, cb)`][`void`][Performs the equivalent operation to `std::sinh` on argument `cb` and stores the result in `b`. Only required when `B` is an floating point type.]]
+[[`eval_cosh(b, cb)`][`void`][Performs the equivalent operation to `std::cosh` on argument `cb` and stores the result in `b`. Only required when `B` is an floating point type.]]
+[[`eval_tanh(b, cb)`][`void`][Performs the equivalent operation to `std::tanh` on argument `cb` and stores the result in `b`. Only required when `B` is an floating point type.]]
+[[`eval_fmod(b, cb, cb2)`][`void`][Performs the equivalent operation to `std::fmod` on arguments `cb` and `cb2`, and store the result in `b`. Only required when `B` is an floating point type.]]
+[[`eval_pow(b, cb, cb2)`][`void`][Performs the equivalent operation to `std::pow` on arguments `cb` and `cb2`, and store the result in `b`. Only required when `B` is an floating point type.]]
+[[`eval_atan2(b, cb, cb2)`][`void`][Performs the equivalent operation to `std::atan` on arguments `cb` and `cb2`, and store the result in `b`. Only required when `B` is an floating point type.]]
+]
 
 [endsect]
 

Modified: sandbox/big_number/libs/multiprecision/test/Jamfile.v2
==============================================================================
--- sandbox/big_number/libs/multiprecision/test/Jamfile.v2 (original)
+++ sandbox/big_number/libs/multiprecision/test/Jamfile.v2 2011-11-09 12:37:40 EST (Wed, 09 Nov 2011)
@@ -490,3 +490,35 @@
          [ check-target-builds ../config//has_mpfr : : <build>no ] ;
 
 run ../example/mp_float_snips.cpp ;
+
+run test_round.cpp
+ : # command line
+ : # input files
+ : # requirements
+ <define>TEST_BACKEND
+ : test_round_backend_concept ;
+
+run test_round.cpp gmp
+ : # command line
+ : # input files
+ : # requirements
+ <define>TEST_MPF_50
+ [ check-target-builds ../config//has_gmp : : <build>no ]
+ : test_round_mpf50 ;
+
+run test_round.cpp mpfr
+ : # command line
+ : # input files
+ : # requirements
+ <define>TEST_MPFR_50
+ [ check-target-builds ../config//has_mpfr : : <build>no ]
+ : test_round_mpfr_50 ;
+
+run test_round.cpp
+ : # command line
+ : # input files
+ : # requirements
+ <define>TEST_MP_FLOAT
+ [ check-target-builds ../config//has_mpfr : : <build>no ]
+ : test_round_mp_float ;
+

Modified: sandbox/big_number/libs/multiprecision/test/test_log.cpp
==============================================================================
--- sandbox/big_number/libs/multiprecision/test/test_log.cpp (original)
+++ sandbox/big_number/libs/multiprecision/test/test_log.cpp 2011-11-09 12:37:40 EST (Wed, 09 Nov 2011)
@@ -151,6 +151,7 @@
    T pi = "3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609";
    T tenth = 1;
    tenth /= 10;
+ T logten = log(T(10));
 
    unsigned max_err = 0;
    for(unsigned k = 0; k < data.size(); k++)
@@ -166,6 +167,18 @@
       err = e.template convert_to<unsigned>();
       if(err > max_err)
          max_err = err;
+
+ val = boost::multiprecision::log10(tenth + pi * (100 * k) * (100 * k));
+ e = relative_error(val, T(data[k] / logten));
+ err = e.template convert_to<unsigned>();
+ if(err > max_err)
+ max_err = err;
+
+ val = boost::multiprecision::log10(1 / (tenth + pi * (100 * k) * (100 * k)));
+ e = relative_error(val, T(-data[k] / logten));
+ err = e.template convert_to<unsigned>();
+ if(err > max_err)
+ max_err = err;
    }
    std::cout << "Max error was: " << max_err << std::endl;
    BOOST_TEST(max_err < 10);

Added: sandbox/big_number/libs/multiprecision/test/test_round.cpp
==============================================================================
--- (empty file)
+++ sandbox/big_number/libs/multiprecision/test/test_round.cpp 2011-11-09 12:37:40 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,404 @@
+// (C) Copyright John Maddock 2007.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+#include <boost/math/special_functions/round.hpp>
+#include <boost/math/special_functions/trunc.hpp>
+#include <boost/math/special_functions/modf.hpp>
+#include <boost/math/special_functions/sign.hpp>
+#include <boost/random/mersenne_twister.hpp>
+
+#define BOOST_CHECK_THROW(x, EX)\
+ try { x; BOOST_ERROR("Expected exception not thrown"); } \
+ catch(const EX&){}\
+ catch(...){ BOOST_ERROR("Incorrect exception type thrown"); }
+
+
+#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_MP_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ)
+# define TEST_MPF_50
+# define TEST_MPFR_50
+# define TEST_BACKEND
+# define TEST_MP_FLOAT
+
+#ifdef _MSC_VER
+#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!")
+#endif
+#ifdef __GNUC__
+#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!"
+#endif
+
+#endif
+
+#if defined(TEST_MPF_50)
+#include <boost/multiprecision/gmp.hpp>
+#endif
+#ifdef TEST_MPFR_50
+#include <boost/multiprecision/mpfr.hpp>
+#endif
+#ifdef TEST_BACKEND
+#include <boost/multiprecision/concepts/mp_number_architypes.hpp>
+#endif
+#ifdef TEST_MP_FLOAT
+#include <boost/multiprecision/mp_float.hpp>
+#endif
+
+boost::mt19937 rng;
+
+template <class T>
+T get_random()
+{
+ //
+ // Fill all the bits in T with random values,
+ // likewise set the exponent to a random value
+ // that will still fit inside a T, and always
+ // have a remainder as well as an integer part.
+ //
+ int bits = boost::math::tools::digits<T>();
+ int shift = 0;
+ int exponent = rng() % (bits - 4);
+ T result = 0;
+ while(bits > 0)
+ {
+ result += ldexp(static_cast<T>(rng()), shift);
+ shift += std::numeric_limits<int>::digits;
+ bits -= std::numeric_limits<int>::digits;
+ }
+ return rng() & 1u ? -ldexp(frexp(result, &bits), exponent) : ldexp(frexp(result, &bits), exponent);
+}
+
+template <class T, class U>
+void check_within_half(T a, U u)
+{
+ BOOST_MATH_STD_USING
+ if(fabs(a-u) > 0.5f)
+ {
+ BOOST_ERROR("Rounded result differed by more than 0.5 from the original");
+ std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
+ << std::left << a << u << std::endl;
+ }
+ if((fabs(a - u) == 0.5f) && (fabs(static_cast<T>(u)) < fabs(a)))
+ {
+ BOOST_ERROR("Rounded result was towards zero with boost::round");
+ std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
+ << std::left << a << u << std::endl;
+ }
+}
+
+//
+// We may not have an abs overload for long long so provide a fall back:
+//
+template <class T>
+inline T safe_abs(T const& v ...)
+{
+ return v < 0 ? -v : v;
+}
+
+template <class T, class U>
+void check_trunc_result(T a, U u)
+{
+ BOOST_MATH_STD_USING
+ if(fabs(a-u) >= 1)
+ {
+ BOOST_ERROR("Rounded result differed by more than 1 from the original");
+ std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
+ << std::left << a << u << std::endl;
+ }
+ if(abs(a) < safe_abs(u))
+ {
+ BOOST_ERROR("Truncated result had larger absolute value than the original");
+ std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
+ << std::left << a << u << std::endl;
+ }
+ if(fabs(static_cast<T>(u)) > fabs(a))
+ {
+ BOOST_ERROR("Rounded result was away from zero with boost::trunc");
+ std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
+ << std::left << a << u << std::endl;
+ }
+}
+
+template <class T, class U>
+void check_modf_result(T a, T fract, U ipart)
+{
+ BOOST_MATH_STD_USING
+ if(fract + ipart != a)
+ {
+ BOOST_ERROR("Fractional and integer results do not add up to the original value");
+ std::cerr << "Values were: " << std::setprecision(35) << " "
+ << std::left << a << ipart << " " << fract << std::endl;
+ }
+ if((boost::math::sign(a) != boost::math::sign(fract)) && boost::math::sign(fract))
+ {
+ BOOST_ERROR("Original and fractional parts have differing signs");
+ std::cerr << "Values were: " << std::setprecision(35) << " "
+ << std::left << a << ipart << " " << fract << std::endl;
+ }
+ if((boost::math::sign(a) != boost::math::sign(ipart)) && boost::math::sign(ipart))
+ {
+ BOOST_ERROR("Original and integer parts have differing signs");
+ std::cerr << "Values were: " << std::setprecision(35) << " "
+ << std::left << a << ipart << " " << ipart << std::endl;
+ }
+ if(fabs(a-ipart) >= 1)
+ {
+ BOOST_ERROR("Rounded result differed by more than 1 from the original");
+ std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
+ << std::left << a << ipart << std::endl;
+ }
+}
+
+template <class T>
+void test()
+{
+ BOOST_MATH_STD_USING
+
+ for(int i = 0; i < 1000; ++i)
+ {
+ T arg = get_random<T>();
+ T r = round(arg);
+ check_within_half(arg, r);
+ BOOST_TEST(r == round(arg + 0));
+ r = trunc(arg);
+ check_trunc_result(arg, r);
+ BOOST_TEST(r == trunc(arg + 0));
+ T frac = modf(arg, &r);
+ check_modf_result(arg, frac, r);
+
+ if(abs(r) < (std::numeric_limits<int>::max)())
+ {
+ int i = iround(arg);
+ check_within_half(arg, i);
+ BOOST_TEST(i == iround(arg + 0));
+ i = itrunc(arg);
+ check_trunc_result(arg, i);
+ BOOST_TEST(i == itrunc(arg + 0));
+ r = modf(arg, &i);
+ check_modf_result(arg, r, i);
+ }
+ if(abs(r) < (std::numeric_limits<long>::max)())
+ {
+ long l = lround(arg);
+ check_within_half(arg, l);
+ BOOST_TEST(l == lround(arg + 0));
+ l = ltrunc(arg);
+ check_trunc_result(arg, l);
+ BOOST_TEST(l == ltrunc(arg + 0));
+ r = modf(arg, &l);
+ check_modf_result(arg, r, l);
+ }
+
+#ifdef BOOST_HAS_LONG_LONG
+ if(abs(r) < (std::numeric_limits<boost::long_long_type>::max)())
+ {
+ boost::long_long_type ll = llround(arg);
+ check_within_half(arg, ll);
+ BOOST_TEST(ll == llround(arg + 0));
+ ll = lltrunc(arg);
+ check_trunc_result(arg, ll);
+ BOOST_TEST(ll == lltrunc(arg + 0));
+ r = modf(arg, &ll);
+ check_modf_result(arg, r, ll);
+ }
+#endif
+ }
+ //
+ // Test boundary cases:
+ //
+ if(std::numeric_limits<T>::digits >= std::numeric_limits<int>::digits)
+ {
+ int si = iround(static_cast<T>((std::numeric_limits<int>::max)()));
+ check_within_half(static_cast<T>((std::numeric_limits<int>::max)()), si);
+ BOOST_TEST(si == iround(static_cast<T>((std::numeric_limits<int>::max)()) + 0));
+ si = iround(static_cast<T>((std::numeric_limits<int>::min)()));
+ check_within_half(static_cast<T>((std::numeric_limits<int>::min)()), si);
+ BOOST_TEST(si == iround(static_cast<T>((std::numeric_limits<int>::min)()) + 0));
+ si = itrunc(static_cast<T>((std::numeric_limits<int>::max)()));
+ check_trunc_result(static_cast<T>((std::numeric_limits<int>::max)()), si);
+ BOOST_TEST(si == itrunc(static_cast<T>((std::numeric_limits<int>::max)()) + 0));
+ si = itrunc(static_cast<T>((std::numeric_limits<int>::min)()));
+ check_trunc_result(static_cast<T>((std::numeric_limits<int>::min)()), si);
+ BOOST_TEST(si == itrunc(static_cast<T>((std::numeric_limits<int>::min)()) + 0));
+
+ si = iround(static_cast<T>((std::numeric_limits<int>::max)() - 1));
+ check_within_half(static_cast<T>((std::numeric_limits<int>::max)() - 1), si);
+ si = iround(static_cast<T>((std::numeric_limits<int>::min)() + 1));
+ check_within_half(static_cast<T>((std::numeric_limits<int>::min)() + 1), si);
+ si = itrunc(static_cast<T>((std::numeric_limits<int>::max)() - 1));
+ check_trunc_result(static_cast<T>((std::numeric_limits<int>::max)() - 1), si);
+ si = itrunc(static_cast<T>((std::numeric_limits<int>::min)() + 1));
+ check_trunc_result(static_cast<T>((std::numeric_limits<int>::min)() + 1), si);
+ }
+ if(std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits)
+ {
+ long k = lround(static_cast<T>((std::numeric_limits<long>::max)()));
+ check_within_half(static_cast<T>((std::numeric_limits<long>::max)()), k);
+ BOOST_TEST(k == lround(static_cast<T>((std::numeric_limits<long>::max)()) + 0));
+ k = lround(static_cast<T>((std::numeric_limits<long>::min)()));
+ check_within_half(static_cast<T>((std::numeric_limits<long>::min)()), k);
+ BOOST_TEST(k == lround(static_cast<T>((std::numeric_limits<long>::min)()) + 0));
+ k = ltrunc(static_cast<T>((std::numeric_limits<long>::max)()));
+ check_trunc_result(static_cast<T>((std::numeric_limits<long>::max)()), k);
+ BOOST_TEST(k == ltrunc(static_cast<T>((std::numeric_limits<long>::max)()) + 0));
+ k = ltrunc(static_cast<T>((std::numeric_limits<long>::min)()));
+ check_trunc_result(static_cast<T>((std::numeric_limits<long>::min)()), k);
+ BOOST_TEST(k == ltrunc(static_cast<T>((std::numeric_limits<long>::min)()) + 0));
+
+ k = lround(static_cast<T>((std::numeric_limits<long>::max)() - 1));
+ check_within_half(static_cast<T>((std::numeric_limits<long>::max)() - 1), k);
+ k = lround(static_cast<T>((std::numeric_limits<long>::min)() + 1));
+ check_within_half(static_cast<T>((std::numeric_limits<long>::min)() + 1), k);
+ k = ltrunc(static_cast<T>((std::numeric_limits<long>::max)() - 1));
+ check_trunc_result(static_cast<T>((std::numeric_limits<long>::max)() - 1), k);
+ k = ltrunc(static_cast<T>((std::numeric_limits<long>::min)() + 1));
+ check_trunc_result(static_cast<T>((std::numeric_limits<long>::min)() + 1), k);
+ }
+#ifndef BOOST_NO_LONG_LONG
+ if(std::numeric_limits<T>::digits >= std::numeric_limits<boost::long_long_type>::digits)
+ {
+ boost::long_long_type j = llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()));
+ check_within_half(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()), j);
+ BOOST_TEST(j == llround(static_cast<T>((std::numeric_limits<long long>::max)()) + 0));
+ j = llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()));
+ check_within_half(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()), j);
+ BOOST_TEST(j == llround(static_cast<T>((std::numeric_limits<long long>::min)()) + 0));
+ j = lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()));
+ check_trunc_result(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()), j);
+ BOOST_TEST(j == lltrunc(static_cast<T>((std::numeric_limits<long long>::max)()) + 0));
+ j = lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()));
+ check_trunc_result(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()), j);
+ BOOST_TEST(j == lltrunc(static_cast<T>((std::numeric_limits<long long>::min)()) + 0));
+
+ j = llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)() - 1));
+ check_within_half(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)() - 1), j);
+ j = llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)() + 1));
+ check_within_half(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)() + 1), j);
+ j = lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)() - 1));
+ check_trunc_result(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)() - 1), j);
+ j = lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)() + 1));
+ check_trunc_result(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)() + 1), j);
+ }
+#endif
+ //
+ // Finish off by testing the error handlers:
+ //
+ BOOST_CHECK_THROW(static_cast<T>(iround(static_cast<T>(1e20))), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(iround(static_cast<T>(-1e20))), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(lround(static_cast<T>(1e20))), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(lround(static_cast<T>(-1e20))), boost::math::rounding_error);
+#ifdef BOOST_HAS_LONG_LONG
+ BOOST_CHECK_THROW(static_cast<T>(llround(static_cast<T>(1e20))), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(llround(static_cast<T>(-1e20))), boost::math::rounding_error);
+#endif
+ if(std::numeric_limits<T>::has_infinity)
+ {
+ BOOST_CHECK_THROW(static_cast<T>(round(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(iround(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(iround(-std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(lround(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(lround(-std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+ #ifdef BOOST_HAS_LONG_LONG
+ BOOST_CHECK_THROW(static_cast<T>(llround(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(llround(-std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+ #endif
+ }
+ if(std::numeric_limits<T>::has_quiet_NaN)
+ {
+ BOOST_CHECK_THROW(static_cast<T>(round(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(iround(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(lround(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
+ #ifdef BOOST_HAS_LONG_LONG
+ BOOST_CHECK_THROW(static_cast<T>(llround(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
+ #endif
+ }
+ BOOST_CHECK_THROW(static_cast<T>(itrunc(static_cast<T>(1e20))), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(itrunc(static_cast<T>(-1e20))), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(ltrunc(static_cast<T>(1e20))), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(ltrunc(static_cast<T>(-1e20))), boost::math::rounding_error);
+#ifdef BOOST_HAS_LONG_LONG
+ BOOST_CHECK_THROW(static_cast<T>(lltrunc(static_cast<T>(1e20))), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(lltrunc(static_cast<T>(-1e20))), boost::math::rounding_error);
+#endif
+ if(std::numeric_limits<T>::has_infinity)
+ {
+ BOOST_CHECK_THROW(static_cast<T>(trunc(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(itrunc(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(itrunc(-std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(ltrunc(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(ltrunc(-std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+ #ifdef BOOST_HAS_LONG_LONG
+ BOOST_CHECK_THROW(static_cast<T>(lltrunc(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(lltrunc(-std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+ #endif
+ }
+ if(std::numeric_limits<T>::has_quiet_NaN)
+ {
+ BOOST_CHECK_THROW(static_cast<T>(trunc(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(itrunc(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(ltrunc(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
+ #ifdef BOOST_HAS_LONG_LONG
+ BOOST_CHECK_THROW(static_cast<T>(lltrunc(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
+ #endif
+ }
+ if(std::numeric_limits<T>::digits >= std::numeric_limits<int>::digits)
+ {
+ BOOST_CHECK_THROW(static_cast<T>(itrunc(static_cast<T>((std::numeric_limits<int>::max)()) + 1)), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(itrunc(static_cast<T>((std::numeric_limits<int>::min)()) - 1)), boost::math::rounding_error);
+ }
+ if(std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits)
+ {
+ BOOST_CHECK_THROW(static_cast<T>(ltrunc(static_cast<T>((std::numeric_limits<long>::max)()) + 1)), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(ltrunc(static_cast<T>((std::numeric_limits<long>::min)()) - 1)), boost::math::rounding_error);
+ }
+#ifndef BOOST_NO_LONG_LONG
+ if(std::numeric_limits<T>::digits >= std::numeric_limits<boost::long_long_type>::digits)
+ {
+ BOOST_CHECK_THROW(static_cast<T>(lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()) + 1)), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()) - 1)), boost::math::rounding_error);
+ }
+#endif
+ if(std::numeric_limits<T>::digits >= std::numeric_limits<int>::digits)
+ {
+ BOOST_CHECK_THROW(static_cast<T>(iround(static_cast<T>((std::numeric_limits<int>::max)()) + 1)), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(iround(static_cast<T>((std::numeric_limits<int>::min)()) - 1)), boost::math::rounding_error);
+ }
+ if(std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits)
+ {
+ BOOST_CHECK_THROW(static_cast<T>(lround(static_cast<T>((std::numeric_limits<long>::max)()) + 1)), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(lround(static_cast<T>((std::numeric_limits<long>::min)()) - 1)), boost::math::rounding_error);
+ }
+#ifndef BOOST_NO_LONG_LONG
+ if(std::numeric_limits<T>::digits >= std::numeric_limits<boost::long_long_type>::digits)
+ {
+ BOOST_CHECK_THROW(static_cast<T>(llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()) + 1)), boost::math::rounding_error);
+ BOOST_CHECK_THROW(static_cast<T>(llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()) - 1)), boost::math::rounding_error);
+ }
+#endif
+}
+
+int main()
+{
+#ifdef TEST_MPF_50
+ test<boost::multiprecision::mpf_float_50>();
+ test<boost::multiprecision::mpf_float_100>();
+#endif
+#ifdef TEST_MPFR_50
+ test<boost::multiprecision::mpfr_float_50>();
+ test<boost::multiprecision::mpfr_float_100>();
+#endif
+#ifdef TEST_MP_FLOAT
+ test<boost::multiprecision::mp_float_50>();
+ test<boost::multiprecision::mp_float_100>();
+#endif
+#ifdef TEST_BACKEND
+ test<boost::multiprecision::mp_number<boost::multiprecision::concepts::mp_number_backend_float_architype> >();
+#endif
+ return boost::report_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