|
Boost-Commit : |
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();
+}
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