Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r73819 - in sandbox/big_number: boost/math boost/math/big_number boost/math/concepts libs/math/test
From: john_at_[hidden]
Date: 2011-08-16 14:02:05


Author: johnmaddock
Date: 2011-08-16 14:02:03 EDT (Tue, 16 Aug 2011)
New Revision: 73819
URL: http://svn.boost.org/trac/boost/changeset/73819

Log:
Change backend concepts to allow for easier default implementations, plus out-of-place arithmetic as well as in-place.
Change non-member functions to use expression templates with result value passed to the function as "workspace".
Added:
   sandbox/big_number/boost/math/big_number/big_number_base.hpp (contents, props changed)
   sandbox/big_number/boost/math/big_number/default_ops.hpp (contents, props changed)
Text files modified:
   sandbox/big_number/boost/math/big_number.hpp | 560 +++++++++-------------------
   sandbox/big_number/boost/math/big_number/gmp.hpp | 767 ++++++++++++++++++++++++---------------
   sandbox/big_number/boost/math/concepts/big_number_architypes.hpp | 248 ++----------
   sandbox/big_number/libs/math/test/linpack-benchmark.cpp | 1
   sandbox/big_number/libs/math/test/test_arithmetic.cpp | 97 ++++
   5 files changed, 789 insertions(+), 884 deletions(-)

Modified: sandbox/big_number/boost/math/big_number.hpp
==============================================================================
--- sandbox/big_number/boost/math/big_number.hpp (original)
+++ sandbox/big_number/boost/math/big_number.hpp 2011-08-16 14:02:03 EDT (Tue, 16 Aug 2011)
@@ -17,157 +17,11 @@
 #include <boost/type_traits/is_signed.hpp>
 #include <boost/type_traits/is_unsigned.hpp>
 #include <boost/type_traits/is_floating_point.hpp>
+#include <boost/math/big_number/default_ops.hpp>
 
 namespace boost{ namespace math{
 
 template <class Backend>
-class big_number;
-
-namespace detail{
-
-// Forward-declare an expression wrapper
-template<typename Expr>
-struct big_number_exp;
-//
-// Declare our grammars:
-//
-struct big_number_grammar
- : proto::or_<
- proto::terminal< proto::_ >
- , proto::plus< big_number_grammar, big_number_grammar >
- , proto::multiplies< big_number_grammar, big_number_grammar >
- , proto::minus< big_number_grammar, big_number_grammar >
- , proto::divides< big_number_grammar, big_number_grammar >
- , proto::unary_plus< big_number_grammar >
- , proto::negate< big_number_grammar >
- , proto::modulus<big_number_grammar, big_number_grammar>
- >
-{};
-
-// Define a calculator domain. Expression within
-// the calculator domain will be wrapped in the
-// calculator<> expression wrapper.
-struct big_number_domain
- : proto::domain< proto::generator<big_number_exp>, big_number_grammar>
-{};
-
-template<typename Expr>
-struct big_number_exp
- : proto::extends<Expr, big_number_exp<Expr>, big_number_domain>
-{
- typedef
- proto::extends<Expr, big_number_exp<Expr>, big_number_domain> base_type;
-
- big_number_exp(Expr const &expr = Expr())
- : base_type(expr)
- {}
- template <class Other>
- big_number_exp(const Other& o)
- : base_type(o)
- {}
-};
-
-struct CalcDepth
- : proto::or_<
- proto::when< proto::terminal<proto::_>,
- mpl::int_<0>()
- >
- , proto::when< proto::unary_expr<proto::_, CalcDepth>,
- CalcDepth(proto::_child)
- >
- , proto::when< proto::binary_expr<proto::_, CalcDepth, CalcDepth>,
- mpl::plus<mpl::max<CalcDepth(proto::_left),
- CalcDepth(proto::_right)>, mpl::int_<1> >()
- >
- >
-{};
-
-template <int b>
-struct has_enough_bits
-{
- template <class T>
- struct type : public mpl::bool_<std::numeric_limits<T>::digits >= b>{};
-};
-
-template <class Val, class Backend, class Tag>
-struct canonical_imp
-{
- typedef Val type;
-};
-template <class Val, class Backend>
-struct canonical_imp<Val, Backend, mpl::int_<0> >
-{
- typedef typename has_enough_bits<std::numeric_limits<Val>::digits>::template type<mpl::_> pred_type;
- typedef typename mpl::find_if<
- typename Backend::signed_types,
- pred_type
- >::type iter_type;
- typedef typename mpl::deref<iter_type>::type type;
-};
-template <class Val, class Backend>
-struct canonical_imp<Val, Backend, mpl::int_<1> >
-{
- typedef typename has_enough_bits<std::numeric_limits<Val>::digits>::template type<mpl::_> pred_type;
- typedef typename mpl::find_if<
- typename Backend::unsigned_types,
- pred_type
- >::type iter_type;
- typedef typename mpl::deref<iter_type>::type type;
-};
-template <class Val, class Backend>
-struct canonical_imp<Val, Backend, mpl::int_<2> >
-{
- typedef typename has_enough_bits<std::numeric_limits<Val>::digits>::template type<mpl::_> pred_type;
- typedef typename mpl::find_if<
- typename Backend::real_types,
- pred_type
- >::type iter_type;
- typedef typename mpl::deref<iter_type>::type type;
-};
-template <class Val, class Backend>
-struct canonical_imp<Val, Backend, mpl::int_<3> >
-{
- typedef const char* type;
-};
-
-template <class Val, class Backend>
-struct canonical
-{
- typedef typename mpl::if_<
- is_signed<Val>,
- mpl::int_<0>,
- typename mpl::if_<
- is_unsigned<Val>,
- mpl::int_<1>,
- typename mpl::if_<
- is_floating_point<Val>,
- mpl::int_<2>,
- typename mpl::if_<
- mpl::or_<
- is_convertible<Val, const char*>,
- is_same<Val, std::string>
- >,
- mpl::int_<3>,
- mpl::int_<4>
- >::type
- >::type
- >::type
- >::type tag_type;
-
- typedef typename canonical_imp<Val, Backend, tag_type>::type type;
-};
-
-} // namespace detail
-
-//
-// Traits class, lets us know whether a backend is an integer type, otherwise assumed to be a real number type:
-//
-template <class Num>
-struct is_extended_integer : public mpl::false_ {};
-template <class Backend>
-struct is_extended_integer<big_number<Backend> > : public is_extended_integer<Backend>{};
-
-template <class Backend>
 class big_number : public detail::big_number_exp<typename proto::terminal<big_number<Backend>*>::type >
 {
    typedef detail::big_number_exp<typename proto::terminal<big_number<Backend>*>::type > base_type;
@@ -207,7 +61,7 @@
    template <class Exp>
    big_number& operator=(const detail::big_number_exp<Exp>& e)
    {
- do_assign(e, typename proto::tag_of<Exp>::type());
+ do_assign(e, typename detail::assign_and_eval<Exp>::type());
       return *this;
    }
 
@@ -230,7 +84,7 @@
    {
       proto::value(*this) = this;
       BOOST_ASSERT(proto::value(*this) == this);
- do_assign(e, typename proto::tag_of<Exp>::type());
+ do_assign(e, typename detail::assign_and_eval<Exp>::type());
    }
 
 #ifndef BOOST_NO_RVALUE_REFERENCES
@@ -267,7 +121,8 @@
    typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type
       operator+=(const V& v)
    {
- do_add_value(canonical_value(v), mpl::false_());
+ using big_num_default_ops::add;
+ add(m_backend, canonical_value(v));
       return *this;
    }
 
@@ -291,7 +146,8 @@
    typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type
       operator-=(const V& v)
    {
- do_subtract_value(canonical_value(v), mpl::false_());
+ using big_num_default_ops::subtract;
+ subtract(m_backend, canonical_value(v));
       return *this;
    }
 
@@ -316,7 +172,8 @@
    typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type
       operator*=(const V& v)
    {
- do_multiplies_value(canonical_value(v), mpl::false_());
+ using big_num_default_ops::multiply;
+ multiply(m_backend, canonical_value(v));
       return *this;
    }
 
@@ -342,7 +199,8 @@
       operator%=(const V& v)
    {
       BOOST_STATIC_ASSERT_MSG(is_extended_integer<Backend>::value, "The modulus operation is only valid for integer types");
- do_modulus_value(canonical_value(v), mpl::false_());
+ using big_num_default_ops::modulus;
+ modulus(m_backend, canonical_value(v));
       return *this;
    }
 
@@ -366,16 +224,17 @@
    typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type
       operator/=(const V& v)
    {
- do_divide_value(canonical_value(v), mpl::false_());
+ using big_num_default_ops::divide;
+ divide(m_backend, canonical_value(v));
       return *this;
    }
 
    //
    // String conversion functions:
    //
- std::string str(unsigned digits = 0)const
+ std::string str(unsigned digits = 0, bool scientific = true)const
    {
- return m_backend.str(digits);
+ return m_backend.str(digits, scientific);
    }
    //
    // Default precision:
@@ -418,17 +277,102 @@
    }
 private:
    template <class Exp>
+ void do_assign(const Exp& e, const detail::add_immediates&)
+ {
+ using big_num_default_ops::add;
+ typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
+ typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
+ add(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
+ }
+
+ template <class Exp>
+ void do_assign(const Exp& e, const detail::add_and_negate_immediates&)
+ {
+ using big_num_default_ops::add;
+ typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
+ typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
+ add(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
+ m_backend.negate();
+ }
+
+ template <class Exp>
+ void do_assign(const Exp& e, const detail::subtract_immediates&)
+ {
+ using big_num_default_ops::subtract;
+ typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
+ typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
+ subtract(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
+ }
+
+ template <class Exp>
+ void do_assign(const Exp& e, const detail::subtract_and_negate_immediates&)
+ {
+ using big_num_default_ops::subtract;
+ typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
+ typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
+ subtract(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
+ m_backend.negate();
+ }
+
+ template <class Exp>
+ void do_assign(const Exp& e, const detail::multiply_immediates&)
+ {
+ using big_num_default_ops::multiply;
+ typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
+ typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
+ multiply(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
+ }
+
+ template <class Exp>
+ void do_assign(const Exp& e, const detail::multiply_and_negate_immediates&)
+ {
+ using big_num_default_ops::multiply;
+ typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
+ typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
+ multiply(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
+ m_backend.negate();
+ }
+
+ template <class Exp>
+ void do_assign(const Exp& e, const detail::divide_immediates&)
+ {
+ using big_num_default_ops::divide;
+ typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
+ typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
+ divide(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
+ }
+
+ template <class Exp>
+ void do_assign(const Exp& e, const detail::divide_and_negate_immediates&)
+ {
+ using big_num_default_ops::divide;
+ typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
+ typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
+ divide(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
+ m_backend.negate();
+ }
+
+ template <class Exp>
+ void do_assign(const Exp& e, const detail::modulus_immediates&)
+ {
+ using big_num_default_ops::modulus;
+ typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
+ typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
+ modulus(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
+ }
+
+ template <class Exp>
    void do_assign(const Exp& e, const proto::tag::unary_plus&)
    {
       typedef typename proto::result_of::left<Exp>::type left_type;
- do_assign(proto::left(e), typename proto::tag_of<left_type>::type());
+ do_assign(proto::left(e), typename detail::assign_and_eval<left_type>::type());
    }
 
    template <class Exp>
    void do_assign(const Exp& e, const proto::tag::negate&)
    {
       typedef typename proto::result_of::left<Exp>::type left_type;
- do_assign(proto::left(e), typename proto::tag_of<left_type>::type());
+ do_assign(proto::left(e), typename detail::assign_and_eval<left_type>::type());
       m_backend.negate();
    }
 
@@ -461,12 +405,12 @@
       }
       else if(left_depth >= right_depth)
       {
- do_assign(proto::left(e), typename proto::tag_of<left_type>::type());
+ do_assign(proto::left(e), typename detail::assign_and_eval<left_type>::type());
          do_add(proto::right(e), typename proto::tag_of<right_type>::type());
       }
       else
       {
- do_assign(proto::right(e), typename proto::tag_of<right_type>::type());
+ do_assign(proto::right(e), typename detail::assign_and_eval<right_type>::type());
          do_add(proto::left(e), typename proto::tag_of<left_type>::type());
       }
    }
@@ -500,12 +444,12 @@
       }
       else if(left_depth >= right_depth)
       {
- do_assign(proto::left(e), typename proto::tag_of<left_type>::type());
+ do_assign(proto::left(e), typename detail::assign_and_eval<left_type>::type());
          do_subtract(proto::right(e), typename proto::tag_of<right_type>::type());
       }
       else
       {
- do_assign(proto::right(e), typename proto::tag_of<right_type>::type());
+ do_assign(proto::right(e), typename detail::assign_and_eval<right_type>::type());
          do_subtract(proto::left(e), typename proto::tag_of<left_type>::type());
          m_backend.negate();
       }
@@ -539,12 +483,12 @@
       }
       else if(left_depth >= right_depth)
       {
- do_assign(proto::left(e), typename proto::tag_of<left_type>::type());
+ do_assign(proto::left(e), typename detail::assign_and_eval<left_type>::type());
          do_multiplies(proto::right(e), typename proto::tag_of<right_type>::type());
       }
       else
       {
- do_assign(proto::right(e), typename proto::tag_of<right_type>::type());
+ do_assign(proto::right(e), typename detail::assign_and_eval<right_type>::type());
          do_multiplies(proto::left(e), typename proto::tag_of<left_type>::type());
       }
    }
@@ -572,7 +516,7 @@
       }
       else
       {
- do_assign(proto::left(e), typename proto::tag_of<left_type>::type());
+ do_assign(proto::left(e), typename detail::assign_and_eval<left_type>::type());
          do_divide(proto::right(e), typename proto::tag_of<right_type>::type());
       }
    }
@@ -605,7 +549,7 @@
       }
       else
       {
- do_assign(proto::left(e), typename proto::tag_of<left_type>::type());
+ do_assign(proto::left(e), typename detail::assign_and_eval<left_type>::type());
          do_modulus(proto::right(e), typename proto::tag_of<right_type>::type());
       }
    }
@@ -617,28 +561,55 @@
          m_backend = canonical_value(proto::value(e));
       }
    }
-
    template <class Exp>
- void do_add(const Exp& e, const proto::tag::terminal&)
+ void do_assign(const Exp& e, const proto::tag::function&)
    {
- typedef typename proto::result_of::value<Exp>::type t1;
- typedef typename remove_reference<t1>::type t2;
- typedef typename remove_cv<t2>::type t3;
- typedef typename detail::canonical<t3, Backend>::type t4;
- typedef typename is_convertible<t4, const char*>::type tag;
- do_add_value(canonical_value(proto::value(e)), tag());
+ typedef typename proto::arity_of<Exp>::type tag_type;
+ do_assign_function(e, tag_type());
    }
-
- template <class V>
- void do_add_value(const V& v, const mpl::false_&)
+ template <class Exp>
+ void do_assign_function(const Exp& e, const mpl::long_<1>&)
    {
- m_backend += v;
+ proto::value(proto::left(e))(&m_backend);
    }
- template <class V>
- void do_add_value(const V& v, const mpl::true_&)
+ template <class Exp>
+ void do_assign_function(const Exp& e, const mpl::long_<2>&)
+ {
+ typedef typename proto::result_of::right<Exp>::type right_type;
+ typedef typename proto::tag_of<right_type>::type tag_type;
+ do_assign_function_1(proto::value(proto::left(e)), proto::right(e), tag_type());
+ }
+ template <class F, class Exp>
+ void do_assign_function_1(const F& f, const Exp& val, const proto::tag::terminal&)
+ {
+ f(&m_backend, canonical_value(proto::value(val)));
+ }
+ template <class F, class Exp, class Tag>
+ void do_assign_function_1(const F& f, const Exp& val, const Tag&)
+ {
+ big_number t(val);
+ f(&m_backend, t.backend());
+ }
+ template <class Exp>
+ void do_assign_function(const Exp& e, const mpl::long_<3>&)
+ {
+ typedef typename proto::result_of::right<Exp>::type right_type;
+ typedef typename proto::tag_of<right_type>::type tag_type;
+ typedef typename proto::result_of::child_c<Exp, 2>::type end_type;
+ typedef typename proto::tag_of<end_type>::type end_tag;
+ do_assign_function_2(proto::value(proto::left(e)), proto::right(e), proto::child_c<2>(e), tag_type(), end_tag());
+ }
+ template <class F, class Exp1, class Exp2>
+ void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const proto::tag::terminal&, const proto::tag::terminal&)
+ {
+ f(&m_backend, canonical_value(proto::value(val1)), canonical_value(proto::value(val2)));
+ }
+
+ template <class Exp>
+ void do_add(const Exp& e, const proto::tag::terminal&)
    {
- self_type temp(v);
- m_backend += temp.m_backend;
+ using big_num_default_ops::add;
+ add(m_backend, canonical_value(proto::value(e)));
    }
 
    template <class Exp>
@@ -683,24 +654,8 @@
    template <class Exp>
    void do_subtract(const Exp& e, const proto::tag::terminal&)
    {
- typedef typename proto::result_of::value<Exp>::type t1;
- typedef typename remove_reference<t1>::type t2;
- typedef typename remove_cv<t2>::type t3;
- typedef typename detail::canonical<t3, Backend>::type t4;
- typedef typename is_convertible<t4, const char*>::type tag;
- do_subtract_value(canonical_value(proto::value(e)), tag());
- }
-
- template <class V>
- void do_subtract_value(const V& v, const mpl::false_&)
- {
- m_backend -= v;
- }
- template <class V>
- void do_subtract_value(const V& v, const mpl::true_&)
- {
- self_type temp(v);
- m_backend -= temp.m_backend;
+ using big_num_default_ops::subtract;
+ subtract(m_backend, canonical_value(proto::value(e)));
    }
 
    template <class Exp>
@@ -745,25 +700,8 @@
    template <class Exp>
    void do_multiplies(const Exp& e, const proto::tag::terminal&)
    {
- typedef typename proto::result_of::value<Exp>::type t1;
- typedef typename remove_reference<t1>::type t2;
- typedef typename remove_cv<t2>::type t3;
- typedef typename detail::canonical<t3, Backend>::type t4;
- typedef typename is_convertible<t4, const char*>::type tag;
- do_multiplies_value(canonical_value(proto::value(e)), tag());
- }
-
- template <class Val>
- void do_multiplies_value(const Val& v, const mpl::false_&)
- {
- m_backend *= v;
- }
-
- template <class Val>
- void do_multiplies_value(const Val& e, const mpl::true_&)
- {
- self_type temp(e);
- m_backend *= temp.m_backend;
+ using big_num_default_ops::multiply;
+ multiply(m_backend, canonical_value(proto::value(e)));
    }
 
    template <class Exp>
@@ -802,32 +740,16 @@
    template <class Exp, class unknown>
    void do_multiplies(const Exp& e, const unknown&)
    {
+ using big_num_default_ops::multiply;
       self_type temp(e);
- m_backend *= temp.m_backend;
+ multiply(m_backend, temp.m_backend);
    }
 
    template <class Exp>
    void do_divide(const Exp& e, const proto::tag::terminal&)
    {
- typedef typename proto::result_of::value<Exp>::type t1;
- typedef typename remove_reference<t1>::type t2;
- typedef typename remove_cv<t2>::type t3;
- typedef typename detail::canonical<t3, Backend>::type t4;
- typedef typename is_convertible<t4, const char*>::type tag;
- do_divide_value(canonical_value(proto::value(e)), tag());
- }
-
- template <class Val>
- void do_divide_value(const Val& v, const mpl::false_&)
- {
- m_backend /= v;
- }
-
- template <class Val>
- void do_divide_value(const Val& e, const mpl::true_&)
- {
- self_type temp(e);
- m_backend /= temp.m_backend;
+ using big_num_default_ops::divide;
+ divide(m_backend, canonical_value(proto::value(e)));
    }
 
    template <class Exp>
@@ -866,39 +788,24 @@
    template <class Exp, class unknown>
    void do_divide(const Exp& e, const unknown&)
    {
+ using big_num_default_ops::multiply;
       self_type temp(e);
- m_backend /= temp.m_backend;
+ divide(m_backend, temp.m_backend);
    }
 
    template <class Exp>
    void do_modulus(const Exp& e, const proto::tag::terminal&)
    {
- typedef typename proto::result_of::value<Exp>::type t1;
- typedef typename remove_reference<t1>::type t2;
- typedef typename remove_cv<t2>::type t3;
- typedef typename detail::canonical<t3, Backend>::type t4;
- typedef typename is_convertible<t4, const char*>::type tag;
- do_modulus_value(canonical_value(proto::value(e)), tag());
- }
-
- template <class Val>
- void do_modulus_value(const Val& v, const mpl::false_&)
- {
- m_backend %= v;
- }
-
- template <class Val>
- void do_modulus_value(const Val& e, const mpl::true_&)
- {
- self_type temp(e);
- m_backend %= temp.m_backend;
+ using big_num_default_ops::modulus;
+ modulus(m_backend, canonical_value(proto::value(e)));
    }
 
    template <class Exp, class Unknown>
    void do_modulus(const Exp& e, const Unknown&)
    {
+ using big_num_default_ops::modulus;
       self_type temp(e);
- do_modulus_value(canonical_value(proto::value(temp)), mpl::false_());
+ modulus(m_backend, canonical_value(proto::value(temp)));
    }
 
    // Tests if the expression contains a reference to *this:
@@ -953,6 +860,19 @@
    {
       return v == this;
    }
+ template <class Exp>
+ static typename detail::underlying_result<Exp>::type underlying_value(const big_number_exp<Exp>& e, const proto::tag::terminal&)
+ {
+ return proto::value(e);
+ }
+ template <class Exp, class tag>
+ static typename detail::underlying_result<Exp>::type
+ underlying_value(const big_number_exp<Exp>& e, const tag&)
+ {
+ typedef typename proto::result_of::left<Exp>::type left_type;
+ typedef typename proto::tag_of<left_type>::type tag_type;
+ return underlying_value(proto::left(e), tag_type());
+ }
 
    static const Backend& canonical_value(const self_type& v){ return v.m_backend; }
    static const Backend& canonical_value(const self_type* v){ return v->m_backend; }
@@ -967,72 +887,6 @@
 namespace detail
 {
 
-template <class Exp1, class Exp2>
-struct combine_expression_type
-{
- typedef void type;
-};
-
-template <class Backend>
-struct combine_expression_type<boost::math::big_number<Backend>, boost::math::big_number<Backend> >
-{
- typedef boost::math::big_number<Backend> type;
-};
-
-template <class Backend, class Exp>
-struct combine_expression_type<boost::math::big_number<Backend>, Exp>
-{
- typedef boost::math::big_number<Backend> type;
-};
-
-template <class Backend, class Exp>
-struct combine_expression_type<Exp, boost::math::big_number<Backend> >
-{
- typedef boost::math::big_number<Backend> type;
-};
-
-template <class T>
-struct is_big_number : public mpl::false_{};
-template <class T>
-struct is_big_number<boost::math::big_number<T> > : public mpl::true_{};
-template <class T>
-struct is_big_number_exp : public mpl::false_{};
-template <class T>
-struct is_big_number_exp<boost::math::detail::big_number_exp<T> > : public mpl::true_{};
-
-
-template <class Exp, int arity>
-struct expression_type_imp;
-
-template <class Exp>
-struct expression_type_imp<Exp, 0>
-{
- typedef typename remove_pointer<typename proto::result_of::value<Exp>::type>::type type;
-};
-
-template <class Exp>
-struct expression_type_imp<Exp, 1>
-{
- typedef typename proto::result_of::left<Exp>::type nested_type;
- typedef typename expression_type_imp<nested_type, proto::arity_of<nested_type>::value>::type type;
-};
-
-template <class Exp>
-struct expression_type_imp<Exp, 2>
-{
- typedef typename proto::result_of::left<Exp>::type left_type;
- typedef typename proto::result_of::right<Exp>::type right_type;
- typedef typename expression_type_imp<left_type, proto::arity_of<left_type>::value>::type left_result;
- typedef typename expression_type_imp<right_type, proto::arity_of<right_type>::value>::type right_result;
- typedef typename combine_expression_type<left_result, right_result>::type type;
-};
-
-template <class Exp>
-struct expression_type
-{
- typedef typename expression_type_imp<Exp, proto::arity_of<Exp>::value>::type type;
-};
-
 template <class Backend>
 inline int big_number_compare(const big_number<Backend>& a, const big_number<Backend>& b)
 {
@@ -1164,13 +1018,20 @@
 }
 
 template <class Backend>
-std::ostream& operator << (std::ostream& os, const big_number<Backend>& r)
+inline std::ostream& operator << (std::ostream& os, const big_number<Backend>& r)
+{
+ return os << r.str(static_cast<unsigned>(os.precision(), os.flags() & os.scientific));
+}
+template <class Exp>
+inline std::ostream& operator << (std::ostream& os, const detail::big_number_exp<Exp>& r)
 {
- return os << r.str(static_cast<unsigned>(os.precision()));
+ typedef typename detail::expression_type<Exp>::type value_type;
+ value_type temp(r);
+ return os << temp;
 }
 
 template <class Backend>
-std::istream& operator >> (std::istream& is, big_number<Backend>& r)
+inline std::istream& operator >> (std::istream& is, big_number<Backend>& r)
 {
    std::string s;
    is >> s;
@@ -1178,47 +1039,6 @@
    return is;
 }
 
-//
-// Non-member functions accepting an expression-template as argument:
-//
-#undef sqrt
-template <class Exp>
-typename boost::math::detail::expression_type<Exp>::type sqrt(const detail::big_number_exp<Exp>& val)
-{
- typedef typename detail::expression_type<Exp>::type result_type;
- return sqrt(result_type(val));
-}
-template <class Exp>
-typename detail::expression_type<Exp>::type abs(const detail::big_number_exp<Exp>& val)
-{
- typedef typename detail::expression_type<Exp>::type result_type;
- return abs(result_type(val));
-}
-template <class Exp>
-typename detail::expression_type<Exp>::type fabs(const detail::big_number_exp<Exp>& val)
-{
- typedef typename detail::expression_type<Exp>::type result_type;
- return fabs(result_type(val));
-}
-template <class Exp>
-typename detail::expression_type<Exp>::type ceil(const detail::big_number_exp<Exp>& val)
-{
- typedef typename detail::expression_type<Exp>::type result_type;
- return ceil(result_type(val));
-}
-template <class Exp>
-typename detail::expression_type<Exp>::type floor(const detail::big_number_exp<Exp>& val)
-{
- typedef typename detail::expression_type<Exp>::type result_type;
- return floor(result_type(val));
-}
-template <class Exp>
-typename detail::expression_type<Exp>::type trunc(const detail::big_number_exp<Exp>& val)
-{
- typedef typename detail::expression_type<Exp>::type result_type;
- return trunc(result_type(val));
-}
-
 }} // namespaces
 
 #endif

Added: sandbox/big_number/boost/math/big_number/big_number_base.hpp
==============================================================================
--- (empty file)
+++ sandbox/big_number/boost/math/big_number/big_number_base.hpp 2011-08-16 14:02:03 EDT (Tue, 16 Aug 2011)
@@ -0,0 +1,463 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2011 John Maddock. Distributed under 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)
+
+#ifndef BOOST_MATH_BIG_NUM_BASE_HPP
+#define BOOST_MATH_BIG_NUM_BASE_HPP
+
+namespace boost{ namespace math{
+
+template <class Backend>
+class big_number;
+
+namespace detail{
+
+// Forward-declare an expression wrapper
+template<typename Expr>
+struct big_number_exp;
+//
+// Declare our grammars:
+//
+struct big_number_grammar
+ : proto::or_<
+ proto::terminal< proto::_ >
+ , proto::plus< big_number_grammar, big_number_grammar >
+ , proto::multiplies< big_number_grammar, big_number_grammar >
+ , proto::minus< big_number_grammar, big_number_grammar >
+ , proto::divides< big_number_grammar, big_number_grammar >
+ , proto::unary_plus< big_number_grammar >
+ , proto::negate< big_number_grammar >
+ , proto::modulus<big_number_grammar, big_number_grammar>
+ >
+{};
+
+// Define a calculator domain. Expression within
+// the calculator domain will be wrapped in the
+// calculator<> expression wrapper.
+struct big_number_domain
+ : proto::domain< proto::generator<big_number_exp>, big_number_grammar>
+{};
+
+template<typename Expr>
+struct big_number_exp
+ : proto::extends<Expr, big_number_exp<Expr>, big_number_domain>
+{
+ typedef
+ proto::extends<Expr, big_number_exp<Expr>, big_number_domain> base_type;
+
+ big_number_exp(Expr const &expr = Expr())
+ : base_type(expr)
+ {}
+ template <class Other>
+ big_number_exp(const Other& o)
+ : base_type(o)
+ {}
+};
+
+struct CalcDepth
+ : proto::or_<
+ proto::when< proto::terminal<proto::_>,
+ mpl::int_<0>()
+ >
+ , proto::when< proto::unary_expr<proto::_, CalcDepth>,
+ CalcDepth(proto::_child)
+ >
+ , proto::when< proto::binary_expr<proto::_, CalcDepth, CalcDepth>,
+ mpl::plus<mpl::max<CalcDepth(proto::_left),
+ CalcDepth(proto::_right)>, mpl::int_<1> >()
+ >
+ >
+{};
+
+template <int b>
+struct has_enough_bits
+{
+ template <class T>
+ struct type : public mpl::bool_<std::numeric_limits<T>::digits >= b>{};
+};
+
+template <class Val, class Backend, class Tag>
+struct canonical_imp
+{
+ typedef Val type;
+};
+template <class Val, class Backend>
+struct canonical_imp<Val, Backend, mpl::int_<0> >
+{
+ typedef typename has_enough_bits<std::numeric_limits<Val>::digits>::template type<mpl::_> pred_type;
+ typedef typename mpl::find_if<
+ typename Backend::signed_types,
+ pred_type
+ >::type iter_type;
+ typedef typename mpl::deref<iter_type>::type type;
+};
+template <class Val, class Backend>
+struct canonical_imp<Val, Backend, mpl::int_<1> >
+{
+ typedef typename has_enough_bits<std::numeric_limits<Val>::digits>::template type<mpl::_> pred_type;
+ typedef typename mpl::find_if<
+ typename Backend::unsigned_types,
+ pred_type
+ >::type iter_type;
+ typedef typename mpl::deref<iter_type>::type type;
+};
+template <class Val, class Backend>
+struct canonical_imp<Val, Backend, mpl::int_<2> >
+{
+ typedef typename has_enough_bits<std::numeric_limits<Val>::digits>::template type<mpl::_> pred_type;
+ typedef typename mpl::find_if<
+ typename Backend::real_types,
+ pred_type
+ >::type iter_type;
+ typedef typename mpl::deref<iter_type>::type type;
+};
+template <class Val, class Backend>
+struct canonical_imp<Val, Backend, mpl::int_<3> >
+{
+ typedef const char* type;
+};
+
+template <class Val, class Backend>
+struct canonical
+{
+ typedef typename mpl::if_<
+ is_signed<Val>,
+ mpl::int_<0>,
+ typename mpl::if_<
+ is_unsigned<Val>,
+ mpl::int_<1>,
+ typename mpl::if_<
+ is_floating_point<Val>,
+ mpl::int_<2>,
+ typename mpl::if_<
+ mpl::or_<
+ is_convertible<Val, const char*>,
+ is_same<Val, std::string>
+ >,
+ mpl::int_<3>,
+ mpl::int_<4>
+ >::type
+ >::type
+ >::type
+ >::type tag_type;
+
+ typedef typename canonical_imp<Val, Backend, tag_type>::type type;
+};
+
+template <class Exp, class tag>
+struct assign_and_eval_imp
+{
+ typedef tag type;
+};
+
+struct add_immediates{};
+struct add_and_negate_immediates{};
+struct subtract_immediates{};
+struct subtract_and_negate_immediates{};
+struct multiply_immediates{};
+struct multiply_and_negate_immediates{};
+struct divide_immediates{};
+struct divide_and_negate_immediates{};
+struct modulus_immediates{};
+
+struct immediate{};
+struct negative_immediate{};
+
+template <class Exp, class tag>
+struct immediate_type
+{
+ typedef tag type;
+};
+template <class Exp>
+struct immediate_type<Exp, proto::tag::terminal>
+{
+ typedef immediate type;
+};
+template <class Exp>
+struct immediate_type<Exp, proto::tag::unary_plus>
+{
+ typedef typename proto::result_of::left<Exp>::type left_type;
+ typedef typename proto::tag_of<left_type>::type left_tag;
+ typedef typename mpl::if_<
+ is_same<left_tag, proto::tag::terminal>,
+ immediate,
+ left_tag
+ >::type type;
+};
+template <class Exp>
+struct immediate_type<Exp, proto::tag::negate>
+{
+ typedef typename proto::result_of::left<Exp>::type left_type;
+ typedef typename proto::tag_of<left_type>::type left_tag;
+ typedef typename immediate_type<left_type, left_tag>::type tag;
+ typedef typename mpl::if_<
+ is_same<immediate, tag>,
+ negative_immediate,
+ tag
+ >::type type;
+};
+
+template <class Exp>
+struct assign_and_eval_imp<Exp, proto::tag::plus>
+{
+ typedef typename proto::result_of::left<Exp>::type left_type;
+ typedef typename proto::result_of::right<Exp>::type right_type;
+ typedef typename proto::tag_of<left_type>::type left_tag;
+ typedef typename proto::tag_of<right_type>::type right_tag;
+ typedef typename immediate_type<left_type, left_tag>::type left_imm;
+ typedef typename immediate_type<right_type, right_tag>::type right_imm;
+ typedef typename mpl::if_<
+ mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, immediate> >,
+ add_immediates,
+ typename mpl::if_<
+ mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, negative_immediate> >,
+ subtract_immediates,
+ typename mpl::if_<
+ mpl::and_<is_same<left_imm, negative_immediate>, is_same<right_imm, immediate> >,
+ subtract_and_negate_immediates,
+ typename mpl::if_<
+ mpl::and_<is_same<left_imm, negative_immediate>, is_same<right_imm, negative_immediate> >,
+ add_and_negate_immediates,
+ proto::tag::plus
+ >::type
+ >::type
+ >::type
+ >::type type;
+};
+
+template <class Exp>
+struct assign_and_eval_imp<Exp, proto::tag::minus>
+{
+ typedef typename proto::result_of::left<Exp>::type left_type;
+ typedef typename proto::result_of::right<Exp>::type right_type;
+ typedef typename proto::tag_of<left_type>::type left_tag;
+ typedef typename proto::tag_of<right_type>::type right_tag;
+ typedef typename immediate_type<left_type, left_tag>::type left_imm;
+ typedef typename immediate_type<right_type, right_tag>::type right_imm;
+ typedef typename mpl::if_<
+ mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, immediate> >,
+ subtract_immediates,
+ typename mpl::if_<
+ mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, negative_immediate> >,
+ add_immediates,
+ typename mpl::if_<
+ mpl::and_<is_same<left_imm, negative_immediate>, is_same<right_imm, immediate> >,
+ add_and_negate_immediates,
+ typename mpl::if_<
+ mpl::and_<is_same<left_imm, negative_immediate>, is_same<right_imm, negative_immediate> >,
+ subtract_and_negate_immediates,
+ proto::tag::minus
+ >::type
+ >::type
+ >::type
+ >::type type;
+};
+
+template <class Exp>
+struct assign_and_eval_imp<Exp, proto::tag::multiplies>
+{
+ typedef typename proto::result_of::left<Exp>::type left_type;
+ typedef typename proto::result_of::right<Exp>::type right_type;
+ typedef typename proto::tag_of<left_type>::type left_tag;
+ typedef typename proto::tag_of<right_type>::type right_tag;
+ typedef typename immediate_type<left_type, left_tag>::type left_imm;
+ typedef typename immediate_type<right_type, right_tag>::type right_imm;
+ typedef typename mpl::if_<
+ mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, immediate> >,
+ multiply_immediates,
+ typename mpl::if_<
+ mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, negative_immediate> >,
+ multiply_and_negate_immediates,
+ typename mpl::if_<
+ mpl::and_<is_same<left_imm, negative_immediate>, is_same<right_imm, immediate> >,
+ multiply_and_negate_immediates,
+ typename mpl::if_<
+ mpl::and_<is_same<left_imm, negative_immediate>, is_same<right_imm, negative_immediate> >,
+ multiply_immediates,
+ proto::tag::multiplies
+ >::type
+ >::type
+ >::type
+ >::type type;
+};
+
+template <class Exp>
+struct assign_and_eval_imp<Exp, proto::tag::divides>
+{
+ typedef typename proto::result_of::left<Exp>::type left_type;
+ typedef typename proto::result_of::right<Exp>::type right_type;
+ typedef typename proto::tag_of<left_type>::type left_tag;
+ typedef typename proto::tag_of<right_type>::type right_tag;
+ typedef typename immediate_type<left_type, left_tag>::type left_imm;
+ typedef typename immediate_type<right_type, right_tag>::type right_imm;
+ typedef typename mpl::if_<
+ mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, immediate> >,
+ divide_immediates,
+ typename mpl::if_<
+ mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, negative_immediate> >,
+ divide_and_negate_immediates,
+ typename mpl::if_<
+ mpl::and_<is_same<left_imm, negative_immediate>, is_same<right_imm, immediate> >,
+ divide_and_negate_immediates,
+ typename mpl::if_<
+ mpl::and_<is_same<left_imm, negative_immediate>, is_same<right_imm, negative_immediate> >,
+ divide_immediates,
+ proto::tag::divides
+ >::type
+ >::type
+ >::type
+ >::type type;
+};
+
+template <class Exp>
+struct assign_and_eval_imp<Exp, proto::tag::modulus>
+{
+ typedef typename proto::result_of::left<Exp>::type left_type;
+ typedef typename proto::result_of::right<Exp>::type right_type;
+ typedef typename proto::tag_of<left_type>::type left_tag;
+ typedef typename proto::tag_of<right_type>::type right_tag;
+ typedef typename immediate_type<left_type, left_tag>::type left_imm;
+ typedef typename immediate_type<right_type, right_tag>::type right_imm;
+ typedef typename mpl::if_<
+ mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, immediate> >,
+ modulus_immediates,
+ proto::tag::modulus
+ >::type type;
+};
+
+template <class Exp>
+struct assign_and_eval
+{
+ typedef typename proto::tag_of<Exp>::type tag_type;
+ typedef typename assign_and_eval_imp<Exp, tag_type>::type type;
+};
+
+template <class Exp, class tag>
+struct underlying_result_imp
+{
+ typedef typename proto::result_of::left<Exp>::type left_type;
+ typedef typename proto::tag_of<left_type>::type tag_type;
+ typedef typename underlying_result_imp<left_type, tag_type>::type type;
+};
+
+template <class Exp>
+struct underlying_result_imp<Exp, proto::tag::terminal>
+{
+ typedef typename proto::result_of::value<Exp const &>::type type;
+};
+
+template <class Exp>
+struct underlying_result
+{
+ typedef typename proto::tag_of<Exp>::type tag_type;
+ typedef typename underlying_result_imp<Exp, tag_type>::type type;
+};
+
+template <class Exp1, class Exp2>
+struct combine_expression_type
+{
+ typedef void type;
+};
+
+template <class Backend>
+struct combine_expression_type<boost::math::big_number<Backend>, boost::math::big_number<Backend> >
+{
+ typedef boost::math::big_number<Backend> type;
+};
+
+template <class Backend, class Exp>
+struct combine_expression_type<boost::math::big_number<Backend>, Exp>
+{
+ typedef boost::math::big_number<Backend> type;
+};
+
+template <class Backend, class Exp>
+struct combine_expression_type<Exp, boost::math::big_number<Backend> >
+{
+ typedef boost::math::big_number<Backend> type;
+};
+
+template <class T>
+struct is_big_number : public mpl::false_{};
+template <class T>
+struct is_big_number<boost::math::big_number<T> > : public mpl::true_{};
+template <class T>
+struct is_big_number_exp : public mpl::false_{};
+template <class T>
+struct is_big_number_exp<boost::math::detail::big_number_exp<T> > : public mpl::true_{};
+
+
+template <class Exp, int arity>
+struct expression_type_imp;
+
+template <class Exp>
+struct expression_type_imp<Exp, 0>
+{
+ typedef typename remove_pointer<typename proto::result_of::value<Exp>::type>::type type;
+};
+
+template <class Exp>
+struct expression_type_imp<Exp, 1>
+{
+ typedef typename proto::result_of::left<Exp>::type nested_type;
+ typedef typename expression_type_imp<nested_type, proto::arity_of<nested_type>::value>::type type;
+};
+
+template <class Exp>
+struct expression_type_imp<Exp, 2>
+{
+ typedef typename proto::result_of::left<Exp>::type left_type;
+ typedef typename proto::result_of::right<Exp>::type right_type;
+ typedef typename expression_type_imp<left_type, proto::arity_of<left_type>::value>::type left_result;
+ typedef typename expression_type_imp<right_type, proto::arity_of<right_type>::value>::type right_result;
+ typedef typename combine_expression_type<left_result, right_result>::type type;
+};
+
+template <class Exp>
+struct expression_type_imp<Exp, 3>
+{
+ typedef typename proto::result_of::left<Exp>::type left_type;
+ typedef typename proto::result_of::right<Exp>::type right_type;
+ typedef typename proto::result_of::child_c<Exp, 2>::type end_type;
+ typedef typename expression_type_imp<left_type, proto::arity_of<left_type>::value>::type left_result;
+ typedef typename expression_type_imp<right_type, proto::arity_of<right_type>::value>::type right_result;
+ typedef typename expression_type_imp<end_type, proto::arity_of<end_type>::value>::type end_result;
+ typedef typename combine_expression_type<left_result, typename combine_expression_type<right_result, end_type>::type>::type type;
+};
+
+template <class Exp>
+struct expression_type
+{
+ typedef typename expression_type_imp<Exp, proto::arity_of<Exp>::value>::type type;
+};
+
+template <class Exp>
+struct backend_type
+{
+ typedef typename expression_type<Exp>::type num_type;
+ typedef typename backend_type<num_type>::type type;
+};
+
+template <class Backend>
+struct backend_type<boost::math::big_number<Backend> >
+{
+ typedef Backend type;
+};
+
+} // namespace detail
+
+//
+// Traits class, lets us know whether a backend is an integer type, otherwise assumed to be a real number type:
+//
+template <class Num>
+struct is_extended_integer : public mpl::false_ {};
+template <class Backend>
+struct is_extended_integer<big_number<Backend> > : public is_extended_integer<Backend>{};
+
+
+}} // namespaces
+
+#endif // BOOST_MATH_BIG_NUM_BASE_HPP
+
+

Added: sandbox/big_number/boost/math/big_number/default_ops.hpp
==============================================================================
--- (empty file)
+++ sandbox/big_number/boost/math/big_number/default_ops.hpp 2011-08-16 14:02:03 EDT (Tue, 16 Aug 2011)
@@ -0,0 +1,302 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2011 John Maddock. Distributed under 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)
+
+#ifndef BOOST_MATH_BIG_NUM_DEF_OPS
+#define BOOST_MATH_BIG_NUM_DEF_OPS
+
+#include <boost/math/big_number/big_number_base.hpp>
+
+namespace boost{ namespace math{ namespace big_num_default_ops{
+
+//
+// Default versions of mixed arithmetic, these just construct a temporary
+// from the arithmetic value and then do the arithmetic on that:
+//
+template <class T, class V>
+inline typename enable_if<mpl::or_<is_arithmetic<V>, is_convertible<V, const char*>, is_same<V, std::string> > >::type
+ add(T& result, V const& v)
+{
+ T t;
+ t = v;
+ add(result, t);
+}
+template <class T, class V>
+inline typename enable_if<mpl::or_<is_arithmetic<V>, is_convertible<V, const char*>, is_same<V, std::string> > >::type
+ subtract(T& result, V const& v)
+{
+ T t;
+ t = v;
+ subtract(result, t);
+}
+template <class T, class V>
+inline typename enable_if<mpl::or_<is_arithmetic<V>, is_convertible<V, const char*>, is_same<V, std::string> > >::type
+ multiply(T& result, V const& v)
+{
+ T t;
+ t = v;
+ multiply(result, t);
+}
+template <class T, class V>
+inline typename enable_if<mpl::or_<is_arithmetic<V>, is_convertible<V, const char*>, is_same<V, std::string> > >::type
+ divide(T& result, V const& v)
+{
+ T t;
+ t = v;
+ divide(result, t);
+}
+template <class T, class V>
+inline typename enable_if<mpl::or_<is_arithmetic<V>, is_convertible<V, const char*>, is_same<V, std::string> > >::type
+ modulus(T& result, V const& v)
+{
+ T t;
+ t = v;
+ mudulus(result, t);
+}
+
+template <class T>
+inline bool is_same_object(const T& u, const T&v)
+{ return &u == &v; }
+template <class T, class U>
+inline bool is_same_object(const T& u, const U&v)
+{ return false; }
+
+//
+// Default versions of 3-arg arithmetic functions, these just forward to the 2 arg versions:
+//
+template <class T, class U, class V>
+inline void add(T& t, const U& u, const V& v)
+{
+ if(is_same_object(t, v))
+ {
+ add(t, u);
+ }
+ else if(is_same_object(t, u))
+ {
+ add(t, v);
+ }
+ else
+ {
+ t = u;
+ add(t, v);
+ }
+}
+template <class T, class U, class V>
+inline void subtract(T& t, const U& u, const V& v)
+{
+ if(is_same_object(t, u))
+ subtract(t, v);
+ else if(is_same_object(t, v))
+ {
+ subtract(t, u);
+ t.negate();
+ }
+ else
+ {
+ t = u;
+ subtract(t, v);
+ }
+}
+template <class T, class U, class V>
+inline void multiply(T& t, const U& u, const V& v)
+{
+ if(is_same_object(t, u))
+ multiply(t, v);
+ else if(is_same_object(t, v))
+ multiply(t, u);
+ else
+ {
+ t = u;
+ multiply(t, v);
+ }
+}
+template <class T, class U, class V>
+inline void divide(T& t, const U& u, const V& v)
+{
+ if(is_same_object(t, u))
+ divide(t, v);
+ else if(is_same_object(t, v))
+ {
+ T temp = t;
+ divide(temp, u, v);
+ temp.swap(t);
+ }
+ else
+ {
+ t = u;
+ divide(t, v);
+ }
+}
+template <class T, class U, class V>
+inline void modulus(T& t, const U& u, const V& v)
+{
+ if(is_same_object(t, u))
+ modulus(t, v);
+ else if(is_same_object(t, v))
+ {
+ T temp;
+ modulus(temp, u, v);
+ temp.swap(t);
+ }
+ else
+ {
+ t = u;
+ modulus(t, v);
+ }
+}
+
+//
+// Functions:
+//
+template <class T>
+void abs(T* result, const T& arg)
+{
+ typedef typename T::signed_types type_list;
+ typedef typename mpl::front<type_list>::type front;
+ *result = arg;
+ if(arg.compare(front(0)) < 0)
+ result->negate();
+}
+template <class T>
+void fabs(T* result, const T& arg)
+{
+ typedef typename T::signed_types type_list;
+ typedef typename mpl::front<type_list>::type front;
+ *result = arg;
+ if(arg.compare(front(0)) < 0)
+ result->negate();
+}
+
+//
+// These have to implemented by the backend, declared here so that our macro generated code compiles OK.
+//
+template <class T>
+typename enable_if_c<sizeof(T) == 0>::type floor();
+template <class T>
+typename enable_if_c<sizeof(T) == 0>::type ceil();
+template <class T>
+typename enable_if_c<sizeof(T) == 0>::type trunc();
+template <class T>
+typename enable_if_c<sizeof(T) == 0>::type sqrt();
+template <class T>
+typename enable_if_c<sizeof(T) == 0>::type ldexp();
+template <class T>
+typename enable_if_c<sizeof(T) == 0>::type frexp();
+
+}
+
+
+template <class Backend>
+class big_number;
+
+namespace detail{
+
+template<typename Expr>
+struct big_number_exp;
+
+}
+
+#define UNARY_OP_FUNCTOR(func)\
+namespace detail{\
+template <class Backend>\
+struct BOOST_JOIN(func, _funct)\
+{\
+ void operator()(Backend* result, const Backend& arg)const\
+ {\
+ using big_num_default_ops::func;\
+ func(result, arg);\
+ }\
+};\
+\
+}\
+\
+template <class Exp>\
+typename proto::result_of::make_expr<\
+ proto::tag::function\
+ , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<Exp>::type>\
+ , detail::big_number_exp<Exp>\
+>::type const \
+func(const detail::big_number_exp<Exp>& arg)\
+{\
+ return proto::make_expr<proto::tag::function>(\
+ detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<Exp>::type>() \
+ , arg \
+ );\
+}\
+template <class Backend>\
+typename proto::result_of::make_expr<\
+ proto::tag::function\
+ , detail::BOOST_JOIN(func, _funct)<Backend>\
+ , detail::big_number_exp<typename proto::terminal<big_number<Backend>*>::type>\
+>::type const \
+func(const big_number<Backend>& arg)\
+{\
+ return proto::make_expr<proto::tag::function>(\
+ detail::BOOST_JOIN(func, _funct)<Backend>() \
+ , static_cast<const detail::big_number_exp<typename proto::terminal<big_number<Backend>*>::type>&>(arg) \
+ );\
+}
+
+#define BINARY_OP_FUNCTOR(func)\
+namespace detail{\
+template <class Backend>\
+struct BOOST_JOIN(func, _funct)\
+{\
+ template <class A2>\
+ void operator()(Backend* result, const Backend& arg, const A2& a)const\
+ {\
+ using big_num_default_ops::func;\
+ func(result, arg, a);\
+ }\
+};\
+\
+}\
+\
+template <class Exp, class A2>\
+typename proto::result_of::make_expr<\
+ proto::tag::function\
+ , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<Exp>::type>\
+ , detail::big_number_exp<Exp>\
+ , typename proto::result_of::as_child<const A2&>::type\
+>::type const \
+func(const detail::big_number_exp<Exp>& arg, const A2& a)\
+{\
+ return proto::make_expr<proto::tag::function>(\
+ detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<Exp>::type>() \
+ , arg, proto::as_child(a) \
+ );\
+}\
+template <class Backend, class A2>\
+typename proto::result_of::make_expr<\
+ proto::tag::function\
+ , detail::BOOST_JOIN(func, _funct)<Backend>\
+ , detail::big_number_exp<typename proto::terminal<big_number<Backend>*>::type>\
+ , typename proto::result_of::as_child<const A2&>::type\
+>::type const \
+func(const big_number<Backend>& arg, const A2& a)\
+{\
+ return proto::make_expr<proto::tag::function>(\
+ detail::BOOST_JOIN(func, _funct)<Backend>() \
+ , static_cast<const detail::big_number_exp<typename proto::terminal<big_number<Backend>*>::type>&>(arg),\
+ proto::as_child(a)\
+ );\
+}
+
+UNARY_OP_FUNCTOR(abs)
+UNARY_OP_FUNCTOR(fabs)
+UNARY_OP_FUNCTOR(sqrt)
+UNARY_OP_FUNCTOR(floor)
+UNARY_OP_FUNCTOR(ceil)
+UNARY_OP_FUNCTOR(trunc)
+
+BINARY_OP_FUNCTOR(ldexp)
+BINARY_OP_FUNCTOR(frexp)
+
+#undef BINARY_OP_FUNCTOR
+#undef UNARY_OP_FUNCTOR
+
+}} // namespaces
+
+#endif
+

Modified: sandbox/big_number/boost/math/big_number/gmp.hpp
==============================================================================
--- sandbox/big_number/boost/math/big_number/gmp.hpp (original)
+++ sandbox/big_number/boost/math/big_number/gmp.hpp 2011-08-16 14:02:03 EDT (Tue, 16 Aug 2011)
@@ -145,130 +145,45 @@
       mpf_set_str(m_data, s, 10);
       return *this;
    }
- gmp_real_imp& operator += (const gmp_real<digits10>& o)
- {
- mpf_add(m_data, m_data, o.m_data);
- return *this;
- }
- template <class V>
- gmp_real_imp& operator += (V v)
- {
- gmp_real<digits10> d;
- d = v;
- return *this += d;
- }
- gmp_real_imp& operator -= (const gmp_real<digits10>& o)
- {
- mpf_sub(m_data, m_data, o.m_data);
- return *this;
- }
- template <class V>
- gmp_real_imp& operator -= (V v)
- {
- gmp_real<digits10> d;
- d = v;
- return *this -= d;
- }
- gmp_real_imp& operator *= (const gmp_real<digits10>& o)
- {
- mpf_mul(m_data, m_data, o.m_data);
- return *this;
- }
- template <class V>
- gmp_real_imp& operator *= (V v)
- {
- gmp_real<digits10> d;
- d = v;
- return *this *= d;
- }
- gmp_real_imp& operator /= (const gmp_real<digits10>& o)
- {
- mpf_div(m_data, m_data, o.m_data);
- return *this;
- }
- template <class V>
- gmp_real_imp& operator /= (V v)
- {
- gmp_real<digits10> d;
- d = v;
- return *this /= d;
- }
- gmp_real_imp& operator += (unsigned long i)
- {
- mpf_add_ui(m_data, m_data, i);
- return *this;
- }
- gmp_real_imp& operator -= (unsigned long i)
- {
- mpf_sub_ui(m_data, m_data, i);
- return *this;
- }
- gmp_real_imp& operator *= (unsigned long i)
- {
- mpf_mul_ui(m_data, m_data, i);
- return *this;
- }
- gmp_real_imp& operator /= (unsigned long i)
- {
- mpf_div_ui(m_data, m_data, i);
- return *this;
- }
- gmp_real_imp& operator += (long i)
- {
- if(i > 0)
- mpf_add_ui(m_data, m_data, i);
- else
- mpf_sub_ui(m_data, m_data, std::abs(i));
- return *this;
- }
- gmp_real_imp& operator -= (long i)
- {
- if(i > 0)
- mpf_sub_ui(m_data, m_data, i);
- else
- mpf_add_ui(m_data, m_data, std::abs(i));
- return *this;
- }
- gmp_real_imp& operator *= (long i)
- {
- mpf_mul_ui(m_data, m_data, std::abs(i));
- if(i < 0)
- mpf_neg(m_data, m_data);
- return *this;
- }
- gmp_real_imp& operator /= (long i)
- {
- mpf_div_ui(m_data, m_data, std::abs(i));
- if(i < 0)
- mpf_neg(m_data, m_data);
- return *this;
- }
    void swap(gmp_real_imp& o)
    {
       mpf_swap(m_data, o.m_data);
    }
- std::string str(unsigned digits)const
+ std::string str(unsigned digits, bool scientific)const
    {
+ std::string result;
       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, digits, m_data);
- std::string s("0.");
- if(ps[0] == '-')
+ std::ptrdiff_t sl = std::strlen(ps);
+ if(sl == 0)
+ return "0";
+ if(*ps == '-')
+ --sl; // number of digits excluding sign.
+ if(!scientific
+ && (sl <= std::numeric_limits<boost::uintmax_t>::digits10 + 1)
+ && (e >= sl)
+ && (sl <= std::numeric_limits<boost::uintmax_t>::digits10 + 1))
       {
- s.insert(0, ps, 1);
- s += ps + 1;
+ result = ps;
+ result.append(e-sl, '0');
       }
       else
       {
- s += ps;
+ result = ps;
+ if(ps[0] == '-')
+ result.insert(2, 1, '.');
+ else
+ result.insert(1, 1, '.');
+ --e;
+ if(e)
+ result += "e" + lexical_cast<std::string>(e);
       }
- s += "e";
- s += boost::lexical_cast<std::string>(e);
       mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
       (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
- return s;
+ return result;
    }
    ~gmp_real_imp()
    {
@@ -400,74 +315,280 @@
    }
 };
 
+template <unsigned digits10>
+inline void add(gmp_real<digits10>& result, const gmp_real<digits10>& o)
+{
+ mpf_add(result.data(), result.data(), o.data());
+}
+template <unsigned digits10>
+inline void subtract(gmp_real<digits10>& result, const gmp_real<digits10>& o)
+{
+ mpf_sub(result.data(), result.data(), o.data());
+}
+template <unsigned digits10>
+inline void multiply(gmp_real<digits10>& result, const gmp_real<digits10>& o)
+{
+ mpf_mul(result.data(), result.data(), o.data());
+}
+template <unsigned digits10>
+inline void divide(gmp_real<digits10>& result, const gmp_real<digits10>& o)
+{
+ mpf_div(result.data(), result.data(), o.data());
+}
+template <unsigned digits10>
+inline void add(gmp_real<digits10>& result, unsigned long i)
+{
+ mpf_add_ui(result.data(), result.data(), i);
+}
+template <unsigned digits10>
+inline void subtract(gmp_real<digits10>& result, unsigned long i)
+{
+ mpf_sub_ui(result.data(), result.data(), i);
+}
+template <unsigned digits10>
+inline void multiply(gmp_real<digits10>& result, unsigned long i)
+{
+ mpf_mul_ui(result.data(), result.data(), i);
+}
+template <unsigned digits10>
+inline void divide(gmp_real<digits10>& result, unsigned long i)
+{
+ mpf_div_ui(result.data(), result.data(), i);
+}
+template <unsigned digits10>
+inline void add(gmp_real<digits10>& result, long i)
+{
+ if(i > 0)
+ mpf_add_ui(result.data(), result.data(), i);
+ else
+ mpf_sub_ui(result.data(), result.data(), std::abs(i));
+}
+template <unsigned digits10>
+inline void subtract(gmp_real<digits10>& result, long i)
+{
+ if(i > 0)
+ mpf_sub_ui(result.data(), result.data(), i);
+ else
+ mpf_add_ui(result.data(), result.data(), std::abs(i));
+}
+template <unsigned digits10>
+inline void multiply(gmp_real<digits10>& result, long i)
+{
+ mpf_mul_ui(result.data(), result.data(), std::abs(i));
+ if(i < 0)
+ mpf_neg(result.data(), result.data());
+}
+template <unsigned digits10>
+inline void divide(gmp_real<digits10>& result, long i)
+{
+ mpf_div_ui(result.data(), result.data(), std::abs(i));
+ if(i < 0)
+ mpf_neg(result.data(), result.data());
+}
+//
+// Specialised 3 arg versions of the basic operators:
+//
+template <unsigned digits10>
+inline void add(gmp_real<digits10>& a, const gmp_real<digits10>& x, const gmp_real<digits10>& y)
+{
+ mpf_add(a.data(), x.data(), y.data());
+}
+template <unsigned digits10>
+inline void add(gmp_real<digits10>& a, const gmp_real<digits10>& x, unsigned long y)
+{
+ mpf_add_ui(a.data(), x.data(), y);
+}
+template <unsigned digits10>
+inline void add(gmp_real<digits10>& a, const gmp_real<digits10>& x, long y)
+{
+ if(y < 0)
+ mpf_sub_ui(a.data(), x.data(), -y);
+ else
+ mpf_add_ui(a.data(), x.data(), y);
+}
+template <unsigned digits10>
+inline void add(gmp_real<digits10>& a, unsigned long x, const gmp_real<digits10>& y)
+{
+ mpf_add_ui(a.data(), y.data(), x);
+}
+template <unsigned digits10>
+inline void add(gmp_real<digits10>& a, long x, const gmp_real<digits10>& y)
+{
+ if(x < 0)
+ {
+ mpf_ui_sub(a.data(), -x, y.data());
+ mpf_neg(a.data(), a.data());
+ }
+ else
+ mpf_add_ui(a.data(), y.data(), x);
+}
+template <unsigned digits10>
+inline void subtract(gmp_real<digits10>& a, const gmp_real<digits10>& x, const gmp_real<digits10>& y)
+{
+ mpf_sub(a.data(), x.data(), y.data());
+}
+template <unsigned digits10>
+inline void subtract(gmp_real<digits10>& a, const gmp_real<digits10>& x, unsigned long y)
+{
+ mpf_sub_ui(a.data(), x.data(), y);
+}
+template <unsigned digits10>
+inline void subtract(gmp_real<digits10>& a, const gmp_real<digits10>& x, long y)
+{
+ if(y < 0)
+ mpf_add_ui(a.data(), x.data(), -y);
+ else
+ mpf_sub_ui(a.data(), x.data(), y);
+}
+template <unsigned digits10>
+inline void subtract(gmp_real<digits10>& a, unsigned long x, const gmp_real<digits10>& y)
+{
+ mpf_ui_sub(a.data(), x, y.data());
+}
+template <unsigned digits10>
+inline void subtract(gmp_real<digits10>& a, long x, const gmp_real<digits10>& y)
+{
+ if(x < 0)
+ {
+ mpf_add_ui(a.data(), y.data(), -x);
+ mpf_neg(a.data(), a.data());
+ }
+ else
+ mpf_ui_sub(a.data(), x, y.data());
+}
+
+template <unsigned digits10>
+inline void multiply(gmp_real<digits10>& a, const gmp_real<digits10>& x, const gmp_real<digits10>& y)
+{
+ mpf_mul(a.data(), x.data(), y.data());
+}
+template <unsigned digits10>
+inline void multiply(gmp_real<digits10>& a, const gmp_real<digits10>& x, unsigned long y)
+{
+ mpf_mul_ui(a.data(), x.data(), y);
+}
+template <unsigned digits10>
+inline void multiply(gmp_real<digits10>& a, const gmp_real<digits10>& x, long y)
+{
+ if(y < 0)
+ {
+ mpf_mul_ui(a.data(), x.data(), -y);
+ a.negate();
+ }
+ else
+ mpf_mul_ui(a.data(), x.data(), y);
+}
+template <unsigned digits10>
+inline void multiply(gmp_real<digits10>& a, unsigned long x, const gmp_real<digits10>& y)
+{
+ mpf_mul_ui(a.data(), y.data(), x);
+}
+template <unsigned digits10>
+inline void multiply(gmp_real<digits10>& a, long x, const gmp_real<digits10>& y)
+{
+ if(x < 0)
+ {
+ mpf_mul_ui(a.data(), y.data(), -x);
+ mpf_neg(a.data(), a.data());
+ }
+ else
+ mpf_mul_ui(a.data(), y.data(), x);
+}
+
+template <unsigned digits10>
+inline void divide(gmp_real<digits10>& a, const gmp_real<digits10>& x, const gmp_real<digits10>& y)
+{
+ mpf_div(a.data(), x.data(), y.data());
+}
+template <unsigned digits10>
+inline void divide(gmp_real<digits10>& a, const gmp_real<digits10>& x, unsigned long y)
+{
+ mpf_div_ui(a.data(), x.data(), y);
+}
+template <unsigned digits10>
+inline void divide(gmp_real<digits10>& a, const gmp_real<digits10>& x, long y)
+{
+ if(y < 0)
+ {
+ mpf_div_ui(a.data(), x.data(), -y);
+ a.negate();
+ }
+ else
+ mpf_div_ui(a.data(), x.data(), y);
+}
+template <unsigned digits10>
+inline void divide(gmp_real<digits10>& a, unsigned long x, const gmp_real<digits10>& y)
+{
+ mpf_ui_div(a.data(), x, y.data());
+}
+template <unsigned digits10>
+inline void divide(gmp_real<digits10>& a, long x, const gmp_real<digits10>& y)
+{
+ if(x < 0)
+ {
+ mpf_ui_div(a.data(), -x, y.data());
+ mpf_neg(a.data(), a.data());
+ }
+ else
+ mpf_ui_div(a.data(), x, y.data());
+}
+
 //
 // Native non-member operations:
 //
 template <unsigned Digits10>
-big_number<gmp_real<Digits10> > sqrt(const big_number<gmp_real<Digits10> >& val)
+inline void sqrt(gmp_real<Digits10>* result, const gmp_real<Digits10>& val)
 {
- big_number<gmp_real<Digits10> > result;
- mpf_sqrt(result.backend().data(), val.backend().data());
- return result;
+ mpf_sqrt(result->data(), val.data());
 }
+
 template <unsigned Digits10>
-big_number<gmp_real<Digits10> > abs(const big_number<gmp_real<Digits10> >& val)
+inline void abs(gmp_real<Digits10>* result, const gmp_real<Digits10>& val)
 {
- big_number<gmp_real<Digits10> > result;
- mpf_abs(result.backend().data(), val.backend().data());
- return result;
+ mpf_abs(result->data(), val.data());
 }
+
 template <unsigned Digits10>
-big_number<gmp_real<Digits10> > fabs(const big_number<gmp_real<Digits10> >& val)
+inline void fabs(gmp_real<Digits10>* result, const gmp_real<Digits10>& val)
 {
- big_number<gmp_real<Digits10> > result;
- mpf_abs(result.backend().data(), val.backend().data());
- return result;
+ mpf_abs(result->data(), val.data());
 }
 template <unsigned Digits10>
-big_number<gmp_real<Digits10> > ceil(const big_number<gmp_real<Digits10> >& val)
+inline void ceil(gmp_real<Digits10>* result, const gmp_real<Digits10>& val)
 {
- big_number<gmp_real<Digits10> > result;
- mpf_ceil(result.backend().data(), val.backend().data());
- return result;
+ mpf_ceil(result->data(), val.data());
 }
 template <unsigned Digits10>
-big_number<gmp_real<Digits10> > floor(const big_number<gmp_real<Digits10> >& val)
+inline void floor(gmp_real<Digits10>* result, const gmp_real<Digits10>& val)
 {
- big_number<gmp_real<Digits10> > result;
- mpf_floor(result.backend().data(), val.backend().data());
- return result;
+ mpf_floor(result->data(), val.data());
 }
 template <unsigned Digits10>
-big_number<gmp_real<Digits10> > trunc(const big_number<gmp_real<Digits10> >& val)
+inline void trunc(gmp_real<Digits10>* result, const gmp_real<Digits10>& val)
 {
- big_number<gmp_real<Digits10> > result;
- mpf_trunc(result.backend().data(), val.backend().data());
- return result;
+ mpf_trunc(result->data(), val.data());
 }
 template <unsigned Digits10>
-big_number<gmp_real<Digits10> > ldexp(const big_number<gmp_real<Digits10> >& val, long e)
+inline void ldexp(gmp_real<Digits10>* result, const gmp_real<Digits10>& val, long e)
 {
- big_number<gmp_real<Digits10> > result;
    if(e > 0)
- mpf_mul_2exp(result.backend().data(), val.backend().data(), e);
+ mpf_mul_2exp(result->data(), val.data(), e);
    else if(e < 0)
- mpf_div_2exp(result.backend().data(), val.backend().data(), -e);
- return result;
+ mpf_div_2exp(result->data(), val.data(), -e);
 }
 template <unsigned Digits10>
-big_number<gmp_real<Digits10> > frexp(const big_number<gmp_real<Digits10> >& val, int* e)
+inline void frexp(gmp_real<Digits10>* result, const gmp_real<Digits10>& val, int* e)
 {
    long v;
- mpf_get_d_2exp(&v, val.backend().data());
+ mpf_get_d_2exp(&v, val.data());
    *e = v;
- return ldexp(val, -v);
+ return ldexp(result, val, -v);
 }
 template <unsigned Digits10>
-big_number<gmp_real<Digits10> > frexp(const big_number<gmp_real<Digits10> >& val, long* e)
+inline void frexp(gmp_real<Digits10>* result, const gmp_real<Digits10>& val, long* e)
 {
- mpf_get_d_2exp(e, val.backend().data());
- return ldexp(val, -*e);
+ mpf_get_d_2exp(e, val.data());
+ return ldexp(result, val, -*e);
 }
 
 struct gmp_int
@@ -582,163 +703,11 @@
       mpz_set_str(m_data, s, 10);
       return *this;
    }
- gmp_int& operator += (const gmp_int& o)
- {
- mpz_add(m_data, m_data, o.m_data);
- return *this;
- }
- template <class V>
- gmp_int& operator += (V v)
- {
- gmp_int d;
- d = v;
- return *this += d;
- }
- gmp_int& operator -= (const gmp_int& o)
- {
- mpz_sub(m_data, m_data, o.m_data);
- return *this;
- }
- template <class V>
- gmp_int& operator -= (V v)
- {
- gmp_int d;
- d = v;
- return *this -= d;
- }
- gmp_int& operator *= (const gmp_int& o)
- {
- mpz_mul(m_data, m_data, o.m_data);
- return *this;
- }
- template <class V>
- gmp_int& operator *= (V v)
- {
- gmp_int d;
- d = v;
- return *this *= d;
- }
- gmp_int& operator /= (const gmp_int& o)
- {
- mpz_div(m_data, m_data, o.m_data);
- return *this;
- }
- template <class V>
- gmp_int& operator /= (V v)
- {
- gmp_int d;
- d = v;
- return *this /= d;
- }
- gmp_int& operator %= (const gmp_int& o)
- {
- bool neg = mpz_sgn(m_data) < 0;
- bool neg2 = mpz_sgn(o.m_data) < 0;
- mpz_mod(m_data, m_data, o.m_data);
- if(neg)
- {
- if(!neg2)
- negate();
- mpz_add(m_data, m_data, o.m_data);
- if(!neg2)
- negate();
- }
- return *this;
- }
- template <class V>
- gmp_int& operator %= (V v)
- {
- gmp_int d;
- d = v;
- return *this %= d;
- }
- gmp_int& operator += (unsigned long i)
- {
- mpz_add_ui(m_data, m_data, i);
- return *this;
- }
- gmp_int& operator -= (unsigned long i)
- {
- mpz_sub_ui(m_data, m_data, i);
- return *this;
- }
- gmp_int& operator *= (unsigned long i)
- {
- mpz_mul_ui(m_data, m_data, i);
- return *this;
- }
- gmp_int& operator %= (unsigned long i)
- {
- bool neg = mpz_sgn(m_data) < 0;
- mpz_mod_ui(m_data, m_data, i);
- if(neg)
- {
- negate();
- mpz_add_ui(m_data, m_data, i);
- negate();
- }
- return *this;
- }
- gmp_int& operator /= (unsigned long i)
- {
- mpz_div_ui(m_data, m_data, i);
- return *this;
- }
- gmp_int& operator += (long i)
- {
- if(i > 0)
- mpz_add_ui(m_data, m_data, i);
- else
- mpz_sub_ui(m_data, m_data, std::abs(i));
- return *this;
- }
- gmp_int& operator -= (long i)
- {
- if(i > 0)
- mpz_sub_ui(m_data, m_data, i);
- else
- mpz_add_ui(m_data, m_data, std::abs(i));
- return *this;
- }
- gmp_int& operator *= (long i)
- {
- mpz_mul_ui(m_data, m_data, std::abs(i));
- if(i < 0)
- mpz_neg(m_data, m_data);
- return *this;
- }
- gmp_int& operator %= (long i)
- {
- bool neg = mpz_sgn(m_data) < 0;
- bool neg2 = i < 0;
- mpz_mod_ui(m_data, m_data, std::abs(i));
- if(neg)
- {
- if(!neg2)
- {
- negate();
- mpz_add_ui(m_data, m_data, std::abs(i));
- negate();
- }
- else
- {
- mpz_sub_ui(m_data, m_data, std::abs(i));
- }
- }
- return *this;
- }
- gmp_int& operator /= (long i)
- {
- mpz_div_ui(m_data, m_data, std::abs(i));
- if(i < 0)
- mpz_neg(m_data, m_data);
- return *this;
- }
    void swap(gmp_int& o)
    {
       mpz_swap(m_data, o.m_data);
    }
- std::string str(unsigned)const
+ std::string str(unsigned /*digits*/, bool /*scientific*/)const
    {
       void *(*alloc_func_ptr) (size_t);
       void *(*realloc_func_ptr) (void *, size_t, size_t);
@@ -776,10 +745,218 @@
       d = v;
       return compare(d);
    }
+ mpz_t& data() { return m_data; }
+ const mpz_t& data()const { return m_data; }
 protected:
    mpz_t m_data;
 };
 
+inline void add(gmp_int& t, const gmp_int& o)
+{
+ mpz_add(t.data(), t.data(), o.data());
+}
+inline void subtract(gmp_int& t, const gmp_int& o)
+{
+ mpz_sub(t.data(), t.data(), o.data());
+}
+inline void multiply(gmp_int& t, const gmp_int& o)
+{
+ mpz_mul(t.data(), t.data(), o.data());
+}
+inline void divide(gmp_int& t, const gmp_int& o)
+{
+ mpz_div(t.data(), t.data(), o.data());
+}
+inline void modulus(gmp_int& t, const gmp_int& o)
+{
+ bool neg = mpz_sgn(t.data()) < 0;
+ bool neg2 = mpz_sgn(o.data()) < 0;
+ mpz_mod(t.data(), t.data(), o.data());
+ if(neg)
+ {
+ if(!neg2)
+ t.negate();
+ mpz_add(t.data(), t.data(), o.data());
+ if(!neg2)
+ t.negate();
+ }
+}
+inline void add(gmp_int& t, unsigned long i)
+{
+ mpz_add_ui(t.data(), t.data(), i);
+}
+inline void subtract(gmp_int& t, unsigned long i)
+{
+ mpz_sub_ui(t.data(), t.data(), i);
+}
+inline void multiply(gmp_int& t, unsigned long i)
+{
+ mpz_mul_ui(t.data(), t.data(), i);
+}
+inline void modulus(gmp_int& t, unsigned long i)
+{
+ bool neg = mpz_sgn(t.data()) < 0;
+ mpz_mod_ui(t.data(), t.data(), i);
+ if(neg)
+ {
+ t.negate();
+ mpz_add_ui(t.data(), t.data(), i);
+ t.negate();
+ }
+}
+inline void divide(gmp_int& t, unsigned long i)
+{
+ mpz_div_ui(t.data(), t.data(), i);
+}
+inline void add(gmp_int& t, long i)
+{
+ if(i > 0)
+ mpz_add_ui(t.data(), t.data(), i);
+ else
+ mpz_sub_ui(t.data(), t.data(), -i);
+}
+inline void subtract(gmp_int& t, long i)
+{
+ if(i > 0)
+ mpz_sub_ui(t.data(), t.data(), i);
+ else
+ mpz_add_ui(t.data(), t.data(), -i);
+}
+inline void multiply(gmp_int& t, long i)
+{
+ mpz_mul_ui(t.data(), t.data(), std::abs(i));
+ if(i < 0)
+ mpz_neg(t.data(), t.data());
+}
+inline void modulus(gmp_int& t, long i)
+{
+ bool neg = mpz_sgn(t.data()) < 0;
+ bool neg2 = i < 0;
+ mpz_mod_ui(t.data(), t.data(), std::abs(i));
+ if(neg)
+ {
+ if(!neg2)
+ {
+ t.negate();
+ mpz_add_ui(t.data(), t.data(), std::abs(i));
+ t.negate();
+ }
+ else
+ {
+ mpz_sub_ui(t.data(), t.data(), std::abs(i));
+ }
+ }
+}
+inline void divide(gmp_int& t, long i)
+{
+ mpz_div_ui(t.data(), t.data(), std::abs(i));
+ if(i < 0)
+ mpz_neg(t.data(), t.data());
+}
+
+inline void add(gmp_int& t, const gmp_int& p, const gmp_int& o)
+{
+ mpz_add(t.data(), p.data(), o.data());
+}
+inline void subtract(gmp_int& t, const gmp_int& p, const gmp_int& o)
+{
+ mpz_sub(t.data(), p.data(), o.data());
+}
+inline void multiply(gmp_int& t, const gmp_int& p, const gmp_int& o)
+{
+ mpz_mul(t.data(), p.data(), o.data());
+}
+inline void divide(gmp_int& t, const gmp_int& p, const gmp_int& o)
+{
+ mpz_div(t.data(), p.data(), o.data());
+}
+inline void modulus(gmp_int& t, const gmp_int& p, const gmp_int& o)
+{
+ bool neg = mpz_sgn(p.data()) < 0;
+ bool neg2 = mpz_sgn(o.data()) < 0;
+ mpz_mod(t.data(), p.data(), o.data());
+ if(neg)
+ {
+ if(!neg2)
+ t.negate();
+ mpz_add(t.data(), t.data(), o.data());
+ if(!neg2)
+ t.negate();
+ }
+}
+inline void add(gmp_int& t, const gmp_int& p, unsigned long i)
+{
+ mpz_add_ui(t.data(), p.data(), i);
+}
+inline void subtract(gmp_int& t, const gmp_int& p, unsigned long i)
+{
+ mpz_sub_ui(t.data(), p.data(), i);
+}
+inline void multiply(gmp_int& t, const gmp_int& p, unsigned long i)
+{
+ mpz_mul_ui(t.data(), p.data(), i);
+}
+inline void modulus(gmp_int& t, const gmp_int& p, unsigned long i)
+{
+ bool neg = mpz_sgn(p.data()) < 0;
+ mpz_mod_ui(t.data(), p.data(), i);
+ if(neg)
+ {
+ t.negate();
+ mpz_add_ui(t.data(), t.data(), i);
+ t.negate();
+ }
+}
+inline void divide(gmp_int& t, const gmp_int& p, unsigned long i)
+{
+ mpz_div_ui(t.data(), p.data(), i);
+}
+inline void add(gmp_int& t, const gmp_int& p, long i)
+{
+ if(i > 0)
+ mpz_add_ui(t.data(), p.data(), i);
+ else
+ mpz_sub_ui(t.data(), p.data(), -i);
+}
+inline void subtract(gmp_int& t, const gmp_int& p, long i)
+{
+ if(i > 0)
+ mpz_sub_ui(t.data(), p.data(), i);
+ else
+ mpz_add_ui(t.data(), p.data(), -i);
+}
+inline void multiply(gmp_int& t, const gmp_int& p, long i)
+{
+ mpz_mul_ui(t.data(), p.data(), std::abs(i));
+ if(i < 0)
+ mpz_neg(t.data(), t.data());
+}
+inline void modulus(gmp_int& t, const gmp_int& p, long i)
+{
+ bool neg = mpz_sgn(p.data()) < 0;
+ bool neg2 = i < 0;
+ mpz_mod_ui(t.data(), p.data(), std::abs(i));
+ if(neg)
+ {
+ if(!neg2)
+ {
+ t.negate();
+ mpz_add_ui(t.data(), t.data(), std::abs(i));
+ t.negate();
+ }
+ else
+ {
+ mpz_sub_ui(t.data(), t.data(), std::abs(i));
+ }
+ }
+}
+inline void divide(gmp_int& t, const gmp_int& p, long i)
+{
+ mpz_div_ui(t.data(), p.data(), std::abs(i));
+ if(i < 0)
+ mpz_neg(t.data(), t.data());
+}
+
 template<>
 struct is_extended_integer<gmp_int> : public mpl::true_ {};
 

Modified: sandbox/big_number/boost/math/concepts/big_number_architypes.hpp
==============================================================================
--- sandbox/big_number/boost/math/concepts/big_number_architypes.hpp (original)
+++ sandbox/big_number/boost/math/concepts/big_number_architypes.hpp 2011-08-16 14:02:03 EDT (Tue, 16 Aug 2011)
@@ -18,9 +18,9 @@
 
 struct big_number_backend_real_architype
 {
- typedef mpl::list<int, long long> signed_types;
- typedef mpl::list<unsigned, unsigned long long> unsigned_types;
- typedef mpl::list<double, long double> real_types;
+ typedef mpl::list<long long> signed_types;
+ typedef mpl::list<unsigned long long> unsigned_types;
+ typedef mpl::list<long double> real_types;
 
    big_number_backend_real_architype()
    {
@@ -49,24 +49,6 @@
       std::cout << "Int Assignment (" << i << ")" << std::endl;
       return *this;
    }
- big_number_backend_real_architype& operator = (unsigned i)
- {
- m_value = i;
- std::cout << "UInt Assignment (" << i << ")" << std::endl;
- return *this;
- }
- big_number_backend_real_architype& operator = (int i)
- {
- m_value = i;
- std::cout << "Int Assignment (" << i << ")" << std::endl;
- return *this;
- }
- big_number_backend_real_architype& operator = (double d)
- {
- m_value = d;
- std::cout << "double Assignment (" << d << ")" << std::endl;
- return *this;
- }
    big_number_backend_real_architype& operator = (long double d)
    {
       m_value = d;
@@ -79,182 +61,29 @@
       std::cout << "const char* Assignment (" << s << ")" << std::endl;
       return *this;
    }
- big_number_backend_real_architype& operator += (const big_number_backend_real_architype& o)
- {
- std::cout << "Addition (" << m_value << " += " << o.m_value << ")" << std::endl;
- m_value += o.m_value;
- return *this;
- }
- big_number_backend_real_architype& operator -= (const big_number_backend_real_architype& o)
- {
- std::cout << "Subtraction (" << m_value << " -= " << o.m_value << ")" << std::endl;
- m_value -= o.m_value;
- return *this;
- }
- big_number_backend_real_architype& operator *= (const big_number_backend_real_architype& o)
- {
- std::cout << "Multiplication (" << m_value << " *= " << o.m_value << ")" << std::endl;
- m_value *= o.m_value;
- return *this;
- }
- big_number_backend_real_architype& operator /= (const big_number_backend_real_architype& o)
- {
- std::cout << "Division (" << m_value << " /= " << o.m_value << ")" << std::endl;
- m_value /= o.m_value;
- return *this;
- }
- big_number_backend_real_architype& operator += (boost::uintmax_t i)
- {
- std::cout << "UIntmax_t Addition (" << m_value << " += " << i << ")" << std::endl;
- m_value += i;
- return *this;
- }
- big_number_backend_real_architype& operator -= (boost::uintmax_t i)
- {
- std::cout << "UIntmax_t Subtraction (" << m_value << " -= " << i << ")" << std::endl;
- m_value -= i;
- return *this;
- }
- big_number_backend_real_architype& operator *= (boost::uintmax_t i)
- {
- std::cout << "UIntmax_t Multiplication (" << m_value << " *= " << i << ")" << std::endl;
- m_value *= i;
- return *this;
- }
- big_number_backend_real_architype& operator /= (boost::uintmax_t i)
- {
- std::cout << "UIntmax_t Division (" << m_value << " /= " << i << ")" << std::endl;
- m_value /= i;
- return *this;
- }
- big_number_backend_real_architype& operator += (boost::intmax_t i)
- {
- std::cout << "Intmax_t Addition (" << m_value << " += " << i << ")" << std::endl;
- m_value += i;
- return *this;
- }
- big_number_backend_real_architype& operator -= (boost::intmax_t i)
- {
- std::cout << "Intmax_t Subtraction (" << m_value << " -= " << i << ")" << std::endl;
- m_value -= i;
- return *this;
- }
- big_number_backend_real_architype& operator *= (boost::intmax_t i)
- {
- std::cout << "Intmax_t Multiplication (" << m_value << " *= " << i << ")" << std::endl;
- m_value *= i;
- return *this;
- }
- big_number_backend_real_architype& operator /= (boost::intmax_t i)
- {
- std::cout << "Intmax_t Division (" << m_value << " /= " << i << ")" << std::endl;
- m_value /= i;
- return *this;
- }
- big_number_backend_real_architype& operator += (unsigned i)
- {
- std::cout << "UInt Addition (" << m_value << " += " << i << ")" << std::endl;
- m_value += i;
- return *this;
- }
- big_number_backend_real_architype& operator -= (unsigned i)
- {
- std::cout << "UInt Subtraction (" << m_value << " -= " << i << ")" << std::endl;
- m_value -= i;
- return *this;
- }
- big_number_backend_real_architype& operator *= (unsigned i)
- {
- std::cout << "UInt Multiplication (" << m_value << " *= " << i << ")" << std::endl;
- m_value *= i;
- return *this;
- }
- big_number_backend_real_architype& operator /= (unsigned i)
- {
- std::cout << "UInt Division (" << m_value << " /= " << i << ")" << std::endl;
- m_value /= i;
- return *this;
- }
- big_number_backend_real_architype& operator += (int i)
- {
- std::cout << "Int Addition (" << m_value << " += " << i << ")" << std::endl;
- m_value += i;
- return *this;
- }
- big_number_backend_real_architype& operator -= (int i)
- {
- std::cout << "Int Subtraction (" << m_value << " -= " << i << ")" << std::endl;
- m_value -= i;
- return *this;
- }
- big_number_backend_real_architype& operator *= (int i)
- {
- std::cout << "Int Multiplication (" << m_value << " *= " << i << ")" << std::endl;
- m_value *= i;
- return *this;
- }
- big_number_backend_real_architype& operator /= (int i)
- {
- std::cout << "Int Division (" << m_value << " /= " << i << ")" << std::endl;
- m_value /= i;
- return *this;
- }
- big_number_backend_real_architype& operator += (double d)
- {
- std::cout << "double Addition (" << m_value << " += " << d << ")" << std::endl;
- m_value += d;
- return *this;
- }
- big_number_backend_real_architype& operator -= (double d)
- {
- std::cout << "double Subtraction (" << m_value << " -= " << d << ")" << std::endl;
- m_value -= d;
- return *this;
- }
- big_number_backend_real_architype& operator *= (double d)
- {
- std::cout << "double Multiplication (" << m_value << " *= " << d << ")" << std::endl;
- m_value *= d;
- return *this;
- }
- big_number_backend_real_architype& operator /= (double d)
- {
- std::cout << "double Division (" << m_value << " /= " << d << ")" << std::endl;
- m_value /= d;
- return *this;
- }
- big_number_backend_real_architype& operator += (long double d)
- {
- std::cout << "long double Addition (" << m_value << " += " << d << ")" << std::endl;
- m_value += d;
- return *this;
- }
- big_number_backend_real_architype& operator -= (long double d)
- {
- std::cout << "long double Subtraction (" << m_value << " -= " << d << ")" << std::endl;
- m_value -= d;
- return *this;
- }
- big_number_backend_real_architype& operator *= (long double d)
- {
- std::cout << "long double Multiplication (" << m_value << " *= " << d << ")" << std::endl;
- m_value *= d;
- return *this;
- }
- big_number_backend_real_architype& operator /= (long double d)
- {
- std::cout << "long double Division (" << m_value << " /= " << d << ")" << std::endl;
- m_value /= d;
- return *this;
- }
    void swap(big_number_backend_real_architype& o)
    {
       std::cout << "Swapping (" << m_value << " with " << o.m_value << ")" << std::endl;
       std::swap(m_value, o.m_value);
    }
- std::string str(unsigned)const
+ std::string str(unsigned digits, bool scientific)const
    {
- std::string s(boost::lexical_cast<std::string>(m_value));
+ std::stringstream ss;
+ if(scientific)
+ ss.setf(ss.scientific);
+ if(digits)
+ ss.precision(digits);
+ else
+ ss.precision(std::numeric_limits<long double>::digits10 + 2);
+ boost::intmax_t i = m_value;
+ boost::uintmax_t u = m_value;
+ if(!scientific && m_value == i)
+ ss << i;
+ else if(!scientific && m_value == u)
+ ss << u;
+ else
+ ss << m_value;
+ std::string s = ss.str();
       std::cout << "Converting to string (" << s << ")" << std::endl;
       return s;
    }
@@ -268,16 +97,6 @@
       std::cout << "Comparison" << std::endl;
       return m_value > o.m_value ? 1 : (m_value < o.m_value ? -1 : 0);
    }
- int compare(int i)const
- {
- std::cout << "Comparison with int" << std::endl;
- return m_value > i ? 1 : (m_value < i ? -1 : 0);
- }
- int compare(unsigned i)const
- {
- std::cout << "Comparison with unsigned" << std::endl;
- return m_value > i ? 1 : (m_value < i ? -1 : 0);
- }
    int compare(boost::intmax_t i)const
    {
       std::cout << "Comparison with int" << std::endl;
@@ -288,20 +107,35 @@
       std::cout << "Comparison with unsigned" << std::endl;
       return m_value > i ? 1 : (m_value < i ? -1 : 0);
    }
- int compare(double d)const
- {
- std::cout << "Comparison with double" << std::endl;
- return m_value > d ? 1 : (m_value < d ? -1 : 0);
- }
    int compare(long double d)const
    {
       std::cout << "Comparison with long double" << std::endl;
       return m_value > d ? 1 : (m_value < d ? -1 : 0);
    }
-private:
    long double m_value;
 };
 
+inline void add(big_number_backend_real_architype& result, const big_number_backend_real_architype& o)
+{
+ std::cout << "Addition (" << result.m_value << " += " << o.m_value << ")" << std::endl;
+ result.m_value += o.m_value;
+}
+inline void subtract(big_number_backend_real_architype& result, const big_number_backend_real_architype& o)
+{
+ std::cout << "Subtraction (" << result.m_value << " -= " << o.m_value << ")" << std::endl;
+ result.m_value -= o.m_value;
+}
+inline void multiply(big_number_backend_real_architype& result, const big_number_backend_real_architype& o)
+{
+ std::cout << "Multiplication (" << result.m_value << " *= " << o.m_value << ")" << std::endl;
+ result.m_value *= o.m_value;
+}
+inline void divide(big_number_backend_real_architype& result, const big_number_backend_real_architype& o)
+{
+ std::cout << "Division (" << result.m_value << " /= " << o.m_value << ")" << std::endl;
+ result.m_value /= o.m_value;
+}
+
 typedef boost::math::big_number<big_number_backend_real_architype> big_number_real_architype;
 
 }}} // namespaces

Modified: sandbox/big_number/libs/math/test/linpack-benchmark.cpp
==============================================================================
--- sandbox/big_number/libs/math/test/linpack-benchmark.cpp (original)
+++ sandbox/big_number/libs/math/test/linpack-benchmark.cpp 2011-08-16 14:02:03 EDT (Tue, 16 Aug 2011)
@@ -18,6 +18,7 @@
 #include <iostream>
 #include <iomanip>
 #include <cmath>
+
 #ifdef TEST_BIG_NUMBER
 #include <boost/math/big_number/gmp.hpp>
 typedef boost::math::mpf_real_100 real_type;

Modified: sandbox/big_number/libs/math/test/test_arithmetic.cpp
==============================================================================
--- sandbox/big_number/libs/math/test/test_arithmetic.cpp (original)
+++ sandbox/big_number/libs/math/test/test_arithmetic.cpp 2011-08-16 14:02:03 EDT (Tue, 16 Aug 2011)
@@ -50,6 +50,16 @@
    BOOST_TEST(a % -7 == 20 % -7);
    BOOST_TEST(-a % 7u == -20 % 7);
 
+ b = -b;
+ BOOST_TEST(a % b == 20 % -7);
+ a = -a;
+ BOOST_TEST(a % b == -20 % -7);
+ BOOST_TEST(a % -7 == -20 % -7);
+ b = 7;
+ BOOST_TEST(a % b == -20 % 7);
+ BOOST_TEST(a % 7 == -20 % 7);
+ BOOST_TEST(a % 7u == -20 % 7);
+
    a = 20;
    a %= b;
    BOOST_TEST(a == 20 % 7);
@@ -83,6 +93,7 @@
 template <class Real>
 void test_real_ops(const boost::mpl::true_&)
 {
+#if defined(TEST_MPF) || defined(TEST_MPF_50)
    std::cout << "Root2 = " << sqrt(Real(2)) << std::endl;
    BOOST_TEST(abs(Real(2)) == 2);
    BOOST_TEST(abs(Real(-2)) == 2);
@@ -92,12 +103,8 @@
    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:
    //
@@ -108,6 +115,7 @@
    Real r = frexp(v, &exp);
    BOOST_TEST(r == 0.5);
    BOOST_TEST(exp == 10);
+ BOOST_TEST(v == 512);
    v = 1 / v;
    r = frexp(v, &exp);
    BOOST_TEST(r == 0.5);
@@ -115,9 +123,24 @@
 #endif
 }
 
+template <class T>
+struct lexical_cast_target_type
+{
+ typedef typename boost::mpl::if_<
+ boost::is_signed<T>,
+ boost::intmax_t,
+ typename boost::mpl::if_<
+ boost::is_unsigned<T>,
+ boost::uintmax_t,
+ T
+ >::type
+ >::type type;
+};
+
 template <class Real, class Num>
 void test_negative_mixed(boost::mpl::true_ const&)
 {
+ typedef typename lexical_cast_target_type<Num>::type target_type;
    std::cout << "Testing mixed arithmetic with type: " << typeid(Real).name() << " and " << typeid(Num).name() << std::endl;
    Num n1 = -static_cast<Num>(1uLL << (std::numeric_limits<Num>::digits - 1));
    Num n2 = -1;
@@ -133,10 +156,10 @@
    BOOST_TEST(n2 == Real(n2));
    BOOST_TEST(n3 == Real(n3));
    BOOST_TEST(n4 == Real(n4));
- BOOST_TEST(n1 == boost::lexical_cast<long double>(Real(n1)));
- BOOST_TEST(n2 == boost::lexical_cast<long double>(Real(n2)));
- BOOST_TEST(n3 == boost::lexical_cast<long double>(Real(n3)));
- BOOST_TEST(n4 == boost::lexical_cast<long double>(Real(n4)));
+ BOOST_TEST(n1 == boost::lexical_cast<target_type>(Real(n1).str(0, boost::is_floating_point<Num>::value)));
+ BOOST_TEST(n2 == boost::lexical_cast<target_type>(Real(n2).str(0, boost::is_floating_point<Num>::value)));
+ BOOST_TEST(n3 == boost::lexical_cast<target_type>(Real(n3).str(0, boost::is_floating_point<Num>::value)));
+ BOOST_TEST(n4 == boost::lexical_cast<target_type>(Real(n4).str(0, boost::is_floating_point<Num>::value)));
    // Assignment:
    Real r(0);
    BOOST_TEST(r != n1);
@@ -172,6 +195,21 @@
    BOOST_TEST(Real(r / n5) == n1 / n5);
    r /= n5;
    BOOST_TEST(r == n1 / n5);
+ //
+ // Extra cases for full coverage:
+ //
+ r = Real(n4) + n5;
+ BOOST_TEST(r == n4 + n5);
+ r = n4 + Real(n5);
+ BOOST_TEST(r == n4 + n5);
+ r = Real(n4) - n5;
+ BOOST_TEST(r == n4 - n5);
+ r = n4 - Real(n5);
+ BOOST_TEST(r == n4 - n5);
+ r = n4 * Real(n5);
+ BOOST_TEST(r == n4 * n5);
+ r = (4 * n4) / Real(4);
+ BOOST_TEST(r == n4);
 }
 
 template <class Real, class Num>
@@ -182,6 +220,7 @@
 template <class Real, class Num>
 void test_mixed()
 {
+ typedef typename lexical_cast_target_type<Num>::type target_type;
    std::cout << "Testing mixed arithmetic with type: " << typeid(Real).name() << " and " << typeid(Num).name() << std::endl;
    Num n1 = static_cast<Num>(1uLL << (std::numeric_limits<Num>::digits - 1));
    Num n2 = 1;
@@ -197,10 +236,10 @@
    BOOST_TEST(n2 == Real(n2));
    BOOST_TEST(n3 == Real(n3));
    BOOST_TEST(n4 == Real(n4));
- BOOST_TEST(n1 == boost::lexical_cast<long double>(Real(n1)));
- BOOST_TEST(n2 == boost::lexical_cast<long double>(Real(n2)));
- BOOST_TEST(n3 == boost::lexical_cast<long double>(Real(n3)));
- BOOST_TEST(n4 == boost::lexical_cast<long double>(Real(n4)));
+ BOOST_TEST(n1 == boost::lexical_cast<target_type>(Real(n1).str(0, boost::is_floating_point<Num>::value)));
+ BOOST_TEST(n2 == boost::lexical_cast<target_type>(Real(n2).str(0, boost::is_floating_point<Num>::value)));
+ BOOST_TEST(n3 == boost::lexical_cast<target_type>(Real(n3).str(0, boost::is_floating_point<Num>::value)));
+ BOOST_TEST(n4 == boost::lexical_cast<target_type>(Real(n4).str(0, boost::is_floating_point<Num>::value)));
    // Assignment:
    Real r(0);
    BOOST_TEST(r != n1);
@@ -237,6 +276,18 @@
    r /= n5;
    BOOST_TEST(r == n1 / n5);
 
+ //
+ // special cases for full coverage:
+ //
+ r = n5 + Real(n4);
+ BOOST_TEST(r == n4 + n5);
+ r = n4 - Real(n5);
+ BOOST_TEST(r == n4 - n5);
+ r = n4 * Real(n5);
+ BOOST_TEST(r == n4 * n5);
+ r = (4 * n4) / Real(4);
+ BOOST_TEST(r == n4);
+
    test_negative_mixed<Real, Num>(boost::mpl::bool_<std::numeric_limits<Num>::is_signed>());
 }
 
@@ -440,6 +491,28 @@
    BOOST_TEST(ac == 16);
 #endif
    //
+ // simple tests with immediate values, these calls can be optimised in many backends:
+ //
+ ac = a + b;
+ BOOST_TEST(ac == 72);
+ ac = a + +b;
+ BOOST_TEST(ac == 72);
+ ac = +a + b;
+ BOOST_TEST(ac == 72);
+ ac = +a + +b;
+ BOOST_TEST(ac == 72);
+ ac = a + -b;
+ BOOST_TEST(ac == 8 - 64);
+ ac = -a + b;
+ BOOST_TEST(ac == -8+64);
+ ac = -a + -b;
+ BOOST_TEST(ac == -72);
+ ac = a + - + -b; // lots of unary operators!!
+ BOOST_TEST(ac == 72);
+ ac = a;
+ ac = b / ac;
+ BOOST_TEST(ac == b / a);
+ //
    // Comparisons:
    //
    BOOST_TEST((a == b) == false);


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