$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r73607 - in sandbox/big_number: . boost boost/math boost/math/big_number boost/math/concepts libs libs/math libs/math/test
From: john_at_[hidden]
Date: 2011-08-08 05:21:21
Author: johnmaddock
Date: 2011-08-08 05:21:20 EDT (Mon, 08 Aug 2011)
New Revision: 73607
URL: http://svn.boost.org/trac/boost/changeset/73607
Log:
Initial checkin of experimental bignum type.
Added:
   sandbox/big_number/
   sandbox/big_number/boost/
   sandbox/big_number/boost/math/
   sandbox/big_number/boost/math/big_number/
   sandbox/big_number/boost/math/big_number.hpp   (contents, props changed)
   sandbox/big_number/boost/math/big_number/gmp.hpp   (contents, props changed)
   sandbox/big_number/boost/math/concepts/
   sandbox/big_number/boost/math/concepts/big_number_architypes.hpp   (contents, props changed)
   sandbox/big_number/libs/
   sandbox/big_number/libs/math/
   sandbox/big_number/libs/math/test/
   sandbox/big_number/libs/math/test/big_number_concept_check.cpp   (contents, props changed)
   sandbox/big_number/libs/math/test/test_arithmetic.cpp   (contents, props changed)
Added: sandbox/big_number/boost/math/big_number.hpp
==============================================================================
--- (empty file)
+++ sandbox/big_number/boost/math/big_number.hpp	2011-08-08 05:21:20 EDT (Mon, 08 Aug 2011)
@@ -0,0 +1,1165 @@
+///////////////////////////////////////////////////////////////////////////////
+//  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_EXTENDED_REAL_HPP
+#define BOOST_MATH_EXTENDED_REAL_HPP
+
+#include <boost/proto/proto.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/mpl/max.hpp>
+#include <boost/mpl/plus.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/assert.hpp>
+#include <boost/type_traits/remove_pointer.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;
+   typedef big_number<Backend> self_type;
+public:
+   big_number()
+   {
+      proto::value(*this) = this;
+      BOOST_ASSERT(proto::value(*this) == this);
+   }
+   big_number(const big_number& e) : m_backend(e.m_backend)
+   {
+      proto::value(*this) = this;
+      BOOST_ASSERT(proto::value(*this) == this);
+   }
+   template <class V>
+   big_number(V v, typename enable_if<mpl::or_<boost::is_arithmetic<V>, is_same<std::string, V>, is_convertible<V, const char*> > >::type* dummy1 = 0)
+   {
+      proto::value(*this) = this;
+      BOOST_ASSERT(proto::value(*this) == this);
+      m_backend = canonical_value(v);
+   }
+   /*
+   big_number(unsigned digits10, typename enable_if_c<false == Backend::is_fixed>::type* dummy = 0)
+      : base_type(digits10)
+   {
+      proto::value(*this) = this;
+      BOOST_ASSERT(proto::value(*this) == this);
+   }*/
+   big_number(const big_number& e, unsigned digits10) : m_backend(e.m_backend, digits10)
+   {
+      proto::value(*this) = this;
+      BOOST_ASSERT(proto::value(*this) == this);
+   }
+   template <class V>
+   big_number(V v, unsigned digits10, typename enable_if<mpl::or_<boost::is_arithmetic<V>, is_same<std::string, V>, is_convertible<V, const char*> > >::type* dummy1 = 0)
+      : base_type(digits10)
+   {
+      proto::value(*this) = this;
+      BOOST_ASSERT(proto::value(*this) == this);
+      m_backend = canonical_value(v);
+   }
+
+   template <class Exp>
+   big_number& operator=(const detail::big_number_exp<Exp>& e)
+   {
+      do_assign(e, typename proto::tag_of<Exp>::type());
+      return *this;
+   }
+
+   big_number& operator=(const big_number& e)
+   {
+      m_backend = e.m_backend;
+      return *this;
+   }
+
+   template <class V>
+   typename enable_if<mpl::or_<boost::is_arithmetic<V>, is_same<std::string, V>, is_convertible<V, const char*> >, big_number<Backend>& >::type 
+      operator=(const V& v)
+   {
+      m_backend = canonical_value(v);
+      return *this;
+   }
+
+   template <class Exp>
+   big_number(const detail::big_number_exp<Exp>& e)
+   {
+      proto::value(*this) = this;
+      BOOST_ASSERT(proto::value(*this) == this);
+      do_assign(e, typename proto::tag_of<Exp>::type());
+   }
+
+   template <class Exp>
+   big_number& operator+=(const detail::big_number_exp<Exp>& e)
+   {
+      // Create a copy if e contains this, but not if we're just doing a
+      //    x *= x
+      if(contains_self(e) && !is_self(e))
+      {
+         self_type temp(e);
+         do_add(temp, typename proto::tag_of<self_type>::type());
+      }
+      else
+      {
+         do_add(e, typename proto::tag_of<Exp>::type());
+      }
+      return *this;
+   }
+
+   template <class V>
+   typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type 
+      operator+=(const V& v)
+   {
+      do_add_value(canonical_value(v), mpl::false_());
+      return *this;
+   }
+
+   template <class Exp>
+   big_number& operator-=(const detail::big_number_exp<Exp>& e)
+   {
+      // Create a copy if e contains this, but not if we're just doing a
+      if(contains_self(e))
+      {
+         self_type temp(e);
+         do_subtract(temp, typename proto::tag_of<self_type>::type());
+      }
+      else
+      {
+         do_subtract(e, typename proto::tag_of<Exp>::type());
+      }
+      return *this;
+   }
+
+   template <class V>
+   typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type 
+      operator-=(const V& v)
+   {
+      do_subtract_value(canonical_value(v), mpl::false_());
+      return *this;
+   }
+
+   template <class Exp>
+   big_number& operator*=(const detail::big_number_exp<Exp>& e)
+   {
+      // Create a temporary if the RHS references *this, but not
+      // if we're just doing an   x += x;
+      if(contains_self(e) && !is_self(e))
+      {
+         self_type temp(e);
+         do_multiplies(temp, typename proto::tag_of<self_type>::type());
+      }
+      else
+      {
+         do_multiplies(e, typename proto::tag_of<Exp>::type());
+      }
+      return *this;
+   }
+
+   template <class V>
+   typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type 
+      operator*=(const V& v)
+   {
+      do_multiplies_value(canonical_value(v), mpl::false_());
+      return *this;
+   }
+
+   template <class Exp>
+   big_number& operator%=(const detail::big_number_exp<Exp>& e)
+   {
+      BOOST_STATIC_ASSERT_MSG(is_extended_integer<Backend>::value, "The modulus operation is only valid for integer types");
+      // Create a temporary if the RHS references *this:
+      if(contains_self(e))
+      {
+         self_type temp(e);
+         do_modulus(temp, typename proto::tag_of<self_type>::type());
+      }
+      else
+      {
+         do_modulus(e, typename proto::tag_of<Exp>::type());
+      }
+      return *this;
+   }
+
+   template <class V>
+   typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type 
+      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_());
+      return *this;
+   }
+
+   template <class Exp>
+   big_number& operator/=(const detail::big_number_exp<Exp>& e)
+   {
+      // Create a temporary if the RHS references *this:
+      if(contains_self(e))
+      {
+         self_type temp(e);
+         do_divide(temp, typename proto::tag_of<self_type>::type());
+      }
+      else
+      {
+         do_divide(e, typename proto::tag_of<Exp>::type());
+      }
+      return *this;
+   }
+
+   template <class V>
+   typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type 
+      operator/=(const V& v)
+   {
+      do_divide_value(canonical_value(v), mpl::false_());
+      return *this;
+   }
+
+   //
+   // String conversion functions:
+   //
+   std::string str()const
+   {
+      return m_backend.str();
+   }
+   //
+   // Default precision:
+   //
+   static unsigned default_precision()
+   {
+      return Backend::default_precision();
+   }
+   static void default_precision(unsigned digits10)
+   {
+      Backend::default_precision(digits10);
+   }
+   unsigned precision()const
+   {
+      return m_backend.precision();
+   }
+   void precision(unsigned digits10)
+   {
+      m_backend.precision(digits10);
+   }
+   //
+   // Comparison:
+   //
+   int compare(const big_number<Backend>& o)const
+   {
+      return m_backend.compare(o.m_backend);
+   }
+   template <class V>
+   typename enable_if<is_arithmetic<V>, int>::type compare(const V& o)const
+   {
+      return m_backend.compare(canonical_value(o));
+   }
+private:
+   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());
+   }
+
+   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());
+      m_backend.negate();
+   }
+
+   template <class Exp>
+   void do_assign(const Exp& e, const proto::tag::plus&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      typedef typename proto::result_of::right<Exp>::type right_type;
+
+      static int const left_depth = boost::result_of<detail::CalcDepth(left_type)>::type::value;
+      static int const right_depth = boost::result_of<detail::CalcDepth(right_type)>::type::value;
+
+      bool bl = contains_self(proto::left(e));
+      bool br = contains_self(proto::right(e));
+
+      if(bl && is_self(proto::left(e)))
+      {
+         // Ignore the left node, it's *this, just add the right:
+         do_add(proto::right(e), typename proto::tag_of<right_type>::type());
+      }
+      else if(br && is_self(proto::right(e)))
+      {
+         // Ignore the right node, it's *this, just add the left:
+         do_add(proto::left(e), typename proto::tag_of<left_type>::type());
+      }
+      else if(bl || br)
+      {
+         self_type temp(e);
+         temp.m_backend.swap(this->m_backend);
+      }
+      else if(left_depth >= right_depth)
+      {
+         do_assign(proto::left(e), typename proto::tag_of<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_add(proto::left(e), typename proto::tag_of<left_type>::type());
+      }
+   }
+   template <class Exp>
+   void do_assign(const Exp& e, const proto::tag::minus&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      typedef typename proto::result_of::right<Exp>::type right_type;
+
+      static int const left_depth = boost::result_of<detail::CalcDepth(left_type)>::type::value;
+      static int const right_depth = boost::result_of<detail::CalcDepth(right_type)>::type::value;
+
+      bool bl = contains_self(proto::left(e));
+      bool br = contains_self(proto::right(e));
+
+      if(bl && is_self(proto::left(e)))
+      {
+         // Ignore the left node, it's *this, just subtract the right:
+         do_subtract(proto::right(e), typename proto::tag_of<right_type>::type());
+      }
+      else if(br && is_self(proto::right(e)))
+      {
+         // Ignore the right node, it's *this, just subtract the left and negate the result:
+         do_subtract(proto::left(e), typename proto::tag_of<left_type>::type());
+         m_backend.negate();
+      }
+      else if(bl || br)
+      {
+         self_type temp(e);
+         temp.m_backend.swap(this->m_backend);
+      }
+      else if(left_depth >= right_depth)
+      {
+         do_assign(proto::left(e), typename proto::tag_of<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_subtract(proto::left(e), typename proto::tag_of<left_type>::type());
+         m_backend.negate();
+      }
+   }
+   template <class Exp>
+   void do_assign(const Exp& e, const proto::tag::multiplies&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      typedef typename proto::result_of::right<Exp>::type right_type;
+
+      static int const left_depth = boost::result_of<detail::CalcDepth(left_type)>::type::value;
+      static int const right_depth = boost::result_of<detail::CalcDepth(right_type)>::type::value;
+
+      bool bl = contains_self(proto::left(e));
+      bool br = contains_self(proto::right(e));
+
+      if(bl && is_self(proto::left(e)))
+      {
+         // Ignore the left node, it's *this, just add the right:
+         do_multiplies(proto::right(e), typename proto::tag_of<right_type>::type());
+      }
+      else if(br && is_self(proto::right(e)))
+      {
+         // Ignore the right node, it's *this, just add the left:
+         do_multiplies(proto::left(e), typename proto::tag_of<left_type>::type());
+      }
+      else if(bl || br)
+      {
+         self_type temp(e);
+         temp.m_backend.swap(this->m_backend);
+      }
+      else if(left_depth >= right_depth)
+      {
+         do_assign(proto::left(e), typename proto::tag_of<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_multiplies(proto::left(e), typename proto::tag_of<left_type>::type());
+      }
+   }
+   template <class Exp>
+   void do_assign(const Exp& e, const proto::tag::divides&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      typedef typename proto::result_of::right<Exp>::type right_type;
+
+      static int const left_depth = boost::result_of<detail::CalcDepth(left_type)>::type::value;
+      static int const right_depth = boost::result_of<detail::CalcDepth(right_type)>::type::value;
+
+      bool bl = contains_self(proto::left(e));
+      bool br = contains_self(proto::right(e));
+
+      if(bl && is_self(proto::left(e)))
+      {
+         // Ignore the left node, it's *this, just add the right:
+         do_divide(proto::right(e), typename proto::tag_of<right_type>::type());
+      }
+      else if(bl || br)
+      {
+         self_type temp(e);
+         temp.m_backend.swap(this->m_backend);
+      }
+      else
+      {
+         do_assign(proto::left(e), typename proto::tag_of<left_type>::type());
+         do_divide(proto::right(e), typename proto::tag_of<right_type>::type());
+      }
+   }
+   template <class Exp>
+   void do_assign(const Exp& e, const proto::tag::modulus&)
+   {
+      //
+      // This operation is only valid for integer backends:
+      //
+      BOOST_STATIC_ASSERT_MSG(is_extended_integer<Backend>::value, "The modulus operation is only valid for integer types");
+
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      typedef typename proto::result_of::right<Exp>::type right_type;
+
+      static int const left_depth = boost::result_of<detail::CalcDepth(left_type)>::type::value;
+      static int const right_depth = boost::result_of<detail::CalcDepth(right_type)>::type::value;
+
+      bool bl = contains_self(proto::left(e));
+      bool br = contains_self(proto::right(e));
+
+      if(bl && is_self(proto::left(e)))
+      {
+         // Ignore the left node, it's *this, just add the right:
+         do_modulus(proto::right(e), typename proto::tag_of<right_type>::type());
+      }
+      else if(bl || br)
+      {
+         self_type temp(e);
+         temp.m_backend.swap(this->m_backend);
+      }
+      else
+      {
+         do_assign(proto::left(e), typename proto::tag_of<left_type>::type());
+         do_modulus(proto::right(e), typename proto::tag_of<right_type>::type());
+      }
+   }
+   template <class Exp>
+   void do_assign(const Exp& e, const proto::tag::terminal&)
+   {
+      if(!is_self(e))
+      {
+         m_backend = canonical_value(proto::value(e));
+      }
+   }
+
+   template <class Exp>
+   void do_add(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_add_value(canonical_value(proto::value(e)), tag());
+   }
+
+   template <class V>
+   void do_add_value(const V& v, const mpl::false_&)
+   {
+      m_backend += v;
+   }
+   template <class V>
+   void do_add_value(const V& v, const mpl::true_&)
+   {
+      self_type temp(v);
+      m_backend += temp.m_backend;
+   }
+
+   template <class Exp>
+   void do_add(const Exp& e, const proto::tag::unary_plus&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      do_add(proto::left(e), typename proto::tag_of<left_type>::type());
+   }
+
+   template <class Exp>
+   void do_add(const Exp& e, const proto::tag::negate&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      do_subtract(proto::left(e), typename proto::tag_of<left_type>::type());
+   }
+
+   template <class Exp>
+   void do_add(const Exp& e, const proto::tag::plus&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      typedef typename proto::result_of::right<Exp>::type right_type;
+      do_add(proto::left(e), typename proto::tag_of<left_type>::type());
+      do_add(proto::right(e), typename proto::tag_of<right_type>::type());
+   }
+
+   template <class Exp>
+   void do_add(const Exp& e, const proto::tag::minus&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      typedef typename proto::result_of::right<Exp>::type right_type;
+      do_add(proto::left(e), typename proto::tag_of<left_type>::type());
+      do_subtract(proto::right(e), typename proto::tag_of<right_type>::type());
+   }
+
+   template <class Exp, class unknown>
+   void do_add(const Exp& e, const unknown&)
+   {
+      self_type temp(e);
+      do_add(temp, proto::tag::terminal());
+   }
+
+   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;
+   }
+
+   template <class Exp>
+   void do_subtract(const Exp& e, const proto::tag::unary_plus&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      do_subtract(proto::left(e), typename proto::tag_of<left_type>::type());
+   }
+
+   template <class Exp>
+   void do_subtract(const Exp& e, const proto::tag::negate&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      do_add(proto::left(e), typename proto::tag_of<left_type>::type());
+   }
+
+   template <class Exp>
+   void do_subtract(const Exp& e, const proto::tag::plus&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      typedef typename proto::result_of::right<Exp>::type right_type;
+      do_subtract(proto::left(e), typename proto::tag_of<left_type>::type());
+      do_subtract(proto::right(e), typename proto::tag_of<right_type>::type());
+   }
+
+   template <class Exp>
+   void do_subtract(const Exp& e, const proto::tag::minus&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      typedef typename proto::result_of::right<Exp>::type right_type;
+      do_subtract(proto::left(e), typename proto::tag_of<left_type>::type());
+      do_add(proto::right(e), typename proto::tag_of<right_type>::type());
+   }
+
+   template <class Exp, class unknown>
+   void do_subtract(const Exp& e, const unknown&)
+   {
+      self_type temp(e);
+      do_subtract(temp, proto::tag::terminal());
+   }
+
+   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;
+   }
+
+   template <class Exp>
+   void do_multiplies(const Exp& e, const proto::tag::unary_plus&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      do_multiplies(proto::left(e), typename proto::tag_of<left_type>::type());
+   }
+
+   template <class Exp>
+   void do_multiplies(const Exp& e, const proto::tag::negate&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      do_multiplies(proto::left(e), typename proto::tag_of<left_type>::type());
+      m_backend.negate();
+   }
+
+   template <class Exp>
+   void do_multiplies(const Exp& e, const proto::tag::multiplies&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      typedef typename proto::result_of::right<Exp>::type right_type;
+      do_multiplies(proto::left(e), typename proto::tag_of<left_type>::type());
+      do_multiplies(proto::right(e), typename proto::tag_of<right_type>::type());
+   }
+
+   template <class Exp>
+   void do_multiplies(const Exp& e, const proto::tag::divides&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      typedef typename proto::result_of::right<Exp>::type right_type;
+      do_multiplies(proto::left(e), typename proto::tag_of<left_type>::type());
+      do_divide(proto::right(e), typename proto::tag_of<right_type>::type());
+   }
+
+   template <class Exp, class unknown>
+   void do_multiplies(const Exp& e, const unknown&)
+   {
+      self_type temp(e);
+      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;
+   }
+
+   template <class Exp>
+   void do_divide(const Exp& e, const proto::tag::unary_plus&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      do_divide(proto::left(e), typename proto::tag_of<left_type>::type());
+   }
+
+   template <class Exp>
+   void do_divide(const Exp& e, const proto::tag::negate&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      do_divide(proto::left(e), typename proto::tag_of<left_type>::type());
+      m_backend.negate();
+   }
+
+   template <class Exp>
+   void do_divide(const Exp& e, const proto::tag::multiplies&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      typedef typename proto::result_of::right<Exp>::type right_type;
+      do_divide(proto::left(e), typename proto::tag_of<left_type>::type());
+      do_divide(proto::right(e), typename proto::tag_of<right_type>::type());
+   }
+
+   template <class Exp>
+   void do_divide(const Exp& e, const proto::tag::divides&)
+   {
+      typedef typename proto::result_of::left<Exp>::type left_type;
+      typedef typename proto::result_of::right<Exp>::type right_type;
+      do_divide(proto::left(e), typename proto::tag_of<left_type>::type());
+      do_multiplies(proto::right(e), typename proto::tag_of<right_type>::type());
+   }
+
+   template <class Exp, class unknown>
+   void do_divide(const Exp& e, const unknown&)
+   {
+      self_type temp(e);
+      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;
+   }
+
+   template <class Exp, class Unknown>
+   void do_modulus(const Exp& e, const Unknown&)
+   {
+      self_type temp(e);
+      do_modulus_value(canonical_value(proto::value(temp)), mpl::false_());
+   }
+
+   // Tests if the expression contains a reference to *this:
+   template <class Exp>
+   bool contains_self(const Exp& e)const
+   {
+      return contains_self(e, mpl::int_<proto::arity_of<Exp>::value>());
+   }
+   template <class Exp>
+   bool contains_self(const Exp& e, mpl::int_<0> const&)const
+   {
+      return is_really_self(proto::value(e));
+   }
+   template <class Exp>
+   bool contains_self(const Exp& e, mpl::int_<1> const&)const
+   {
+      typedef typename proto::result_of::child_c<Exp, 0>::type child_type;
+      return contains_self(proto::child_c<0>(e), mpl::int_<proto::arity_of<child_type>::value>());
+   }
+   template <class Exp>
+   bool contains_self(const Exp& e, mpl::int_<2> const&)const
+   {
+      typedef typename proto::result_of::child_c<Exp, 0>::type child0_type;
+      typedef typename proto::result_of::child_c<Exp, 1>::type child1_type;
+      return contains_self(proto::child_c<0>(e), mpl::int_<proto::arity_of<child0_type>::value>()) || contains_self(proto::child_c<1>(e), mpl::int_<proto::arity_of<child1_type>::value>());
+   }
+
+   // Test if the expression is a reference to *this:
+   template <class Exp>
+   bool is_self(const Exp& e)const
+   {
+      return is_self(e, mpl::int_<proto::arity_of<Exp>::value>());
+   }
+   template <class Exp>
+   bool is_self(const Exp& e, mpl::int_<0> const&)const
+   {
+      return is_really_self(proto::value(e));
+   }
+   template <class Exp, int v>
+   bool is_self(const Exp& e, mpl::int_<v> const&)const
+   {
+      return false;
+   }
+
+   template <class Val>
+   bool is_really_self(const Val&)const { return false; }
+   bool is_really_self(const self_type* v)const 
+   { 
+      return v == this; 
+   }
+   bool is_really_self(self_type* v)const
+   { 
+      return v == this; 
+   }
+
+   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;  }
+   static const Backend& canonical_value(self_type* v){  return v->m_backend;  }
+   template <class V>
+   static typename detail::canonical<V, Backend>::type canonical_value(const V& v){  return v;  }
+   static typename detail::canonical<std::string, Backend>::type canonical_value(const std::string& v){  return v.c_str();  }
+
+   Backend m_backend;
+};
+
+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)
+{
+   return a.compare(b);
+}
+
+template <class Backend, class Exp>
+inline int big_number_compare(const big_number<Backend>& a, const big_number_exp<Exp>& b)
+{
+   return a.compare(big_number<Backend>(b));
+}
+
+template <class Exp, class Backend>
+inline int big_number_compare(const big_number_exp<Exp>& a, const big_number<Backend>& b)
+{
+   return -b.compare(big_number<Backend>(a));
+}
+
+template <class Backend, class Val>
+inline int big_number_compare(const big_number<Backend>& a, const Val b)
+{
+   return a.compare(b);
+}
+
+template <class Val, class Backend>
+inline int big_number_compare(const Val a, const big_number<Backend>& b)
+{
+   return -b.compare(a);
+}
+
+template <class Exp1, class Exp2>
+inline int big_number_compare(const big_number_exp<Exp1>& a, const big_number_exp<Exp2>& b)
+{
+   typedef typename expression_type<Exp1>::type real1;
+   typedef typename expression_type<Exp2>::type real2;
+   return real1(a).compare(real2(b));
+}
+
+template <class Exp, class Val>
+inline typename enable_if<is_arithmetic<Val>, int>::type big_number_compare(const big_number_exp<Exp>& a, const Val b)
+{
+   typedef typename expression_type<Exp>::type real;
+   real t(a);
+   return t.compare(b);
+}
+
+template <class Val, class Exp>
+inline typename enable_if<is_arithmetic<Val>, int>::type big_number_compare(const Val a, const big_number_exp<Exp>& b)
+{
+   typedef typename expression_type<Exp>::type real;
+   return -real(b).compare(a);
+}
+
+template <class Exp1, class Exp2>
+struct is_valid_comparison_imp
+{
+   typedef typename mpl::or_<
+      is_big_number<Exp1>,
+      is_big_number_exp<Exp1>
+   >::type is1;
+   typedef typename mpl::or_<
+      is_big_number<Exp2>,
+      is_big_number_exp<Exp2>
+   >::type is2;
+   typedef typename mpl::or_<
+      mpl::and_<
+         is1,
+         mpl::or_<
+            is2,
+            is_arithmetic<Exp2>
+         >
+      >,
+      mpl::and_<
+         is2,
+         mpl::or_<
+            is1,
+            is_arithmetic<Exp1>
+         >
+      >
+   >::type type;
+};
+
+template <class Exp1, class Exp2>
+struct is_valid_comparison : public boost::math::detail::is_valid_comparison_imp<Exp1, Exp2>::type {};
+
+}
+
+
+template <class Exp1, class Exp2>
+inline typename boost::enable_if<detail::is_valid_comparison<Exp1, Exp2>, bool>::type 
+   operator == (const Exp1& a, const Exp2& b)
+{
+   return 0 == detail::big_number_compare(a, b);
+}
+
+template <class Exp1, class Exp2>
+inline typename boost::enable_if<detail::is_valid_comparison<Exp1, Exp2>, bool>::type 
+   operator != (const Exp1& a, const Exp2& b)
+{
+   return 0 != detail::big_number_compare(a, b);
+}
+
+template <class Exp1, class Exp2>
+inline typename boost::enable_if<detail::is_valid_comparison<Exp1, Exp2>, bool>::type 
+   operator <= (const Exp1& a, const Exp2& b)
+{
+   return 0 >= detail::big_number_compare(a, b);
+}
+
+template <class Exp1, class Exp2>
+inline typename boost::enable_if<detail::is_valid_comparison<Exp1, Exp2>, bool>::type 
+   operator < (const Exp1& a, const Exp2& b)
+{
+   return 0 > detail::big_number_compare(a, b);
+}
+
+template <class Exp1, class Exp2>
+inline typename boost::enable_if<detail::is_valid_comparison<Exp1, Exp2>, bool>::type 
+   operator >= (const Exp1& a, const Exp2& b)
+{
+   return 0 <= detail::big_number_compare(a, b);
+}
+
+template <class Exp1, class Exp2>
+inline typename boost::enable_if<detail::is_valid_comparison<Exp1, Exp2>, bool>::type 
+   operator > (const Exp1& a, const Exp2& b)
+{
+   return 0 < detail::big_number_compare(a, b);
+}
+
+template <class Backend>
+std::ostream& operator << (std::ostream& os, const big_number<Backend>& r)
+{
+   return os << r.str();
+}
+
+template <class Backend>
+std::istream& operator >> (std::istream& is, big_number<Backend>& r)
+{
+   std::string s;
+   is >> s;
+   r = s;
+   return is;
+}
+
+}} // namespaces
+
+#endif
Added: sandbox/big_number/boost/math/big_number/gmp.hpp
==============================================================================
--- (empty file)
+++ sandbox/big_number/boost/math/big_number/gmp.hpp	2011-08-08 05:21:20 EDT (Mon, 08 Aug 2011)
@@ -0,0 +1,691 @@
+///////////////////////////////////////////////////////////////////////////////
+//  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_ER_GMP_BACKEND_HPP
+#define BOOST_MATH_ER_GMP_BACKEND_HPP
+
+#include <boost/math/big_number.hpp>
+#include <boost/math/special_functions/fpclassify.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/lexical_cast.hpp>
+#include <gmp.h>
+#include <cmath>
+
+namespace boost{ namespace math{
+
+template <unsigned digits10>
+struct gmp_real;
+
+namespace detail{
+
+template <unsigned digits10>
+struct gmp_real_imp
+{
+   typedef mpl::list<long, long long>                 signed_types;
+   typedef mpl::list<unsigned long, unsigned long long>   unsigned_types;
+   typedef mpl::list<double, long double>            real_types;
+
+   gmp_real_imp(){}
+
+   gmp_real_imp(const gmp_real_imp& o)
+   {
+      mpf_init_set(m_data, o.m_data);
+   }
+   gmp_real_imp& operator = (const gmp_real_imp& o)
+   {
+      mpf_set(m_data, o.m_data);
+      return *this;
+   }
+   gmp_real_imp& operator = (boost::uintmax_t i)
+   {
+      boost::uintmax_t mask = ((1uLL << std::numeric_limits<unsigned>::digits) - 1);
+      unsigned shift = 0;
+      mpf_t t;
+      mpf_init2(m_data, ((digits10 + 1) * 1000L) / 301L);
+      mpf_init2(t, ((digits10 + 1) * 1000L) / 301L);
+      while(i)
+      {
+         mpf_set_ui(t, static_cast<unsigned>(i & mask));
+         if(shift)
+            mpf_mul_2exp(t, t, shift);
+         mpf_add(m_data, m_data, t);
+         shift += std::numeric_limits<unsigned>::digits;
+         i >>= std::numeric_limits<unsigned>::digits;
+      }
+      mpf_clear(t);
+      return *this;
+   }
+   gmp_real_imp& operator = (boost::intmax_t i)
+   {
+      bool neg = i < 0;
+      *this = static_cast<boost::uintmax_t>(std::abs(i));
+      if(neg)
+         mpf_neg(m_data, m_data);
+      return *this;
+   }
+   gmp_real_imp& operator = (unsigned long i)
+   {
+      mpf_set_ui(m_data, i);
+      return *this;
+   }
+   gmp_real_imp& operator = (long i)
+   {
+      mpf_set_si(m_data, i);
+      return *this;
+   }
+   gmp_real_imp& operator = (double d)
+   {
+      mpf_set_d(m_data, d);
+      return *this;
+   }
+   gmp_real_imp& operator = (long double a)
+   {
+      using std::frexp;
+      using std::ldexp;
+      using std::floor;
+
+      if (a == 0) {
+         mpf_set_si(m_data, 0);
+         return *this;
+      }
+
+      if (a == 1) {
+         mpf_set_si(m_data, 1);
+         return *this;
+      }
+
+      BOOST_ASSERT(!(boost::math::isinf)(a));
+      BOOST_ASSERT(!(boost::math::isnan)(a));
+
+      int e;
+      long double f, term;
+      mpf_init_set_ui(m_data, 0u);
+
+      f = frexp(a, &e);
+
+      static const int shift = std::numeric_limits<int>::digits - 1;
+
+      while(f)
+      {
+         // extract int sized bits from f:
+         f = ldexp(f, shift);
+         term = floor(f);
+         e -= shift;
+         mpf_mul_2exp(m_data, m_data, shift);
+         if(term > 0)
+            mpf_add_ui(m_data, m_data, static_cast<unsigned>(term));
+         else
+            mpf_sub_ui(m_data, m_data, static_cast<unsigned>(-term));
+         f -= term;
+      }
+      if(e > 0)
+         mpf_mul_2exp(m_data, m_data, e);
+      else if(e < 0)
+         mpf_div_2exp(m_data, m_data, -e);
+      return *this;
+   }
+   gmp_real_imp& operator = (const char* s)
+   {
+      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()const
+   {
+      mp_exp_t e;
+      void *(*alloc_func_ptr) (size_t);
+      void *(*realloc_func_ptr) (void *, size_t, size_t);
+      void (*free_func_ptr) (void *, size_t);
+      const char* ps = mpf_get_str (0, &e, 10, 0, m_data);
+      std::string s("0.");
+      if(ps[0] == '-')
+      {
+         s.insert(0, ps, 1);
+         s += ps + 1;
+      }
+      else
+      {
+         s += ps;
+      }
+      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;
+   }
+   ~gmp_real_imp()
+   {
+      mpf_clear(m_data);
+   }
+   void negate()
+   {
+      mpf_neg(m_data, m_data);
+   }
+   int compare(const gmp_real<digits10>& o)const
+   {
+      return mpf_cmp(m_data, o.m_data);
+   }
+   int compare(long i)const
+   {
+      return mpf_cmp_si(m_data, i);
+   }
+   int compare(unsigned long i)const
+   {
+      return mpf_cmp_ui(m_data, i);
+   }
+   template <class V>
+   int compare(V v)const
+   {
+      gmp_real<digits10> d;
+      d = v;
+      return compare(d);
+   }
+protected:
+   mpf_t m_data;
+};
+
+} // namespace detail
+
+template <unsigned digits10>
+struct gmp_real : public detail::gmp_real_imp<digits10>
+{
+   gmp_real()
+   {
+      mpf_init2(this->m_data, ((digits10 + 1) * 1000L) / 301L);
+   }
+   gmp_real(const gmp_real& o) : gmp_real_imp(o) {}
+
+   gmp_real& operator=(const gmp_real& o)
+   {
+      *static_cast<detail::gmp_real_imp<digits10>*>(this) = static_cast<detail::gmp_real_imp<digits10> const&>(o);
+      return *this;
+   }
+
+   template <class V>
+   gmp_real& operator=(const V& v)
+   {
+      *static_cast<detail::gmp_real_imp<digits10>*>(this) = v;
+      return *this;
+   }
+};
+
+template <>
+struct gmp_real<0> : public detail::gmp_real_imp<0>
+{
+   gmp_real()
+   {
+      mpf_init2(this->m_data, ((get_default_precision() + 1) * 1000L) / 301L);
+   }
+   gmp_real(unsigned digits10)
+   {
+      mpf_init2(this->m_data, ((digits10 + 1) * 1000L) / 301L);
+   }
+   gmp_real(const gmp_real& o) : gmp_real_imp(o) {}
+   gmp_real(const gmp_real& o, unsigned digits10) 
+   {
+      mpf_init2(this->m_data, ((digits10 + 1) * 1000L) / 301L);
+      *this = o;
+   }
+
+   gmp_real& operator=(const gmp_real& o)
+   {
+      *static_cast<detail::gmp_real_imp<0>*>(this) = static_cast<detail::gmp_real_imp<0> const&>(o);
+      return *this;
+   }
+
+   template <class V>
+   gmp_real& operator=(const V& v)
+   {
+      *static_cast<detail::gmp_real_imp<0>*>(this) = v;
+      return *this;
+   }
+   static unsigned default_precision()
+   {
+      return get_default_precision();
+   }
+   static void default_precision(unsigned v)
+   {
+      get_default_precision() = v;
+   }
+   unsigned precision()const
+   {
+      return mpf_get_prec(this->m_data) * 301L / 1000 - 1;
+   }
+   void precision(unsigned digits10)
+   {
+      mpf_set_prec(this->m_data, (digits10 + 1) * 1000L / 301);
+   }
+private:
+   static unsigned& get_default_precision()
+   {
+      static unsigned val = 50;
+      return val;
+   }
+};
+
+struct gmp_int
+{
+   typedef mpl::list<long, long long>                 signed_types;
+   typedef mpl::list<unsigned long, unsigned long long>   unsigned_types;
+   typedef mpl::list<double, long double>            real_types;
+
+   gmp_int()
+   {
+      mpz_init(this->m_data);
+   }
+   gmp_int(const gmp_int& o)
+   {
+      mpz_init_set(m_data, o.m_data);
+   }
+   gmp_int& operator = (const gmp_int& o)
+   {
+      mpz_set(m_data, o.m_data);
+      return *this;
+   }
+   gmp_int& operator = (boost::uintmax_t i)
+   {
+      boost::uintmax_t mask = ((1uLL << std::numeric_limits<unsigned>::digits) - 1);
+      unsigned shift = 0;
+      mpz_t t;
+      mpz_init(m_data);
+      mpz_init(t);
+      while(i)
+      {
+         mpz_set_ui(t, static_cast<unsigned>(i & mask));
+         if(shift)
+            mpz_mul_2exp(t, t, shift);
+         mpz_add(m_data, m_data, t);
+         shift += std::numeric_limits<unsigned>::digits;
+         i >>= std::numeric_limits<unsigned>::digits;
+      }
+      mpz_clear(t);
+      return *this;
+   }
+   gmp_int& operator = (boost::intmax_t i)
+   {
+      bool neg = i < 0;
+      *this = static_cast<boost::uintmax_t>(std::abs(i));
+      if(neg)
+         mpz_neg(m_data, m_data);
+      return *this;
+   }
+   gmp_int& operator = (unsigned long i)
+   {
+      mpz_set_ui(m_data, i);
+      return *this;
+   }
+   gmp_int& operator = (long i)
+   {
+      mpz_set_si(m_data, i);
+      return *this;
+   }
+   gmp_int& operator = (double d)
+   {
+      mpz_set_d(m_data, d);
+      return *this;
+   }
+   gmp_int& operator = (long double a)
+   {
+      using std::frexp;
+      using std::ldexp;
+      using std::floor;
+
+      if (a == 0) {
+         mpz_set_si(m_data, 0);
+         return *this;
+      }
+
+      if (a == 1) {
+         mpz_set_si(m_data, 1);
+         return *this;
+      }
+
+      BOOST_ASSERT(!(boost::math::isinf)(a));
+      BOOST_ASSERT(!(boost::math::isnan)(a));
+
+      int e;
+      long double f, term;
+      mpz_init_set_ui(m_data, 0u);
+
+      f = frexp(a, &e);
+
+      static const int shift = std::numeric_limits<int>::digits - 1;
+
+      while(f)
+      {
+         // extract int sized bits from f:
+         f = ldexp(f, shift);
+         term = floor(f);
+         e -= shift;
+         mpz_mul_2exp(m_data, m_data, shift);
+         if(term > 0)
+            mpz_add_ui(m_data, m_data, static_cast<unsigned>(term));
+         else
+            mpz_sub_ui(m_data, m_data, static_cast<unsigned>(-term));
+         f -= term;
+      }
+      if(e > 0)
+         mpz_mul_2exp(m_data, m_data, e);
+      else if(e < 0)
+         mpz_div_2exp(m_data, m_data, -e);
+      return *this;
+   }
+   gmp_int& operator = (const char* s)
+   {
+      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()const
+   {
+      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 = mpz_get_str (0, 10, m_data);
+      std::string s = ps;
+      mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
+      (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
+      return s;
+   }
+   ~gmp_int()
+   {
+      mpz_clear(m_data);
+   }
+   void negate()
+   {
+      mpz_neg(m_data, m_data);
+   }
+   int compare(const gmp_int& o)const
+   {
+      return mpz_cmp(m_data, o.m_data);
+   }
+   int compare(long i)const
+   {
+      return mpz_cmp_si(m_data, i);
+   }
+   int compare(unsigned long i)const
+   {
+      return mpz_cmp_ui(m_data, i);
+   }
+   template <class V>
+   int compare(V v)const
+   {
+      gmp_int d;
+      d = v;
+      return compare(d);
+   }
+protected:
+   mpz_t m_data;
+};
+
+template<>
+struct is_extended_integer<gmp_int> : public mpl::true_ {};
+
+typedef big_number<gmp_real<50> >    mpf_real_50;
+typedef big_number<gmp_real<100> >   mpf_real_100;
+typedef big_number<gmp_real<500> >   mpf_real_500;
+typedef big_number<gmp_real<1000> >  mpf_real_1000;
+typedef big_number<gmp_real<0> >     mpf_real;
+typedef big_number<gmp_int >         mpz_int;
+
+}}  // namespaces
+
+#endif
Added: sandbox/big_number/boost/math/concepts/big_number_architypes.hpp
==============================================================================
--- (empty file)
+++ sandbox/big_number/boost/math/concepts/big_number_architypes.hpp	2011-08-08 05:21:20 EDT (Mon, 08 Aug 2011)
@@ -0,0 +1,309 @@
+///////////////////////////////////////////////////////////////
+//  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_
+
+#ifndef BOOST_MATH_CONCEPTS_ER_HPP
+#define BOOST_MATH_CONCEPTS_ER_HPP
+
+#include <iostream>
+#include <iomanip>
+#include <boost/cstdint.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/math/big_number.hpp>
+
+namespace boost{
+namespace math{
+namespace concepts{
+
+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;
+
+   big_number_backend_real_architype()
+   {
+      std::cout << "Default construct" << std::endl;
+   }
+   big_number_backend_real_architype(const big_number_backend_real_architype& o)
+   {
+      std::cout << "Copy construct" << std::endl;
+      m_value = o.m_value;
+   }
+   big_number_backend_real_architype& operator = (const big_number_backend_real_architype& o)
+   {
+      m_value = o.m_value;
+      std::cout << "Assignment (" << m_value << ")" << std::endl;
+      return *this;
+   }
+   big_number_backend_real_architype& operator = (boost::uintmax_t i)
+   {
+      m_value = i;
+      std::cout << "UInt Assignment (" << i << ")" << std::endl;
+      return *this;
+   }
+   big_number_backend_real_architype& operator = (boost::intmax_t i)
+   {
+      m_value = i;
+      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;
+      std::cout << "long double Assignment (" << d << ")" << std::endl;
+      return *this;
+   }
+   big_number_backend_real_architype& operator = (const char* s)
+   {
+      m_value = boost::lexical_cast<double>(s);
+      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()const
+   {
+      std::string s(boost::lexical_cast<std::string>(m_value));
+      std::cout << "Converting to string (" << s << ")" << std::endl;
+      return s;
+   }
+   void negate()
+   {
+      std::cout << "Negating (" << m_value << ")" << std::endl;
+      m_value = -m_value;
+   }
+   int compare(const big_number_backend_real_architype& o)const
+   {
+      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;
+      return m_value > i ? 1 : (m_value < i ? -1 : 0);
+   }
+   int compare(boost::uintmax_t i)const
+   {
+      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;
+};
+
+typedef boost::math::big_number<big_number_backend_real_architype> big_number_real_architype;
+
+}}} // namespaces
+
+#endif
Added: sandbox/big_number/libs/math/test/big_number_concept_check.cpp
==============================================================================
--- (empty file)
+++ sandbox/big_number/libs/math/test/big_number_concept_check.cpp	2011-08-08 05:21:20 EDT (Mon, 08 Aug 2011)
@@ -0,0 +1,38 @@
+
+//  Copyright John Maddock 2011.
+//  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)
+
+//
+// This tests two things: that e_float meets our
+// conceptual requirements, and that we can instantiate
+// all our distributions and special functions on this type.
+//
+#define BOOST_MATH_ASSERT_UNDEFINED_POLICY false
+#define TEST_MPFR
+
+#ifdef _MSC_VER
+#  pragma warning(disable:4800)
+#  pragma warning(disable:4512)
+#  pragma warning(disable:4127)
+#  pragma warning(disable:4512)
+#  pragma warning(disable:4503) // decorated name length exceeded, name was truncated
+#endif
+
+#include <boost/math/concepts/big_number_backend.hpp>
+
+#include <boost/math/concepts/real_type_concept.hpp>
+//#include "compile_test/instantiate.hpp"
+/*
+void foo()
+{
+   instantiate(boost::math::ef::e_float());
+}
+*/
+int main()
+{
+   BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept<boost::math::concepts::big_number_real_architype>));
+}
+
+
Added: sandbox/big_number/libs/math/test/test_arithmetic.cpp
==============================================================================
--- (empty file)
+++ sandbox/big_number/libs/math/test/test_arithmetic.cpp	2011-08-08 05:21:20 EDT (Mon, 08 Aug 2011)
@@ -0,0 +1,443 @@
+///////////////////////////////////////////////////////////////
+//  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_
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/math/concepts/big_number_architypes.hpp>
+#include <boost/math/big_number/gmp.hpp>
+
+#if !defined(TEST_MPF50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ)
+#  define TEST_MPF50
+#  define TEST_MPF
+#  define TEST_BACKEND
+#  define TEST_MPZ
+#endif
+
+template <class Real>
+void test_integer_ops(const boost::mpl::false_&){}
+
+template <class Real>
+void test_integer_ops(const boost::mpl::true_&)
+{
+   Real a(20);
+   Real b(7);
+   BOOST_TEST(a % b == 20 % 7);
+   BOOST_TEST(a % 7 == 20 % 7);
+   BOOST_TEST(a % 7u == 20 % 7);
+   BOOST_TEST(-a % b == -20 % 7);
+   BOOST_TEST(-a % -b == -20 % -7);
+   BOOST_TEST(a % -b == 20 % -7);
+   BOOST_TEST(-a % 7 == -20 % 7);
+   BOOST_TEST(-a % -7 == -20 % -7);
+   BOOST_TEST(a % -7 == 20 % -7);
+   BOOST_TEST(-a % 7u == -20 % 7);
+
+   a = 20;
+   a %= b;
+   BOOST_TEST(a == 20 % 7);
+   a = -20;
+   a %= b;
+   BOOST_TEST(a == -20 % 7);
+   a = 20;
+   a %= -b;
+   BOOST_TEST(a == 20 % -7);
+   a = -20;
+   a %= -b;
+   BOOST_TEST(a == -20 % -7);
+
+   a = 20;
+   a %= 7;
+   BOOST_TEST(a == 20 % 7);
+   a = -20;
+   a %= 7;
+   BOOST_TEST(a == -20 % 7);
+   a = 20;
+   a %= -7;
+   BOOST_TEST(a == 20 % -7);
+   a = -20;
+   a %= -7;
+   BOOST_TEST(a == -20 % -7);
+}
+
+template <class Real, class Num>
+void test_negative_mixed(boost::mpl::true_ const&)
+{
+   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;
+   Num n3 = 0;
+   Num n4 = -20;
+   Num n5 = -8;
+   // Default construct:
+   BOOST_TEST(Real(n1) == n1);
+   BOOST_TEST(Real(n2) == n2);
+   BOOST_TEST(Real(n3) == n3);
+   BOOST_TEST(Real(n4) == n4);
+   BOOST_TEST(n1 == Real(n1));
+   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)));
+   // Assignment:
+   Real r(0);
+   BOOST_TEST(r != n1);
+   r = n1;
+   BOOST_TEST(r == n1);
+   r = n2;
+   BOOST_TEST(r == n2);
+   r = n3;
+   BOOST_TEST(r == n3);
+   r = n4;
+   BOOST_TEST(r == n4);
+   // Addition:
+   r = n2;
+   BOOST_TEST(r + n4 == n2 + n4);
+   BOOST_TEST(Real(r + n4) == n2 + n4);
+   r += n4;
+   BOOST_TEST(r == n2 + n4);
+   // subtraction:
+   r = n4;
+   BOOST_TEST(r - n5 == n4 - n5);
+   BOOST_TEST(Real(r - n5) == n4 - n5);
+   r -= n5;
+   BOOST_TEST(r == n4 - n5);
+   // Multiplication:
+   r = n2;
+   BOOST_TEST(r * n4 == n2 * n4);
+   BOOST_TEST(Real(r * n4) == n2 * n4);
+   r *= n4;
+   BOOST_TEST(r == n2 * n4);
+   // Division:
+   r = n1;
+   BOOST_TEST(r / n5 == n1 / n5);
+   BOOST_TEST(Real(r / n5) == n1 / n5);
+   r /= n5;
+   BOOST_TEST(r == n1 / n5);
+}
+
+template <class Real, class Num>
+void test_negative_mixed(boost::mpl::false_ const&)
+{
+}
+
+template <class Real, class Num>
+void test_mixed()
+{
+   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;
+   Num n3 = 0;
+   Num n4 = 20;
+   Num n5 = 8;
+   // Default construct:
+   BOOST_TEST(Real(n1) == n1);
+   BOOST_TEST(Real(n2) == n2);
+   BOOST_TEST(Real(n3) == n3);
+   BOOST_TEST(Real(n4) == n4);
+   BOOST_TEST(n1 == Real(n1));
+   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)));
+   // Assignment:
+   Real r(0);
+   BOOST_TEST(r != n1);
+   r = n1;
+   BOOST_TEST(r == n1);
+   r = n2;
+   BOOST_TEST(r == n2);
+   r = n3;
+   BOOST_TEST(r == n3);
+   r = n4;
+   BOOST_TEST(r == n4);
+   // Addition:
+   r = n2;
+   BOOST_TEST(r + n4 == n2 + n4);
+   BOOST_TEST(Real(r + n4) == n2 + n4);
+   r += n4;
+   BOOST_TEST(r == n2 + n4);
+   // subtraction:
+   r = n4;
+   BOOST_TEST(r - n5 == n4 - n5);
+   BOOST_TEST(Real(r - n5) == n4 - n5);
+   r -= n5;
+   BOOST_TEST(r == n4 - n5);
+   // Multiplication:
+   r = n2;
+   BOOST_TEST(r * n4 == n2 * n4);
+   BOOST_TEST(Real(r * n4) == n2 * n4);
+   r *= n4;
+   BOOST_TEST(r == n2 * n4);
+   // Division:
+   r = n1;
+   BOOST_TEST(r / n5 == n1 / n5);
+   BOOST_TEST(Real(r / n5) == n1 / n5);
+   r /= n5;
+   BOOST_TEST(r == n1 / n5);
+
+   test_negative_mixed<Real, Num>(boost::mpl::bool_<std::numeric_limits<Num>::is_signed>());
+}
+
+template <class Real>
+void test()
+{
+   test_mixed<Real, unsigned char>();
+   test_mixed<Real, signed char>();
+   test_mixed<Real, char>();
+   test_mixed<Real, short>();
+   test_mixed<Real, unsigned short>();
+   test_mixed<Real, int>();
+   test_mixed<Real, unsigned int>();
+   test_mixed<Real, long>();
+   test_mixed<Real, unsigned long>();
+#ifdef BOOST_HAS_LONG_LONG
+   test_mixed<Real, long long>();
+   test_mixed<Real, unsigned long long>();
+#endif
+   test_mixed<Real, float>();
+   test_mixed<Real, double>();
+   test_mixed<Real, long double>();
+   //
+   // Integer only functions:
+   //
+   test_integer_ops<Real>(boost::math::is_extended_integer<Real>());
+   //
+   // Test basic arithmetic:
+   //
+   Real a(8);
+   Real b(64);
+   Real c(500);
+   Real d(1024);
+   BOOST_TEST(a + b == 72);
+   a += b;
+   BOOST_TEST(a == 72);
+   BOOST_TEST(a - b == 8);
+   a -= b;
+   BOOST_TEST(a == 8);
+   BOOST_TEST(a * b == 8*64L);
+   a *= b;
+   BOOST_TEST(a == 8*64L);
+   BOOST_TEST(a / b == 8);
+   a /= b;
+   BOOST_TEST(a == 8);
+
+   Real ac(a);
+   BOOST_TEST(ac == a);
+   BOOST_TEST(-a == -8);
+
+   ac = a * c;
+   BOOST_TEST(ac == 8*500L);
+   
+   ac = ac + b + c;
+   BOOST_TEST(ac == 8*500L+64+500);
+   ac = a;
+   ac = b + c + ac;
+   BOOST_TEST(ac == 8+64+500);
+   ac = ac - b + c;
+   BOOST_TEST(ac == 8+64+500-64+500);
+   ac = a;
+   ac = b + c - ac;
+   BOOST_TEST(ac == -8+64+500);
+   ac = a;
+   ac = ac * b;
+   BOOST_TEST(ac == 8*64);
+   ac = a;
+   ac *= b * ac;
+   BOOST_TEST(ac == 8*8*64);
+   ac = b;
+   ac = ac / a;
+   BOOST_TEST(ac == 64/8);
+   ac = b;
+   ac /= ac / a;
+   BOOST_TEST(ac == 64 / (64/8));
+   ac = a;
+   ac = b + ac * a;
+   BOOST_TEST(ac == 64 * 2);
+   ac = a;
+   ac = b - ac * a;
+   BOOST_TEST(ac == 0);
+   ac = a;
+   ac = b * (ac + a);
+   BOOST_TEST(ac == 64 * (16));
+   ac = a;
+   ac = b / (ac * 1);
+   BOOST_TEST(ac == 64 / 8);
+   ac = a;
+   ac = ac + b;
+   BOOST_TEST(ac == 8 + 64);
+   ac = a;
+   ac = a + ac;
+   BOOST_TEST(ac == 16);
+   ac = a;
+   ac = ac - b;
+   BOOST_TEST(ac == 8 - 64);
+   ac = a;
+   ac = a - ac;
+   BOOST_TEST(ac == 0);
+   ac = a;
+   ac += a + b;
+   BOOST_TEST(ac == 80);
+   ac = a;
+   ac += b + a;
+   BOOST_TEST(ac == 80);
+   ac = a;
+   ac -= a + b;
+   BOOST_TEST(ac == -64);
+   ac = a;
+   ac -= b - a;
+   BOOST_TEST(ac == 16 - 64);
+   ac = +a;
+   BOOST_TEST(ac == 8);
+   ac = -a;
+   BOOST_TEST(ac == -8);
+   ac = 8;
+   ac = a * ac;
+   BOOST_TEST(ac == 8*8);
+   ac = a;
+   ac = ac + "8";
+   BOOST_TEST(ac == 16);
+   ac = a;
+   ac += +a;
+   BOOST_TEST(ac == 16);
+   ac = a;
+   ac += -a;
+   BOOST_TEST(ac == 0);
+   ac = a;
+   ac += b - a;
+   BOOST_TEST(ac == 8 + 64-8);
+   ac = a;
+   ac += b*c;
+   BOOST_TEST(ac == 8 + 64 * 500);
+   ac = a;
+   ac = ac - "8";
+   BOOST_TEST(ac == 0);
+   ac = a;
+   ac -= +a;
+   BOOST_TEST(ac == 0);
+   ac = a;
+   ac -= -a;
+   BOOST_TEST(ac == 16);
+   ac = a;
+   ac -= c - b;
+   BOOST_TEST(ac == 8 - (500-64));
+   ac = a;
+   ac -= b*c;
+   BOOST_TEST(ac == 8 - 500*64);
+   ac = a;
+   ac += ac * b;
+   BOOST_TEST(ac == 8 + 8 * 64);
+   ac = a;
+   ac -= ac * b;
+   BOOST_TEST(ac == 8 - 8 * 64);
+   ac = a * "8";
+   BOOST_TEST(ac == 64);
+   ac *= +a;
+   BOOST_TEST(ac == 64 * 8);
+   ac = a;
+   ac *= -a;
+   BOOST_TEST(ac == -64);
+   ac = a;
+   ac *= b * c;
+   BOOST_TEST(ac == 8 * 64 * 500);
+   ac = a;
+   ac *= b / a;
+   BOOST_TEST(ac == 8 * 64 / 8);
+   ac = a;
+   ac *= b + c;
+   BOOST_TEST(ac == 8 * (64 + 500));
+   ac = b / "8";
+   BOOST_TEST(ac == 8);
+   ac = b;
+   ac /= +a;
+   BOOST_TEST(ac == 8);
+   ac = b;
+   ac /= -a;
+   BOOST_TEST(ac == -8);
+   ac = b;
+   ac /= b / a;
+   BOOST_TEST(ac == 64 / (64/8));
+   ac = b;
+   ac /= a + Real(0);
+   BOOST_TEST(ac == 8);
+   ac = a + std::string("8");
+   BOOST_TEST(ac == 16);
+   //
+   // Comparisons:
+   //
+   BOOST_TEST((a == b) == false);
+   BOOST_TEST((a != b) == true);
+   BOOST_TEST((a <= b) == true);
+   BOOST_TEST((a < b) == true);
+   BOOST_TEST((a >= b) == false);
+   BOOST_TEST((a > b) == false);
+
+   BOOST_TEST((a+b == b) == false);
+   BOOST_TEST((a+b != b) == true);
+   BOOST_TEST((a+b >= b) == true);
+   BOOST_TEST((a+b > b) == true);
+   BOOST_TEST((a+b <= b) == false);
+   BOOST_TEST((a+b < b) == false);
+
+   BOOST_TEST((a == b+a) == false);
+   BOOST_TEST((a != b+a) == true);
+   BOOST_TEST((a <= b+a) == true);
+   BOOST_TEST((a < b+a) == true);
+   BOOST_TEST((a >= b+a) == false);
+   BOOST_TEST((a > b+a) == false);
+
+   BOOST_TEST((a+b == b+a) == true);
+   BOOST_TEST((a+b != b+a) == false);
+   BOOST_TEST((a+b <= b+a) == true);
+   BOOST_TEST((a+b < b+a) == false);
+   BOOST_TEST((a+b >= b+a) == true);
+   BOOST_TEST((a+b > b+a) == false);
+
+   BOOST_TEST((8 == b+a) == false);
+   BOOST_TEST((8 != b+a) == true);
+   BOOST_TEST((8 <= b+a) == true);
+   BOOST_TEST((8 < b+a) == true);
+   BOOST_TEST((8 >= b+a) == false);
+   BOOST_TEST((8 > b+a) == false);
+   BOOST_TEST((800 == b+a) == false);
+   BOOST_TEST((800 != b+a) == true);
+   BOOST_TEST((800 >= b+a) == true);
+   BOOST_TEST((800 > b+a) == true);
+   BOOST_TEST((800 <= b+a) == false);
+   BOOST_TEST((800 < b+a) == false);
+   BOOST_TEST((72 == b+a) == true);
+   BOOST_TEST((72 != b+a) == false);
+   BOOST_TEST((72 <= b+a) == true);
+   BOOST_TEST((72 < b+a) == false);
+   BOOST_TEST((72 >= b+a) == true);
+   BOOST_TEST((72 > b+a) == false);
+}
+
+
+int main()
+{
+#ifdef TEST_BACKEND
+   test<boost::math::big_number<boost::math::concepts::big_number_backend_real_architype> >();
+#endif
+#ifdef TEST_MPF50
+   test<boost::math::mpf_real_50>();
+#endif
+#ifdef TEST_MPF
+   boost::math::mpf_real::default_precision(1000);
+   boost::math::mpf_real r;
+   r.precision(50);
+   BOOST_TEST(r.precision() >= 50);
+   BOOST_TEST(boost::math::mpf_real::default_precision() == 1000);
+   test<boost::math::mpf_real>();
+#endif
+#ifdef TEST_MPZ
+   test<boost::math::mpz_int>();
+#endif
+   return boost::report_errors();
+}