mirror of
https://github.com/boostorg/multiprecision.git
synced 2026-02-13 00:22:25 +00:00
Change backend concepts to allow for easier default implementations, plus out-of-place arithmetic as well as in-place.
Change non-member functions to use expression templates with result value passed to the function as "workspace". [SVN r73819]
This commit is contained in:
@@ -17,156 +17,10 @@
|
||||
#include <boost/type_traits/is_signed.hpp>
|
||||
#include <boost/type_traits/is_unsigned.hpp>
|
||||
#include <boost/type_traits/is_floating_point.hpp>
|
||||
#include <boost/math/big_number/default_ops.hpp>
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
template <class Backend>
|
||||
class big_number;
|
||||
|
||||
namespace detail{
|
||||
|
||||
// Forward-declare an expression wrapper
|
||||
template<typename Expr>
|
||||
struct big_number_exp;
|
||||
//
|
||||
// Declare our grammars:
|
||||
//
|
||||
struct big_number_grammar
|
||||
: proto::or_<
|
||||
proto::terminal< proto::_ >
|
||||
, proto::plus< big_number_grammar, big_number_grammar >
|
||||
, proto::multiplies< big_number_grammar, big_number_grammar >
|
||||
, proto::minus< big_number_grammar, big_number_grammar >
|
||||
, proto::divides< big_number_grammar, big_number_grammar >
|
||||
, proto::unary_plus< big_number_grammar >
|
||||
, proto::negate< big_number_grammar >
|
||||
, proto::modulus<big_number_grammar, big_number_grammar>
|
||||
>
|
||||
{};
|
||||
|
||||
// Define a calculator domain. Expression within
|
||||
// the calculator domain will be wrapped in the
|
||||
// calculator<> expression wrapper.
|
||||
struct big_number_domain
|
||||
: proto::domain< proto::generator<big_number_exp>, big_number_grammar>
|
||||
{};
|
||||
|
||||
template<typename Expr>
|
||||
struct big_number_exp
|
||||
: proto::extends<Expr, big_number_exp<Expr>, big_number_domain>
|
||||
{
|
||||
typedef
|
||||
proto::extends<Expr, big_number_exp<Expr>, big_number_domain> base_type;
|
||||
|
||||
big_number_exp(Expr const &expr = Expr())
|
||||
: base_type(expr)
|
||||
{}
|
||||
template <class Other>
|
||||
big_number_exp(const Other& o)
|
||||
: base_type(o)
|
||||
{}
|
||||
};
|
||||
|
||||
struct CalcDepth
|
||||
: proto::or_<
|
||||
proto::when< proto::terminal<proto::_>,
|
||||
mpl::int_<0>()
|
||||
>
|
||||
, proto::when< proto::unary_expr<proto::_, CalcDepth>,
|
||||
CalcDepth(proto::_child)
|
||||
>
|
||||
, proto::when< proto::binary_expr<proto::_, CalcDepth, CalcDepth>,
|
||||
mpl::plus<mpl::max<CalcDepth(proto::_left),
|
||||
CalcDepth(proto::_right)>, mpl::int_<1> >()
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
template <int b>
|
||||
struct has_enough_bits
|
||||
{
|
||||
template <class T>
|
||||
struct type : public mpl::bool_<std::numeric_limits<T>::digits >= b>{};
|
||||
};
|
||||
|
||||
template <class Val, class Backend, class Tag>
|
||||
struct canonical_imp
|
||||
{
|
||||
typedef Val type;
|
||||
};
|
||||
template <class Val, class Backend>
|
||||
struct canonical_imp<Val, Backend, mpl::int_<0> >
|
||||
{
|
||||
typedef typename has_enough_bits<std::numeric_limits<Val>::digits>::template type<mpl::_> pred_type;
|
||||
typedef typename mpl::find_if<
|
||||
typename Backend::signed_types,
|
||||
pred_type
|
||||
>::type iter_type;
|
||||
typedef typename mpl::deref<iter_type>::type type;
|
||||
};
|
||||
template <class Val, class Backend>
|
||||
struct canonical_imp<Val, Backend, mpl::int_<1> >
|
||||
{
|
||||
typedef typename has_enough_bits<std::numeric_limits<Val>::digits>::template type<mpl::_> pred_type;
|
||||
typedef typename mpl::find_if<
|
||||
typename Backend::unsigned_types,
|
||||
pred_type
|
||||
>::type iter_type;
|
||||
typedef typename mpl::deref<iter_type>::type type;
|
||||
};
|
||||
template <class Val, class Backend>
|
||||
struct canonical_imp<Val, Backend, mpl::int_<2> >
|
||||
{
|
||||
typedef typename has_enough_bits<std::numeric_limits<Val>::digits>::template type<mpl::_> pred_type;
|
||||
typedef typename mpl::find_if<
|
||||
typename Backend::real_types,
|
||||
pred_type
|
||||
>::type iter_type;
|
||||
typedef typename mpl::deref<iter_type>::type type;
|
||||
};
|
||||
template <class Val, class Backend>
|
||||
struct canonical_imp<Val, Backend, mpl::int_<3> >
|
||||
{
|
||||
typedef const char* type;
|
||||
};
|
||||
|
||||
template <class Val, class Backend>
|
||||
struct canonical
|
||||
{
|
||||
typedef typename mpl::if_<
|
||||
is_signed<Val>,
|
||||
mpl::int_<0>,
|
||||
typename mpl::if_<
|
||||
is_unsigned<Val>,
|
||||
mpl::int_<1>,
|
||||
typename mpl::if_<
|
||||
is_floating_point<Val>,
|
||||
mpl::int_<2>,
|
||||
typename mpl::if_<
|
||||
mpl::or_<
|
||||
is_convertible<Val, const char*>,
|
||||
is_same<Val, std::string>
|
||||
>,
|
||||
mpl::int_<3>,
|
||||
mpl::int_<4>
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type tag_type;
|
||||
|
||||
typedef typename canonical_imp<Val, Backend, tag_type>::type type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
//
|
||||
// Traits class, lets us know whether a backend is an integer type, otherwise assumed to be a real number type:
|
||||
//
|
||||
template <class Num>
|
||||
struct is_extended_integer : public mpl::false_ {};
|
||||
template <class Backend>
|
||||
struct is_extended_integer<big_number<Backend> > : public is_extended_integer<Backend>{};
|
||||
|
||||
template <class Backend>
|
||||
class big_number : public detail::big_number_exp<typename proto::terminal<big_number<Backend>*>::type >
|
||||
{
|
||||
@@ -207,7 +61,7 @@ public:
|
||||
template <class Exp>
|
||||
big_number& operator=(const detail::big_number_exp<Exp>& e)
|
||||
{
|
||||
do_assign(e, typename proto::tag_of<Exp>::type());
|
||||
do_assign(e, typename detail::assign_and_eval<Exp>::type());
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -230,7 +84,7 @@ public:
|
||||
{
|
||||
proto::value(*this) = this;
|
||||
BOOST_ASSERT(proto::value(*this) == this);
|
||||
do_assign(e, typename proto::tag_of<Exp>::type());
|
||||
do_assign(e, typename detail::assign_and_eval<Exp>::type());
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
@@ -267,7 +121,8 @@ public:
|
||||
typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type
|
||||
operator+=(const V& v)
|
||||
{
|
||||
do_add_value(canonical_value(v), mpl::false_());
|
||||
using big_num_default_ops::add;
|
||||
add(m_backend, canonical_value(v));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -291,7 +146,8 @@ public:
|
||||
typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type
|
||||
operator-=(const V& v)
|
||||
{
|
||||
do_subtract_value(canonical_value(v), mpl::false_());
|
||||
using big_num_default_ops::subtract;
|
||||
subtract(m_backend, canonical_value(v));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -316,7 +172,8 @@ public:
|
||||
typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type
|
||||
operator*=(const V& v)
|
||||
{
|
||||
do_multiplies_value(canonical_value(v), mpl::false_());
|
||||
using big_num_default_ops::multiply;
|
||||
multiply(m_backend, canonical_value(v));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -342,7 +199,8 @@ public:
|
||||
operator%=(const V& v)
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(is_extended_integer<Backend>::value, "The modulus operation is only valid for integer types");
|
||||
do_modulus_value(canonical_value(v), mpl::false_());
|
||||
using big_num_default_ops::modulus;
|
||||
modulus(m_backend, canonical_value(v));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -366,16 +224,17 @@ public:
|
||||
typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type
|
||||
operator/=(const V& v)
|
||||
{
|
||||
do_divide_value(canonical_value(v), mpl::false_());
|
||||
using big_num_default_ops::divide;
|
||||
divide(m_backend, canonical_value(v));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// String conversion functions:
|
||||
//
|
||||
std::string str(unsigned digits = 0)const
|
||||
std::string str(unsigned digits = 0, bool scientific = true)const
|
||||
{
|
||||
return m_backend.str(digits);
|
||||
return m_backend.str(digits, scientific);
|
||||
}
|
||||
//
|
||||
// Default precision:
|
||||
@@ -417,18 +276,103 @@ public:
|
||||
return m_backend;
|
||||
}
|
||||
private:
|
||||
template <class Exp>
|
||||
void do_assign(const Exp& e, const detail::add_immediates&)
|
||||
{
|
||||
using big_num_default_ops::add;
|
||||
typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
|
||||
typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
|
||||
add(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
|
||||
}
|
||||
|
||||
template <class Exp>
|
||||
void do_assign(const Exp& e, const detail::add_and_negate_immediates&)
|
||||
{
|
||||
using big_num_default_ops::add;
|
||||
typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
|
||||
typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
|
||||
add(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
|
||||
m_backend.negate();
|
||||
}
|
||||
|
||||
template <class Exp>
|
||||
void do_assign(const Exp& e, const detail::subtract_immediates&)
|
||||
{
|
||||
using big_num_default_ops::subtract;
|
||||
typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
|
||||
typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
|
||||
subtract(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
|
||||
}
|
||||
|
||||
template <class Exp>
|
||||
void do_assign(const Exp& e, const detail::subtract_and_negate_immediates&)
|
||||
{
|
||||
using big_num_default_ops::subtract;
|
||||
typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
|
||||
typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
|
||||
subtract(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
|
||||
m_backend.negate();
|
||||
}
|
||||
|
||||
template <class Exp>
|
||||
void do_assign(const Exp& e, const detail::multiply_immediates&)
|
||||
{
|
||||
using big_num_default_ops::multiply;
|
||||
typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
|
||||
typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
|
||||
multiply(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
|
||||
}
|
||||
|
||||
template <class Exp>
|
||||
void do_assign(const Exp& e, const detail::multiply_and_negate_immediates&)
|
||||
{
|
||||
using big_num_default_ops::multiply;
|
||||
typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
|
||||
typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
|
||||
multiply(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
|
||||
m_backend.negate();
|
||||
}
|
||||
|
||||
template <class Exp>
|
||||
void do_assign(const Exp& e, const detail::divide_immediates&)
|
||||
{
|
||||
using big_num_default_ops::divide;
|
||||
typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
|
||||
typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
|
||||
divide(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
|
||||
}
|
||||
|
||||
template <class Exp>
|
||||
void do_assign(const Exp& e, const detail::divide_and_negate_immediates&)
|
||||
{
|
||||
using big_num_default_ops::divide;
|
||||
typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
|
||||
typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
|
||||
divide(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
|
||||
m_backend.negate();
|
||||
}
|
||||
|
||||
template <class Exp>
|
||||
void do_assign(const Exp& e, const detail::modulus_immediates&)
|
||||
{
|
||||
using big_num_default_ops::modulus;
|
||||
typedef typename proto::tag_of<typename proto::result_of::left<Exp>::type>::type left_tag;
|
||||
typedef typename proto::tag_of<typename proto::result_of::right<Exp>::type>::type right_tag;
|
||||
modulus(m_backend, canonical_value(underlying_value(proto::left(e), left_tag())), canonical_value(underlying_value(proto::right(e), right_tag())));
|
||||
}
|
||||
|
||||
template <class Exp>
|
||||
void do_assign(const Exp& e, const proto::tag::unary_plus&)
|
||||
{
|
||||
typedef typename proto::result_of::left<Exp>::type left_type;
|
||||
do_assign(proto::left(e), typename proto::tag_of<left_type>::type());
|
||||
do_assign(proto::left(e), typename detail::assign_and_eval<left_type>::type());
|
||||
}
|
||||
|
||||
template <class Exp>
|
||||
void do_assign(const Exp& e, const proto::tag::negate&)
|
||||
{
|
||||
typedef typename proto::result_of::left<Exp>::type left_type;
|
||||
do_assign(proto::left(e), typename proto::tag_of<left_type>::type());
|
||||
do_assign(proto::left(e), typename detail::assign_and_eval<left_type>::type());
|
||||
m_backend.negate();
|
||||
}
|
||||
|
||||
@@ -461,12 +405,12 @@ private:
|
||||
}
|
||||
else if(left_depth >= right_depth)
|
||||
{
|
||||
do_assign(proto::left(e), typename proto::tag_of<left_type>::type());
|
||||
do_assign(proto::left(e), typename detail::assign_and_eval<left_type>::type());
|
||||
do_add(proto::right(e), typename proto::tag_of<right_type>::type());
|
||||
}
|
||||
else
|
||||
{
|
||||
do_assign(proto::right(e), typename proto::tag_of<right_type>::type());
|
||||
do_assign(proto::right(e), typename detail::assign_and_eval<right_type>::type());
|
||||
do_add(proto::left(e), typename proto::tag_of<left_type>::type());
|
||||
}
|
||||
}
|
||||
@@ -500,12 +444,12 @@ private:
|
||||
}
|
||||
else if(left_depth >= right_depth)
|
||||
{
|
||||
do_assign(proto::left(e), typename proto::tag_of<left_type>::type());
|
||||
do_assign(proto::left(e), typename detail::assign_and_eval<left_type>::type());
|
||||
do_subtract(proto::right(e), typename proto::tag_of<right_type>::type());
|
||||
}
|
||||
else
|
||||
{
|
||||
do_assign(proto::right(e), typename proto::tag_of<right_type>::type());
|
||||
do_assign(proto::right(e), typename detail::assign_and_eval<right_type>::type());
|
||||
do_subtract(proto::left(e), typename proto::tag_of<left_type>::type());
|
||||
m_backend.negate();
|
||||
}
|
||||
@@ -539,12 +483,12 @@ private:
|
||||
}
|
||||
else if(left_depth >= right_depth)
|
||||
{
|
||||
do_assign(proto::left(e), typename proto::tag_of<left_type>::type());
|
||||
do_assign(proto::left(e), typename detail::assign_and_eval<left_type>::type());
|
||||
do_multiplies(proto::right(e), typename proto::tag_of<right_type>::type());
|
||||
}
|
||||
else
|
||||
{
|
||||
do_assign(proto::right(e), typename proto::tag_of<right_type>::type());
|
||||
do_assign(proto::right(e), typename detail::assign_and_eval<right_type>::type());
|
||||
do_multiplies(proto::left(e), typename proto::tag_of<left_type>::type());
|
||||
}
|
||||
}
|
||||
@@ -572,7 +516,7 @@ private:
|
||||
}
|
||||
else
|
||||
{
|
||||
do_assign(proto::left(e), typename proto::tag_of<left_type>::type());
|
||||
do_assign(proto::left(e), typename detail::assign_and_eval<left_type>::type());
|
||||
do_divide(proto::right(e), typename proto::tag_of<right_type>::type());
|
||||
}
|
||||
}
|
||||
@@ -605,7 +549,7 @@ private:
|
||||
}
|
||||
else
|
||||
{
|
||||
do_assign(proto::left(e), typename proto::tag_of<left_type>::type());
|
||||
do_assign(proto::left(e), typename detail::assign_and_eval<left_type>::type());
|
||||
do_modulus(proto::right(e), typename proto::tag_of<right_type>::type());
|
||||
}
|
||||
}
|
||||
@@ -617,28 +561,55 @@ private:
|
||||
m_backend = canonical_value(proto::value(e));
|
||||
}
|
||||
}
|
||||
template <class Exp>
|
||||
void do_assign(const Exp& e, const proto::tag::function&)
|
||||
{
|
||||
typedef typename proto::arity_of<Exp>::type tag_type;
|
||||
do_assign_function(e, tag_type());
|
||||
}
|
||||
template <class Exp>
|
||||
void do_assign_function(const Exp& e, const mpl::long_<1>&)
|
||||
{
|
||||
proto::value(proto::left(e))(&m_backend);
|
||||
}
|
||||
template <class Exp>
|
||||
void do_assign_function(const Exp& e, const mpl::long_<2>&)
|
||||
{
|
||||
typedef typename proto::result_of::right<Exp>::type right_type;
|
||||
typedef typename proto::tag_of<right_type>::type tag_type;
|
||||
do_assign_function_1(proto::value(proto::left(e)), proto::right(e), tag_type());
|
||||
}
|
||||
template <class F, class Exp>
|
||||
void do_assign_function_1(const F& f, const Exp& val, const proto::tag::terminal&)
|
||||
{
|
||||
f(&m_backend, canonical_value(proto::value(val)));
|
||||
}
|
||||
template <class F, class Exp, class Tag>
|
||||
void do_assign_function_1(const F& f, const Exp& val, const Tag&)
|
||||
{
|
||||
big_number t(val);
|
||||
f(&m_backend, t.backend());
|
||||
}
|
||||
template <class Exp>
|
||||
void do_assign_function(const Exp& e, const mpl::long_<3>&)
|
||||
{
|
||||
typedef typename proto::result_of::right<Exp>::type right_type;
|
||||
typedef typename proto::tag_of<right_type>::type tag_type;
|
||||
typedef typename proto::result_of::child_c<Exp, 2>::type end_type;
|
||||
typedef typename proto::tag_of<end_type>::type end_tag;
|
||||
do_assign_function_2(proto::value(proto::left(e)), proto::right(e), proto::child_c<2>(e), tag_type(), end_tag());
|
||||
}
|
||||
template <class F, class Exp1, class Exp2>
|
||||
void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const proto::tag::terminal&, const proto::tag::terminal&)
|
||||
{
|
||||
f(&m_backend, canonical_value(proto::value(val1)), canonical_value(proto::value(val2)));
|
||||
}
|
||||
|
||||
template <class Exp>
|
||||
void do_add(const Exp& e, const proto::tag::terminal&)
|
||||
{
|
||||
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;
|
||||
using big_num_default_ops::add;
|
||||
add(m_backend, canonical_value(proto::value(e)));
|
||||
}
|
||||
|
||||
template <class Exp>
|
||||
@@ -683,24 +654,8 @@ private:
|
||||
template <class Exp>
|
||||
void do_subtract(const Exp& e, const proto::tag::terminal&)
|
||||
{
|
||||
typedef typename proto::result_of::value<Exp>::type t1;
|
||||
typedef typename remove_reference<t1>::type t2;
|
||||
typedef typename remove_cv<t2>::type t3;
|
||||
typedef typename detail::canonical<t3, Backend>::type t4;
|
||||
typedef typename is_convertible<t4, const char*>::type tag;
|
||||
do_subtract_value(canonical_value(proto::value(e)), tag());
|
||||
}
|
||||
|
||||
template <class V>
|
||||
void do_subtract_value(const V& v, const mpl::false_&)
|
||||
{
|
||||
m_backend -= v;
|
||||
}
|
||||
template <class V>
|
||||
void do_subtract_value(const V& v, const mpl::true_&)
|
||||
{
|
||||
self_type temp(v);
|
||||
m_backend -= temp.m_backend;
|
||||
using big_num_default_ops::subtract;
|
||||
subtract(m_backend, canonical_value(proto::value(e)));
|
||||
}
|
||||
|
||||
template <class Exp>
|
||||
@@ -745,25 +700,8 @@ private:
|
||||
template <class Exp>
|
||||
void do_multiplies(const Exp& e, const proto::tag::terminal&)
|
||||
{
|
||||
typedef typename proto::result_of::value<Exp>::type t1;
|
||||
typedef typename remove_reference<t1>::type t2;
|
||||
typedef typename remove_cv<t2>::type t3;
|
||||
typedef typename detail::canonical<t3, Backend>::type t4;
|
||||
typedef typename is_convertible<t4, const char*>::type tag;
|
||||
do_multiplies_value(canonical_value(proto::value(e)), tag());
|
||||
}
|
||||
|
||||
template <class Val>
|
||||
void do_multiplies_value(const Val& v, const mpl::false_&)
|
||||
{
|
||||
m_backend *= v;
|
||||
}
|
||||
|
||||
template <class Val>
|
||||
void do_multiplies_value(const Val& e, const mpl::true_&)
|
||||
{
|
||||
self_type temp(e);
|
||||
m_backend *= temp.m_backend;
|
||||
using big_num_default_ops::multiply;
|
||||
multiply(m_backend, canonical_value(proto::value(e)));
|
||||
}
|
||||
|
||||
template <class Exp>
|
||||
@@ -802,32 +740,16 @@ private:
|
||||
template <class Exp, class unknown>
|
||||
void do_multiplies(const Exp& e, const unknown&)
|
||||
{
|
||||
using big_num_default_ops::multiply;
|
||||
self_type temp(e);
|
||||
m_backend *= temp.m_backend;
|
||||
multiply(m_backend, temp.m_backend);
|
||||
}
|
||||
|
||||
template <class Exp>
|
||||
void do_divide(const Exp& e, const proto::tag::terminal&)
|
||||
{
|
||||
typedef typename proto::result_of::value<Exp>::type t1;
|
||||
typedef typename remove_reference<t1>::type t2;
|
||||
typedef typename remove_cv<t2>::type t3;
|
||||
typedef typename detail::canonical<t3, Backend>::type t4;
|
||||
typedef typename is_convertible<t4, const char*>::type tag;
|
||||
do_divide_value(canonical_value(proto::value(e)), tag());
|
||||
}
|
||||
|
||||
template <class Val>
|
||||
void do_divide_value(const Val& v, const mpl::false_&)
|
||||
{
|
||||
m_backend /= v;
|
||||
}
|
||||
|
||||
template <class Val>
|
||||
void do_divide_value(const Val& e, const mpl::true_&)
|
||||
{
|
||||
self_type temp(e);
|
||||
m_backend /= temp.m_backend;
|
||||
using big_num_default_ops::divide;
|
||||
divide(m_backend, canonical_value(proto::value(e)));
|
||||
}
|
||||
|
||||
template <class Exp>
|
||||
@@ -866,39 +788,24 @@ private:
|
||||
template <class Exp, class unknown>
|
||||
void do_divide(const Exp& e, const unknown&)
|
||||
{
|
||||
using big_num_default_ops::multiply;
|
||||
self_type temp(e);
|
||||
m_backend /= temp.m_backend;
|
||||
divide(m_backend, temp.m_backend);
|
||||
}
|
||||
|
||||
template <class Exp>
|
||||
void do_modulus(const Exp& e, const proto::tag::terminal&)
|
||||
{
|
||||
typedef typename proto::result_of::value<Exp>::type t1;
|
||||
typedef typename remove_reference<t1>::type t2;
|
||||
typedef typename remove_cv<t2>::type t3;
|
||||
typedef typename detail::canonical<t3, Backend>::type t4;
|
||||
typedef typename is_convertible<t4, const char*>::type tag;
|
||||
do_modulus_value(canonical_value(proto::value(e)), tag());
|
||||
}
|
||||
|
||||
template <class Val>
|
||||
void do_modulus_value(const Val& v, const mpl::false_&)
|
||||
{
|
||||
m_backend %= v;
|
||||
}
|
||||
|
||||
template <class Val>
|
||||
void do_modulus_value(const Val& e, const mpl::true_&)
|
||||
{
|
||||
self_type temp(e);
|
||||
m_backend %= temp.m_backend;
|
||||
using big_num_default_ops::modulus;
|
||||
modulus(m_backend, canonical_value(proto::value(e)));
|
||||
}
|
||||
|
||||
template <class Exp, class Unknown>
|
||||
void do_modulus(const Exp& e, const Unknown&)
|
||||
{
|
||||
using big_num_default_ops::modulus;
|
||||
self_type temp(e);
|
||||
do_modulus_value(canonical_value(proto::value(temp)), mpl::false_());
|
||||
modulus(m_backend, canonical_value(proto::value(temp)));
|
||||
}
|
||||
|
||||
// Tests if the expression contains a reference to *this:
|
||||
@@ -953,6 +860,19 @@ private:
|
||||
{
|
||||
return v == this;
|
||||
}
|
||||
template <class Exp>
|
||||
static typename detail::underlying_result<Exp>::type underlying_value(const big_number_exp<Exp>& e, const proto::tag::terminal&)
|
||||
{
|
||||
return proto::value(e);
|
||||
}
|
||||
template <class Exp, class tag>
|
||||
static typename detail::underlying_result<Exp>::type
|
||||
underlying_value(const big_number_exp<Exp>& e, const tag&)
|
||||
{
|
||||
typedef typename proto::result_of::left<Exp>::type left_type;
|
||||
typedef typename proto::tag_of<left_type>::type tag_type;
|
||||
return underlying_value(proto::left(e), tag_type());
|
||||
}
|
||||
|
||||
static const Backend& canonical_value(const self_type& v){ return v.m_backend; }
|
||||
static const Backend& canonical_value(const self_type* v){ return v->m_backend; }
|
||||
@@ -967,72 +887,6 @@ private:
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <class Exp1, class Exp2>
|
||||
struct combine_expression_type
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template <class Backend>
|
||||
struct combine_expression_type<boost::math::big_number<Backend>, boost::math::big_number<Backend> >
|
||||
{
|
||||
typedef boost::math::big_number<Backend> type;
|
||||
};
|
||||
|
||||
template <class Backend, class Exp>
|
||||
struct combine_expression_type<boost::math::big_number<Backend>, Exp>
|
||||
{
|
||||
typedef boost::math::big_number<Backend> type;
|
||||
};
|
||||
|
||||
template <class Backend, class Exp>
|
||||
struct combine_expression_type<Exp, boost::math::big_number<Backend> >
|
||||
{
|
||||
typedef boost::math::big_number<Backend> type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_big_number : public mpl::false_{};
|
||||
template <class T>
|
||||
struct is_big_number<boost::math::big_number<T> > : public mpl::true_{};
|
||||
template <class T>
|
||||
struct is_big_number_exp : public mpl::false_{};
|
||||
template <class T>
|
||||
struct is_big_number_exp<boost::math::detail::big_number_exp<T> > : public mpl::true_{};
|
||||
|
||||
|
||||
template <class Exp, int arity>
|
||||
struct expression_type_imp;
|
||||
|
||||
template <class Exp>
|
||||
struct expression_type_imp<Exp, 0>
|
||||
{
|
||||
typedef typename remove_pointer<typename proto::result_of::value<Exp>::type>::type type;
|
||||
};
|
||||
|
||||
template <class Exp>
|
||||
struct expression_type_imp<Exp, 1>
|
||||
{
|
||||
typedef typename proto::result_of::left<Exp>::type nested_type;
|
||||
typedef typename expression_type_imp<nested_type, proto::arity_of<nested_type>::value>::type type;
|
||||
};
|
||||
|
||||
template <class Exp>
|
||||
struct expression_type_imp<Exp, 2>
|
||||
{
|
||||
typedef typename proto::result_of::left<Exp>::type left_type;
|
||||
typedef typename proto::result_of::right<Exp>::type right_type;
|
||||
typedef typename expression_type_imp<left_type, proto::arity_of<left_type>::value>::type left_result;
|
||||
typedef typename expression_type_imp<right_type, proto::arity_of<right_type>::value>::type right_result;
|
||||
typedef typename combine_expression_type<left_result, right_result>::type type;
|
||||
};
|
||||
|
||||
template <class Exp>
|
||||
struct expression_type
|
||||
{
|
||||
typedef typename expression_type_imp<Exp, proto::arity_of<Exp>::value>::type type;
|
||||
};
|
||||
|
||||
template <class Backend>
|
||||
inline int big_number_compare(const big_number<Backend>& a, const big_number<Backend>& b)
|
||||
{
|
||||
@@ -1164,13 +1018,20 @@ inline typename boost::enable_if<detail::is_valid_comparison<Exp1, Exp2>, bool>:
|
||||
}
|
||||
|
||||
template <class Backend>
|
||||
std::ostream& operator << (std::ostream& os, const big_number<Backend>& r)
|
||||
inline std::ostream& operator << (std::ostream& os, const big_number<Backend>& r)
|
||||
{
|
||||
return os << r.str(static_cast<unsigned>(os.precision()));
|
||||
return os << r.str(static_cast<unsigned>(os.precision(), os.flags() & os.scientific));
|
||||
}
|
||||
template <class Exp>
|
||||
inline std::ostream& operator << (std::ostream& os, const detail::big_number_exp<Exp>& r)
|
||||
{
|
||||
typedef typename detail::expression_type<Exp>::type value_type;
|
||||
value_type temp(r);
|
||||
return os << temp;
|
||||
}
|
||||
|
||||
template <class Backend>
|
||||
std::istream& operator >> (std::istream& is, big_number<Backend>& r)
|
||||
inline std::istream& operator >> (std::istream& is, big_number<Backend>& r)
|
||||
{
|
||||
std::string s;
|
||||
is >> s;
|
||||
@@ -1178,47 +1039,6 @@ std::istream& operator >> (std::istream& is, big_number<Backend>& r)
|
||||
return is;
|
||||
}
|
||||
|
||||
//
|
||||
// Non-member functions accepting an expression-template as argument:
|
||||
//
|
||||
#undef sqrt
|
||||
template <class Exp>
|
||||
typename boost::math::detail::expression_type<Exp>::type sqrt(const detail::big_number_exp<Exp>& val)
|
||||
{
|
||||
typedef typename detail::expression_type<Exp>::type result_type;
|
||||
return sqrt(result_type(val));
|
||||
}
|
||||
template <class Exp>
|
||||
typename detail::expression_type<Exp>::type abs(const detail::big_number_exp<Exp>& val)
|
||||
{
|
||||
typedef typename detail::expression_type<Exp>::type result_type;
|
||||
return abs(result_type(val));
|
||||
}
|
||||
template <class Exp>
|
||||
typename detail::expression_type<Exp>::type fabs(const detail::big_number_exp<Exp>& val)
|
||||
{
|
||||
typedef typename detail::expression_type<Exp>::type result_type;
|
||||
return fabs(result_type(val));
|
||||
}
|
||||
template <class Exp>
|
||||
typename detail::expression_type<Exp>::type ceil(const detail::big_number_exp<Exp>& val)
|
||||
{
|
||||
typedef typename detail::expression_type<Exp>::type result_type;
|
||||
return ceil(result_type(val));
|
||||
}
|
||||
template <class Exp>
|
||||
typename detail::expression_type<Exp>::type floor(const detail::big_number_exp<Exp>& val)
|
||||
{
|
||||
typedef typename detail::expression_type<Exp>::type result_type;
|
||||
return floor(result_type(val));
|
||||
}
|
||||
template <class Exp>
|
||||
typename detail::expression_type<Exp>::type trunc(const detail::big_number_exp<Exp>& val)
|
||||
{
|
||||
typedef typename detail::expression_type<Exp>::type result_type;
|
||||
return trunc(result_type(val));
|
||||
}
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif
|
||||
|
||||
463
include/boost/math/big_number/big_number_base.hpp
Normal file
463
include/boost/math/big_number/big_number_base.hpp
Normal file
@@ -0,0 +1,463 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright 2011 John Maddock. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_BIG_NUM_BASE_HPP
|
||||
#define BOOST_MATH_BIG_NUM_BASE_HPP
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
template <class Backend>
|
||||
class big_number;
|
||||
|
||||
namespace detail{
|
||||
|
||||
// Forward-declare an expression wrapper
|
||||
template<typename Expr>
|
||||
struct big_number_exp;
|
||||
//
|
||||
// Declare our grammars:
|
||||
//
|
||||
struct big_number_grammar
|
||||
: proto::or_<
|
||||
proto::terminal< proto::_ >
|
||||
, proto::plus< big_number_grammar, big_number_grammar >
|
||||
, proto::multiplies< big_number_grammar, big_number_grammar >
|
||||
, proto::minus< big_number_grammar, big_number_grammar >
|
||||
, proto::divides< big_number_grammar, big_number_grammar >
|
||||
, proto::unary_plus< big_number_grammar >
|
||||
, proto::negate< big_number_grammar >
|
||||
, proto::modulus<big_number_grammar, big_number_grammar>
|
||||
>
|
||||
{};
|
||||
|
||||
// Define a calculator domain. Expression within
|
||||
// the calculator domain will be wrapped in the
|
||||
// calculator<> expression wrapper.
|
||||
struct big_number_domain
|
||||
: proto::domain< proto::generator<big_number_exp>, big_number_grammar>
|
||||
{};
|
||||
|
||||
template<typename Expr>
|
||||
struct big_number_exp
|
||||
: proto::extends<Expr, big_number_exp<Expr>, big_number_domain>
|
||||
{
|
||||
typedef
|
||||
proto::extends<Expr, big_number_exp<Expr>, big_number_domain> base_type;
|
||||
|
||||
big_number_exp(Expr const &expr = Expr())
|
||||
: base_type(expr)
|
||||
{}
|
||||
template <class Other>
|
||||
big_number_exp(const Other& o)
|
||||
: base_type(o)
|
||||
{}
|
||||
};
|
||||
|
||||
struct CalcDepth
|
||||
: proto::or_<
|
||||
proto::when< proto::terminal<proto::_>,
|
||||
mpl::int_<0>()
|
||||
>
|
||||
, proto::when< proto::unary_expr<proto::_, CalcDepth>,
|
||||
CalcDepth(proto::_child)
|
||||
>
|
||||
, proto::when< proto::binary_expr<proto::_, CalcDepth, CalcDepth>,
|
||||
mpl::plus<mpl::max<CalcDepth(proto::_left),
|
||||
CalcDepth(proto::_right)>, mpl::int_<1> >()
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
template <int b>
|
||||
struct has_enough_bits
|
||||
{
|
||||
template <class T>
|
||||
struct type : public mpl::bool_<std::numeric_limits<T>::digits >= b>{};
|
||||
};
|
||||
|
||||
template <class Val, class Backend, class Tag>
|
||||
struct canonical_imp
|
||||
{
|
||||
typedef Val type;
|
||||
};
|
||||
template <class Val, class Backend>
|
||||
struct canonical_imp<Val, Backend, mpl::int_<0> >
|
||||
{
|
||||
typedef typename has_enough_bits<std::numeric_limits<Val>::digits>::template type<mpl::_> pred_type;
|
||||
typedef typename mpl::find_if<
|
||||
typename Backend::signed_types,
|
||||
pred_type
|
||||
>::type iter_type;
|
||||
typedef typename mpl::deref<iter_type>::type type;
|
||||
};
|
||||
template <class Val, class Backend>
|
||||
struct canonical_imp<Val, Backend, mpl::int_<1> >
|
||||
{
|
||||
typedef typename has_enough_bits<std::numeric_limits<Val>::digits>::template type<mpl::_> pred_type;
|
||||
typedef typename mpl::find_if<
|
||||
typename Backend::unsigned_types,
|
||||
pred_type
|
||||
>::type iter_type;
|
||||
typedef typename mpl::deref<iter_type>::type type;
|
||||
};
|
||||
template <class Val, class Backend>
|
||||
struct canonical_imp<Val, Backend, mpl::int_<2> >
|
||||
{
|
||||
typedef typename has_enough_bits<std::numeric_limits<Val>::digits>::template type<mpl::_> pred_type;
|
||||
typedef typename mpl::find_if<
|
||||
typename Backend::real_types,
|
||||
pred_type
|
||||
>::type iter_type;
|
||||
typedef typename mpl::deref<iter_type>::type type;
|
||||
};
|
||||
template <class Val, class Backend>
|
||||
struct canonical_imp<Val, Backend, mpl::int_<3> >
|
||||
{
|
||||
typedef const char* type;
|
||||
};
|
||||
|
||||
template <class Val, class Backend>
|
||||
struct canonical
|
||||
{
|
||||
typedef typename mpl::if_<
|
||||
is_signed<Val>,
|
||||
mpl::int_<0>,
|
||||
typename mpl::if_<
|
||||
is_unsigned<Val>,
|
||||
mpl::int_<1>,
|
||||
typename mpl::if_<
|
||||
is_floating_point<Val>,
|
||||
mpl::int_<2>,
|
||||
typename mpl::if_<
|
||||
mpl::or_<
|
||||
is_convertible<Val, const char*>,
|
||||
is_same<Val, std::string>
|
||||
>,
|
||||
mpl::int_<3>,
|
||||
mpl::int_<4>
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type tag_type;
|
||||
|
||||
typedef typename canonical_imp<Val, Backend, tag_type>::type type;
|
||||
};
|
||||
|
||||
template <class Exp, class tag>
|
||||
struct assign_and_eval_imp
|
||||
{
|
||||
typedef tag type;
|
||||
};
|
||||
|
||||
struct add_immediates{};
|
||||
struct add_and_negate_immediates{};
|
||||
struct subtract_immediates{};
|
||||
struct subtract_and_negate_immediates{};
|
||||
struct multiply_immediates{};
|
||||
struct multiply_and_negate_immediates{};
|
||||
struct divide_immediates{};
|
||||
struct divide_and_negate_immediates{};
|
||||
struct modulus_immediates{};
|
||||
|
||||
struct immediate{};
|
||||
struct negative_immediate{};
|
||||
|
||||
template <class Exp, class tag>
|
||||
struct immediate_type
|
||||
{
|
||||
typedef tag type;
|
||||
};
|
||||
template <class Exp>
|
||||
struct immediate_type<Exp, proto::tag::terminal>
|
||||
{
|
||||
typedef immediate type;
|
||||
};
|
||||
template <class Exp>
|
||||
struct immediate_type<Exp, proto::tag::unary_plus>
|
||||
{
|
||||
typedef typename proto::result_of::left<Exp>::type left_type;
|
||||
typedef typename proto::tag_of<left_type>::type left_tag;
|
||||
typedef typename mpl::if_<
|
||||
is_same<left_tag, proto::tag::terminal>,
|
||||
immediate,
|
||||
left_tag
|
||||
>::type type;
|
||||
};
|
||||
template <class Exp>
|
||||
struct immediate_type<Exp, proto::tag::negate>
|
||||
{
|
||||
typedef typename proto::result_of::left<Exp>::type left_type;
|
||||
typedef typename proto::tag_of<left_type>::type left_tag;
|
||||
typedef typename immediate_type<left_type, left_tag>::type tag;
|
||||
typedef typename mpl::if_<
|
||||
is_same<immediate, tag>,
|
||||
negative_immediate,
|
||||
tag
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class Exp>
|
||||
struct assign_and_eval_imp<Exp, proto::tag::plus>
|
||||
{
|
||||
typedef typename proto::result_of::left<Exp>::type left_type;
|
||||
typedef typename proto::result_of::right<Exp>::type right_type;
|
||||
typedef typename proto::tag_of<left_type>::type left_tag;
|
||||
typedef typename proto::tag_of<right_type>::type right_tag;
|
||||
typedef typename immediate_type<left_type, left_tag>::type left_imm;
|
||||
typedef typename immediate_type<right_type, right_tag>::type right_imm;
|
||||
typedef typename mpl::if_<
|
||||
mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, immediate> >,
|
||||
add_immediates,
|
||||
typename mpl::if_<
|
||||
mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, negative_immediate> >,
|
||||
subtract_immediates,
|
||||
typename mpl::if_<
|
||||
mpl::and_<is_same<left_imm, negative_immediate>, is_same<right_imm, immediate> >,
|
||||
subtract_and_negate_immediates,
|
||||
typename mpl::if_<
|
||||
mpl::and_<is_same<left_imm, negative_immediate>, is_same<right_imm, negative_immediate> >,
|
||||
add_and_negate_immediates,
|
||||
proto::tag::plus
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class Exp>
|
||||
struct assign_and_eval_imp<Exp, proto::tag::minus>
|
||||
{
|
||||
typedef typename proto::result_of::left<Exp>::type left_type;
|
||||
typedef typename proto::result_of::right<Exp>::type right_type;
|
||||
typedef typename proto::tag_of<left_type>::type left_tag;
|
||||
typedef typename proto::tag_of<right_type>::type right_tag;
|
||||
typedef typename immediate_type<left_type, left_tag>::type left_imm;
|
||||
typedef typename immediate_type<right_type, right_tag>::type right_imm;
|
||||
typedef typename mpl::if_<
|
||||
mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, immediate> >,
|
||||
subtract_immediates,
|
||||
typename mpl::if_<
|
||||
mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, negative_immediate> >,
|
||||
add_immediates,
|
||||
typename mpl::if_<
|
||||
mpl::and_<is_same<left_imm, negative_immediate>, is_same<right_imm, immediate> >,
|
||||
add_and_negate_immediates,
|
||||
typename mpl::if_<
|
||||
mpl::and_<is_same<left_imm, negative_immediate>, is_same<right_imm, negative_immediate> >,
|
||||
subtract_and_negate_immediates,
|
||||
proto::tag::minus
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class Exp>
|
||||
struct assign_and_eval_imp<Exp, proto::tag::multiplies>
|
||||
{
|
||||
typedef typename proto::result_of::left<Exp>::type left_type;
|
||||
typedef typename proto::result_of::right<Exp>::type right_type;
|
||||
typedef typename proto::tag_of<left_type>::type left_tag;
|
||||
typedef typename proto::tag_of<right_type>::type right_tag;
|
||||
typedef typename immediate_type<left_type, left_tag>::type left_imm;
|
||||
typedef typename immediate_type<right_type, right_tag>::type right_imm;
|
||||
typedef typename mpl::if_<
|
||||
mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, immediate> >,
|
||||
multiply_immediates,
|
||||
typename mpl::if_<
|
||||
mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, negative_immediate> >,
|
||||
multiply_and_negate_immediates,
|
||||
typename mpl::if_<
|
||||
mpl::and_<is_same<left_imm, negative_immediate>, is_same<right_imm, immediate> >,
|
||||
multiply_and_negate_immediates,
|
||||
typename mpl::if_<
|
||||
mpl::and_<is_same<left_imm, negative_immediate>, is_same<right_imm, negative_immediate> >,
|
||||
multiply_immediates,
|
||||
proto::tag::multiplies
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class Exp>
|
||||
struct assign_and_eval_imp<Exp, proto::tag::divides>
|
||||
{
|
||||
typedef typename proto::result_of::left<Exp>::type left_type;
|
||||
typedef typename proto::result_of::right<Exp>::type right_type;
|
||||
typedef typename proto::tag_of<left_type>::type left_tag;
|
||||
typedef typename proto::tag_of<right_type>::type right_tag;
|
||||
typedef typename immediate_type<left_type, left_tag>::type left_imm;
|
||||
typedef typename immediate_type<right_type, right_tag>::type right_imm;
|
||||
typedef typename mpl::if_<
|
||||
mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, immediate> >,
|
||||
divide_immediates,
|
||||
typename mpl::if_<
|
||||
mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, negative_immediate> >,
|
||||
divide_and_negate_immediates,
|
||||
typename mpl::if_<
|
||||
mpl::and_<is_same<left_imm, negative_immediate>, is_same<right_imm, immediate> >,
|
||||
divide_and_negate_immediates,
|
||||
typename mpl::if_<
|
||||
mpl::and_<is_same<left_imm, negative_immediate>, is_same<right_imm, negative_immediate> >,
|
||||
divide_immediates,
|
||||
proto::tag::divides
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class Exp>
|
||||
struct assign_and_eval_imp<Exp, proto::tag::modulus>
|
||||
{
|
||||
typedef typename proto::result_of::left<Exp>::type left_type;
|
||||
typedef typename proto::result_of::right<Exp>::type right_type;
|
||||
typedef typename proto::tag_of<left_type>::type left_tag;
|
||||
typedef typename proto::tag_of<right_type>::type right_tag;
|
||||
typedef typename immediate_type<left_type, left_tag>::type left_imm;
|
||||
typedef typename immediate_type<right_type, right_tag>::type right_imm;
|
||||
typedef typename mpl::if_<
|
||||
mpl::and_<is_same<left_imm, immediate>, is_same<right_imm, immediate> >,
|
||||
modulus_immediates,
|
||||
proto::tag::modulus
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class Exp>
|
||||
struct assign_and_eval
|
||||
{
|
||||
typedef typename proto::tag_of<Exp>::type tag_type;
|
||||
typedef typename assign_and_eval_imp<Exp, tag_type>::type type;
|
||||
};
|
||||
|
||||
template <class Exp, class tag>
|
||||
struct underlying_result_imp
|
||||
{
|
||||
typedef typename proto::result_of::left<Exp>::type left_type;
|
||||
typedef typename proto::tag_of<left_type>::type tag_type;
|
||||
typedef typename underlying_result_imp<left_type, tag_type>::type type;
|
||||
};
|
||||
|
||||
template <class Exp>
|
||||
struct underlying_result_imp<Exp, proto::tag::terminal>
|
||||
{
|
||||
typedef typename proto::result_of::value<Exp const &>::type type;
|
||||
};
|
||||
|
||||
template <class Exp>
|
||||
struct underlying_result
|
||||
{
|
||||
typedef typename proto::tag_of<Exp>::type tag_type;
|
||||
typedef typename underlying_result_imp<Exp, tag_type>::type type;
|
||||
};
|
||||
|
||||
template <class Exp1, class Exp2>
|
||||
struct combine_expression_type
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template <class Backend>
|
||||
struct combine_expression_type<boost::math::big_number<Backend>, boost::math::big_number<Backend> >
|
||||
{
|
||||
typedef boost::math::big_number<Backend> type;
|
||||
};
|
||||
|
||||
template <class Backend, class Exp>
|
||||
struct combine_expression_type<boost::math::big_number<Backend>, Exp>
|
||||
{
|
||||
typedef boost::math::big_number<Backend> type;
|
||||
};
|
||||
|
||||
template <class Backend, class Exp>
|
||||
struct combine_expression_type<Exp, boost::math::big_number<Backend> >
|
||||
{
|
||||
typedef boost::math::big_number<Backend> type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_big_number : public mpl::false_{};
|
||||
template <class T>
|
||||
struct is_big_number<boost::math::big_number<T> > : public mpl::true_{};
|
||||
template <class T>
|
||||
struct is_big_number_exp : public mpl::false_{};
|
||||
template <class T>
|
||||
struct is_big_number_exp<boost::math::detail::big_number_exp<T> > : public mpl::true_{};
|
||||
|
||||
|
||||
template <class Exp, int arity>
|
||||
struct expression_type_imp;
|
||||
|
||||
template <class Exp>
|
||||
struct expression_type_imp<Exp, 0>
|
||||
{
|
||||
typedef typename remove_pointer<typename proto::result_of::value<Exp>::type>::type type;
|
||||
};
|
||||
|
||||
template <class Exp>
|
||||
struct expression_type_imp<Exp, 1>
|
||||
{
|
||||
typedef typename proto::result_of::left<Exp>::type nested_type;
|
||||
typedef typename expression_type_imp<nested_type, proto::arity_of<nested_type>::value>::type type;
|
||||
};
|
||||
|
||||
template <class Exp>
|
||||
struct expression_type_imp<Exp, 2>
|
||||
{
|
||||
typedef typename proto::result_of::left<Exp>::type left_type;
|
||||
typedef typename proto::result_of::right<Exp>::type right_type;
|
||||
typedef typename expression_type_imp<left_type, proto::arity_of<left_type>::value>::type left_result;
|
||||
typedef typename expression_type_imp<right_type, proto::arity_of<right_type>::value>::type right_result;
|
||||
typedef typename combine_expression_type<left_result, right_result>::type type;
|
||||
};
|
||||
|
||||
template <class Exp>
|
||||
struct expression_type_imp<Exp, 3>
|
||||
{
|
||||
typedef typename proto::result_of::left<Exp>::type left_type;
|
||||
typedef typename proto::result_of::right<Exp>::type right_type;
|
||||
typedef typename proto::result_of::child_c<Exp, 2>::type end_type;
|
||||
typedef typename expression_type_imp<left_type, proto::arity_of<left_type>::value>::type left_result;
|
||||
typedef typename expression_type_imp<right_type, proto::arity_of<right_type>::value>::type right_result;
|
||||
typedef typename expression_type_imp<end_type, proto::arity_of<end_type>::value>::type end_result;
|
||||
typedef typename combine_expression_type<left_result, typename combine_expression_type<right_result, end_type>::type>::type type;
|
||||
};
|
||||
|
||||
template <class Exp>
|
||||
struct expression_type
|
||||
{
|
||||
typedef typename expression_type_imp<Exp, proto::arity_of<Exp>::value>::type type;
|
||||
};
|
||||
|
||||
template <class Exp>
|
||||
struct backend_type
|
||||
{
|
||||
typedef typename expression_type<Exp>::type num_type;
|
||||
typedef typename backend_type<num_type>::type type;
|
||||
};
|
||||
|
||||
template <class Backend>
|
||||
struct backend_type<boost::math::big_number<Backend> >
|
||||
{
|
||||
typedef Backend type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
//
|
||||
// Traits class, lets us know whether a backend is an integer type, otherwise assumed to be a real number type:
|
||||
//
|
||||
template <class Num>
|
||||
struct is_extended_integer : public mpl::false_ {};
|
||||
template <class Backend>
|
||||
struct is_extended_integer<big_number<Backend> > : public is_extended_integer<Backend>{};
|
||||
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_BIG_NUM_BASE_HPP
|
||||
|
||||
|
||||
302
include/boost/math/big_number/default_ops.hpp
Normal file
302
include/boost/math/big_number/default_ops.hpp
Normal file
@@ -0,0 +1,302 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright 2011 John Maddock. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_BIG_NUM_DEF_OPS
|
||||
#define BOOST_MATH_BIG_NUM_DEF_OPS
|
||||
|
||||
#include <boost/math/big_number/big_number_base.hpp>
|
||||
|
||||
namespace boost{ namespace math{ namespace big_num_default_ops{
|
||||
|
||||
//
|
||||
// Default versions of mixed arithmetic, these just construct a temporary
|
||||
// from the arithmetic value and then do the arithmetic on that:
|
||||
//
|
||||
template <class T, class V>
|
||||
inline typename enable_if<mpl::or_<is_arithmetic<V>, is_convertible<V, const char*>, is_same<V, std::string> > >::type
|
||||
add(T& result, V const& v)
|
||||
{
|
||||
T t;
|
||||
t = v;
|
||||
add(result, t);
|
||||
}
|
||||
template <class T, class V>
|
||||
inline typename enable_if<mpl::or_<is_arithmetic<V>, is_convertible<V, const char*>, is_same<V, std::string> > >::type
|
||||
subtract(T& result, V const& v)
|
||||
{
|
||||
T t;
|
||||
t = v;
|
||||
subtract(result, t);
|
||||
}
|
||||
template <class T, class V>
|
||||
inline typename enable_if<mpl::or_<is_arithmetic<V>, is_convertible<V, const char*>, is_same<V, std::string> > >::type
|
||||
multiply(T& result, V const& v)
|
||||
{
|
||||
T t;
|
||||
t = v;
|
||||
multiply(result, t);
|
||||
}
|
||||
template <class T, class V>
|
||||
inline typename enable_if<mpl::or_<is_arithmetic<V>, is_convertible<V, const char*>, is_same<V, std::string> > >::type
|
||||
divide(T& result, V const& v)
|
||||
{
|
||||
T t;
|
||||
t = v;
|
||||
divide(result, t);
|
||||
}
|
||||
template <class T, class V>
|
||||
inline typename enable_if<mpl::or_<is_arithmetic<V>, is_convertible<V, const char*>, is_same<V, std::string> > >::type
|
||||
modulus(T& result, V const& v)
|
||||
{
|
||||
T t;
|
||||
t = v;
|
||||
mudulus(result, t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool is_same_object(const T& u, const T&v)
|
||||
{ return &u == &v; }
|
||||
template <class T, class U>
|
||||
inline bool is_same_object(const T& u, const U&v)
|
||||
{ return false; }
|
||||
|
||||
//
|
||||
// Default versions of 3-arg arithmetic functions, these just forward to the 2 arg versions:
|
||||
//
|
||||
template <class T, class U, class V>
|
||||
inline void add(T& t, const U& u, const V& v)
|
||||
{
|
||||
if(is_same_object(t, v))
|
||||
{
|
||||
add(t, u);
|
||||
}
|
||||
else if(is_same_object(t, u))
|
||||
{
|
||||
add(t, v);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = u;
|
||||
add(t, v);
|
||||
}
|
||||
}
|
||||
template <class T, class U, class V>
|
||||
inline void subtract(T& t, const U& u, const V& v)
|
||||
{
|
||||
if(is_same_object(t, u))
|
||||
subtract(t, v);
|
||||
else if(is_same_object(t, v))
|
||||
{
|
||||
subtract(t, u);
|
||||
t.negate();
|
||||
}
|
||||
else
|
||||
{
|
||||
t = u;
|
||||
subtract(t, v);
|
||||
}
|
||||
}
|
||||
template <class T, class U, class V>
|
||||
inline void multiply(T& t, const U& u, const V& v)
|
||||
{
|
||||
if(is_same_object(t, u))
|
||||
multiply(t, v);
|
||||
else if(is_same_object(t, v))
|
||||
multiply(t, u);
|
||||
else
|
||||
{
|
||||
t = u;
|
||||
multiply(t, v);
|
||||
}
|
||||
}
|
||||
template <class T, class U, class V>
|
||||
inline void divide(T& t, const U& u, const V& v)
|
||||
{
|
||||
if(is_same_object(t, u))
|
||||
divide(t, v);
|
||||
else if(is_same_object(t, v))
|
||||
{
|
||||
T temp = t;
|
||||
divide(temp, u, v);
|
||||
temp.swap(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = u;
|
||||
divide(t, v);
|
||||
}
|
||||
}
|
||||
template <class T, class U, class V>
|
||||
inline void modulus(T& t, const U& u, const V& v)
|
||||
{
|
||||
if(is_same_object(t, u))
|
||||
modulus(t, v);
|
||||
else if(is_same_object(t, v))
|
||||
{
|
||||
T temp;
|
||||
modulus(temp, u, v);
|
||||
temp.swap(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = u;
|
||||
modulus(t, v);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Functions:
|
||||
//
|
||||
template <class T>
|
||||
void abs(T* result, const T& arg)
|
||||
{
|
||||
typedef typename T::signed_types type_list;
|
||||
typedef typename mpl::front<type_list>::type front;
|
||||
*result = arg;
|
||||
if(arg.compare(front(0)) < 0)
|
||||
result->negate();
|
||||
}
|
||||
template <class T>
|
||||
void fabs(T* result, const T& arg)
|
||||
{
|
||||
typedef typename T::signed_types type_list;
|
||||
typedef typename mpl::front<type_list>::type front;
|
||||
*result = arg;
|
||||
if(arg.compare(front(0)) < 0)
|
||||
result->negate();
|
||||
}
|
||||
|
||||
//
|
||||
// These have to implemented by the backend, declared here so that our macro generated code compiles OK.
|
||||
//
|
||||
template <class T>
|
||||
typename enable_if_c<sizeof(T) == 0>::type floor();
|
||||
template <class T>
|
||||
typename enable_if_c<sizeof(T) == 0>::type ceil();
|
||||
template <class T>
|
||||
typename enable_if_c<sizeof(T) == 0>::type trunc();
|
||||
template <class T>
|
||||
typename enable_if_c<sizeof(T) == 0>::type sqrt();
|
||||
template <class T>
|
||||
typename enable_if_c<sizeof(T) == 0>::type ldexp();
|
||||
template <class T>
|
||||
typename enable_if_c<sizeof(T) == 0>::type frexp();
|
||||
|
||||
}
|
||||
|
||||
|
||||
template <class Backend>
|
||||
class big_number;
|
||||
|
||||
namespace detail{
|
||||
|
||||
template<typename Expr>
|
||||
struct big_number_exp;
|
||||
|
||||
}
|
||||
|
||||
#define UNARY_OP_FUNCTOR(func)\
|
||||
namespace detail{\
|
||||
template <class Backend>\
|
||||
struct BOOST_JOIN(func, _funct)\
|
||||
{\
|
||||
void operator()(Backend* result, const Backend& arg)const\
|
||||
{\
|
||||
using big_num_default_ops::func;\
|
||||
func(result, arg);\
|
||||
}\
|
||||
};\
|
||||
\
|
||||
}\
|
||||
\
|
||||
template <class Exp>\
|
||||
typename proto::result_of::make_expr<\
|
||||
proto::tag::function\
|
||||
, detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<Exp>::type>\
|
||||
, detail::big_number_exp<Exp>\
|
||||
>::type const \
|
||||
func(const detail::big_number_exp<Exp>& arg)\
|
||||
{\
|
||||
return proto::make_expr<proto::tag::function>(\
|
||||
detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<Exp>::type>() \
|
||||
, arg \
|
||||
);\
|
||||
}\
|
||||
template <class Backend>\
|
||||
typename proto::result_of::make_expr<\
|
||||
proto::tag::function\
|
||||
, detail::BOOST_JOIN(func, _funct)<Backend>\
|
||||
, detail::big_number_exp<typename proto::terminal<big_number<Backend>*>::type>\
|
||||
>::type const \
|
||||
func(const big_number<Backend>& arg)\
|
||||
{\
|
||||
return proto::make_expr<proto::tag::function>(\
|
||||
detail::BOOST_JOIN(func, _funct)<Backend>() \
|
||||
, static_cast<const detail::big_number_exp<typename proto::terminal<big_number<Backend>*>::type>&>(arg) \
|
||||
);\
|
||||
}
|
||||
|
||||
#define BINARY_OP_FUNCTOR(func)\
|
||||
namespace detail{\
|
||||
template <class Backend>\
|
||||
struct BOOST_JOIN(func, _funct)\
|
||||
{\
|
||||
template <class A2>\
|
||||
void operator()(Backend* result, const Backend& arg, const A2& a)const\
|
||||
{\
|
||||
using big_num_default_ops::func;\
|
||||
func(result, arg, a);\
|
||||
}\
|
||||
};\
|
||||
\
|
||||
}\
|
||||
\
|
||||
template <class Exp, class A2>\
|
||||
typename proto::result_of::make_expr<\
|
||||
proto::tag::function\
|
||||
, detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<Exp>::type>\
|
||||
, detail::big_number_exp<Exp>\
|
||||
, typename proto::result_of::as_child<const A2&>::type\
|
||||
>::type const \
|
||||
func(const detail::big_number_exp<Exp>& arg, const A2& a)\
|
||||
{\
|
||||
return proto::make_expr<proto::tag::function>(\
|
||||
detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<Exp>::type>() \
|
||||
, arg, proto::as_child(a) \
|
||||
);\
|
||||
}\
|
||||
template <class Backend, class A2>\
|
||||
typename proto::result_of::make_expr<\
|
||||
proto::tag::function\
|
||||
, detail::BOOST_JOIN(func, _funct)<Backend>\
|
||||
, detail::big_number_exp<typename proto::terminal<big_number<Backend>*>::type>\
|
||||
, typename proto::result_of::as_child<const A2&>::type\
|
||||
>::type const \
|
||||
func(const big_number<Backend>& arg, const A2& a)\
|
||||
{\
|
||||
return proto::make_expr<proto::tag::function>(\
|
||||
detail::BOOST_JOIN(func, _funct)<Backend>() \
|
||||
, static_cast<const detail::big_number_exp<typename proto::terminal<big_number<Backend>*>::type>&>(arg),\
|
||||
proto::as_child(a)\
|
||||
);\
|
||||
}
|
||||
|
||||
UNARY_OP_FUNCTOR(abs)
|
||||
UNARY_OP_FUNCTOR(fabs)
|
||||
UNARY_OP_FUNCTOR(sqrt)
|
||||
UNARY_OP_FUNCTOR(floor)
|
||||
UNARY_OP_FUNCTOR(ceil)
|
||||
UNARY_OP_FUNCTOR(trunc)
|
||||
|
||||
BINARY_OP_FUNCTOR(ldexp)
|
||||
BINARY_OP_FUNCTOR(frexp)
|
||||
|
||||
#undef BINARY_OP_FUNCTOR
|
||||
#undef UNARY_OP_FUNCTOR
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif
|
||||
|
||||
@@ -145,130 +145,45 @@ struct gmp_real_imp
|
||||
mpf_set_str(m_data, s, 10);
|
||||
return *this;
|
||||
}
|
||||
gmp_real_imp& operator += (const gmp_real<digits10>& o)
|
||||
{
|
||||
mpf_add(m_data, m_data, o.m_data);
|
||||
return *this;
|
||||
}
|
||||
template <class V>
|
||||
gmp_real_imp& operator += (V v)
|
||||
{
|
||||
gmp_real<digits10> d;
|
||||
d = v;
|
||||
return *this += d;
|
||||
}
|
||||
gmp_real_imp& operator -= (const gmp_real<digits10>& o)
|
||||
{
|
||||
mpf_sub(m_data, m_data, o.m_data);
|
||||
return *this;
|
||||
}
|
||||
template <class V>
|
||||
gmp_real_imp& operator -= (V v)
|
||||
{
|
||||
gmp_real<digits10> d;
|
||||
d = v;
|
||||
return *this -= d;
|
||||
}
|
||||
gmp_real_imp& operator *= (const gmp_real<digits10>& o)
|
||||
{
|
||||
mpf_mul(m_data, m_data, o.m_data);
|
||||
return *this;
|
||||
}
|
||||
template <class V>
|
||||
gmp_real_imp& operator *= (V v)
|
||||
{
|
||||
gmp_real<digits10> d;
|
||||
d = v;
|
||||
return *this *= d;
|
||||
}
|
||||
gmp_real_imp& operator /= (const gmp_real<digits10>& o)
|
||||
{
|
||||
mpf_div(m_data, m_data, o.m_data);
|
||||
return *this;
|
||||
}
|
||||
template <class V>
|
||||
gmp_real_imp& operator /= (V v)
|
||||
{
|
||||
gmp_real<digits10> d;
|
||||
d = v;
|
||||
return *this /= d;
|
||||
}
|
||||
gmp_real_imp& operator += (unsigned long i)
|
||||
{
|
||||
mpf_add_ui(m_data, m_data, i);
|
||||
return *this;
|
||||
}
|
||||
gmp_real_imp& operator -= (unsigned long i)
|
||||
{
|
||||
mpf_sub_ui(m_data, m_data, i);
|
||||
return *this;
|
||||
}
|
||||
gmp_real_imp& operator *= (unsigned long i)
|
||||
{
|
||||
mpf_mul_ui(m_data, m_data, i);
|
||||
return *this;
|
||||
}
|
||||
gmp_real_imp& operator /= (unsigned long i)
|
||||
{
|
||||
mpf_div_ui(m_data, m_data, i);
|
||||
return *this;
|
||||
}
|
||||
gmp_real_imp& operator += (long i)
|
||||
{
|
||||
if(i > 0)
|
||||
mpf_add_ui(m_data, m_data, i);
|
||||
else
|
||||
mpf_sub_ui(m_data, m_data, std::abs(i));
|
||||
return *this;
|
||||
}
|
||||
gmp_real_imp& operator -= (long i)
|
||||
{
|
||||
if(i > 0)
|
||||
mpf_sub_ui(m_data, m_data, i);
|
||||
else
|
||||
mpf_add_ui(m_data, m_data, std::abs(i));
|
||||
return *this;
|
||||
}
|
||||
gmp_real_imp& operator *= (long i)
|
||||
{
|
||||
mpf_mul_ui(m_data, m_data, std::abs(i));
|
||||
if(i < 0)
|
||||
mpf_neg(m_data, m_data);
|
||||
return *this;
|
||||
}
|
||||
gmp_real_imp& operator /= (long i)
|
||||
{
|
||||
mpf_div_ui(m_data, m_data, std::abs(i));
|
||||
if(i < 0)
|
||||
mpf_neg(m_data, m_data);
|
||||
return *this;
|
||||
}
|
||||
void swap(gmp_real_imp& o)
|
||||
{
|
||||
mpf_swap(m_data, o.m_data);
|
||||
}
|
||||
std::string str(unsigned digits)const
|
||||
std::string str(unsigned digits, bool scientific)const
|
||||
{
|
||||
std::string result;
|
||||
mp_exp_t e;
|
||||
void *(*alloc_func_ptr) (size_t);
|
||||
void *(*realloc_func_ptr) (void *, size_t, size_t);
|
||||
void (*free_func_ptr) (void *, size_t);
|
||||
const char* ps = mpf_get_str (0, &e, 10, digits, m_data);
|
||||
std::string s("0.");
|
||||
if(ps[0] == '-')
|
||||
std::ptrdiff_t sl = std::strlen(ps);
|
||||
if(sl == 0)
|
||||
return "0";
|
||||
if(*ps == '-')
|
||||
--sl; // number of digits excluding sign.
|
||||
if(!scientific
|
||||
&& (sl <= std::numeric_limits<boost::uintmax_t>::digits10 + 1)
|
||||
&& (e >= sl)
|
||||
&& (sl <= std::numeric_limits<boost::uintmax_t>::digits10 + 1))
|
||||
{
|
||||
s.insert(0, ps, 1);
|
||||
s += ps + 1;
|
||||
result = ps;
|
||||
result.append(e-sl, '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
s += ps;
|
||||
result = ps;
|
||||
if(ps[0] == '-')
|
||||
result.insert(2, 1, '.');
|
||||
else
|
||||
result.insert(1, 1, '.');
|
||||
--e;
|
||||
if(e)
|
||||
result += "e" + lexical_cast<std::string>(e);
|
||||
}
|
||||
s += "e";
|
||||
s += boost::lexical_cast<std::string>(e);
|
||||
mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
|
||||
(*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
|
||||
return s;
|
||||
return result;
|
||||
}
|
||||
~gmp_real_imp()
|
||||
{
|
||||
@@ -400,74 +315,280 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
template <unsigned digits10>
|
||||
inline void add(gmp_real<digits10>& result, const gmp_real<digits10>& o)
|
||||
{
|
||||
mpf_add(result.data(), result.data(), o.data());
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void subtract(gmp_real<digits10>& result, const gmp_real<digits10>& o)
|
||||
{
|
||||
mpf_sub(result.data(), result.data(), o.data());
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void multiply(gmp_real<digits10>& result, const gmp_real<digits10>& o)
|
||||
{
|
||||
mpf_mul(result.data(), result.data(), o.data());
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void divide(gmp_real<digits10>& result, const gmp_real<digits10>& o)
|
||||
{
|
||||
mpf_div(result.data(), result.data(), o.data());
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void add(gmp_real<digits10>& result, unsigned long i)
|
||||
{
|
||||
mpf_add_ui(result.data(), result.data(), i);
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void subtract(gmp_real<digits10>& result, unsigned long i)
|
||||
{
|
||||
mpf_sub_ui(result.data(), result.data(), i);
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void multiply(gmp_real<digits10>& result, unsigned long i)
|
||||
{
|
||||
mpf_mul_ui(result.data(), result.data(), i);
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void divide(gmp_real<digits10>& result, unsigned long i)
|
||||
{
|
||||
mpf_div_ui(result.data(), result.data(), i);
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void add(gmp_real<digits10>& result, long i)
|
||||
{
|
||||
if(i > 0)
|
||||
mpf_add_ui(result.data(), result.data(), i);
|
||||
else
|
||||
mpf_sub_ui(result.data(), result.data(), std::abs(i));
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void subtract(gmp_real<digits10>& result, long i)
|
||||
{
|
||||
if(i > 0)
|
||||
mpf_sub_ui(result.data(), result.data(), i);
|
||||
else
|
||||
mpf_add_ui(result.data(), result.data(), std::abs(i));
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void multiply(gmp_real<digits10>& result, long i)
|
||||
{
|
||||
mpf_mul_ui(result.data(), result.data(), std::abs(i));
|
||||
if(i < 0)
|
||||
mpf_neg(result.data(), result.data());
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void divide(gmp_real<digits10>& result, long i)
|
||||
{
|
||||
mpf_div_ui(result.data(), result.data(), std::abs(i));
|
||||
if(i < 0)
|
||||
mpf_neg(result.data(), result.data());
|
||||
}
|
||||
//
|
||||
// Specialised 3 arg versions of the basic operators:
|
||||
//
|
||||
template <unsigned digits10>
|
||||
inline void add(gmp_real<digits10>& a, const gmp_real<digits10>& x, const gmp_real<digits10>& y)
|
||||
{
|
||||
mpf_add(a.data(), x.data(), y.data());
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void add(gmp_real<digits10>& a, const gmp_real<digits10>& x, unsigned long y)
|
||||
{
|
||||
mpf_add_ui(a.data(), x.data(), y);
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void add(gmp_real<digits10>& a, const gmp_real<digits10>& x, long y)
|
||||
{
|
||||
if(y < 0)
|
||||
mpf_sub_ui(a.data(), x.data(), -y);
|
||||
else
|
||||
mpf_add_ui(a.data(), x.data(), y);
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void add(gmp_real<digits10>& a, unsigned long x, const gmp_real<digits10>& y)
|
||||
{
|
||||
mpf_add_ui(a.data(), y.data(), x);
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void add(gmp_real<digits10>& a, long x, const gmp_real<digits10>& y)
|
||||
{
|
||||
if(x < 0)
|
||||
{
|
||||
mpf_ui_sub(a.data(), -x, y.data());
|
||||
mpf_neg(a.data(), a.data());
|
||||
}
|
||||
else
|
||||
mpf_add_ui(a.data(), y.data(), x);
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void subtract(gmp_real<digits10>& a, const gmp_real<digits10>& x, const gmp_real<digits10>& y)
|
||||
{
|
||||
mpf_sub(a.data(), x.data(), y.data());
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void subtract(gmp_real<digits10>& a, const gmp_real<digits10>& x, unsigned long y)
|
||||
{
|
||||
mpf_sub_ui(a.data(), x.data(), y);
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void subtract(gmp_real<digits10>& a, const gmp_real<digits10>& x, long y)
|
||||
{
|
||||
if(y < 0)
|
||||
mpf_add_ui(a.data(), x.data(), -y);
|
||||
else
|
||||
mpf_sub_ui(a.data(), x.data(), y);
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void subtract(gmp_real<digits10>& a, unsigned long x, const gmp_real<digits10>& y)
|
||||
{
|
||||
mpf_ui_sub(a.data(), x, y.data());
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void subtract(gmp_real<digits10>& a, long x, const gmp_real<digits10>& y)
|
||||
{
|
||||
if(x < 0)
|
||||
{
|
||||
mpf_add_ui(a.data(), y.data(), -x);
|
||||
mpf_neg(a.data(), a.data());
|
||||
}
|
||||
else
|
||||
mpf_ui_sub(a.data(), x, y.data());
|
||||
}
|
||||
|
||||
template <unsigned digits10>
|
||||
inline void multiply(gmp_real<digits10>& a, const gmp_real<digits10>& x, const gmp_real<digits10>& y)
|
||||
{
|
||||
mpf_mul(a.data(), x.data(), y.data());
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void multiply(gmp_real<digits10>& a, const gmp_real<digits10>& x, unsigned long y)
|
||||
{
|
||||
mpf_mul_ui(a.data(), x.data(), y);
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void multiply(gmp_real<digits10>& a, const gmp_real<digits10>& x, long y)
|
||||
{
|
||||
if(y < 0)
|
||||
{
|
||||
mpf_mul_ui(a.data(), x.data(), -y);
|
||||
a.negate();
|
||||
}
|
||||
else
|
||||
mpf_mul_ui(a.data(), x.data(), y);
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void multiply(gmp_real<digits10>& a, unsigned long x, const gmp_real<digits10>& y)
|
||||
{
|
||||
mpf_mul_ui(a.data(), y.data(), x);
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void multiply(gmp_real<digits10>& a, long x, const gmp_real<digits10>& y)
|
||||
{
|
||||
if(x < 0)
|
||||
{
|
||||
mpf_mul_ui(a.data(), y.data(), -x);
|
||||
mpf_neg(a.data(), a.data());
|
||||
}
|
||||
else
|
||||
mpf_mul_ui(a.data(), y.data(), x);
|
||||
}
|
||||
|
||||
template <unsigned digits10>
|
||||
inline void divide(gmp_real<digits10>& a, const gmp_real<digits10>& x, const gmp_real<digits10>& y)
|
||||
{
|
||||
mpf_div(a.data(), x.data(), y.data());
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void divide(gmp_real<digits10>& a, const gmp_real<digits10>& x, unsigned long y)
|
||||
{
|
||||
mpf_div_ui(a.data(), x.data(), y);
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void divide(gmp_real<digits10>& a, const gmp_real<digits10>& x, long y)
|
||||
{
|
||||
if(y < 0)
|
||||
{
|
||||
mpf_div_ui(a.data(), x.data(), -y);
|
||||
a.negate();
|
||||
}
|
||||
else
|
||||
mpf_div_ui(a.data(), x.data(), y);
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void divide(gmp_real<digits10>& a, unsigned long x, const gmp_real<digits10>& y)
|
||||
{
|
||||
mpf_ui_div(a.data(), x, y.data());
|
||||
}
|
||||
template <unsigned digits10>
|
||||
inline void divide(gmp_real<digits10>& a, long x, const gmp_real<digits10>& y)
|
||||
{
|
||||
if(x < 0)
|
||||
{
|
||||
mpf_ui_div(a.data(), -x, y.data());
|
||||
mpf_neg(a.data(), a.data());
|
||||
}
|
||||
else
|
||||
mpf_ui_div(a.data(), x, y.data());
|
||||
}
|
||||
|
||||
//
|
||||
// Native non-member operations:
|
||||
//
|
||||
template <unsigned Digits10>
|
||||
big_number<gmp_real<Digits10> > sqrt(const big_number<gmp_real<Digits10> >& val)
|
||||
inline void sqrt(gmp_real<Digits10>* result, const gmp_real<Digits10>& val)
|
||||
{
|
||||
big_number<gmp_real<Digits10> > result;
|
||||
mpf_sqrt(result.backend().data(), val.backend().data());
|
||||
return result;
|
||||
mpf_sqrt(result->data(), val.data());
|
||||
}
|
||||
|
||||
template <unsigned Digits10>
|
||||
inline void abs(gmp_real<Digits10>* result, const gmp_real<Digits10>& val)
|
||||
{
|
||||
mpf_abs(result->data(), val.data());
|
||||
}
|
||||
|
||||
template <unsigned Digits10>
|
||||
inline void fabs(gmp_real<Digits10>* result, const gmp_real<Digits10>& val)
|
||||
{
|
||||
mpf_abs(result->data(), val.data());
|
||||
}
|
||||
template <unsigned Digits10>
|
||||
big_number<gmp_real<Digits10> > abs(const big_number<gmp_real<Digits10> >& val)
|
||||
inline void ceil(gmp_real<Digits10>* result, const gmp_real<Digits10>& val)
|
||||
{
|
||||
big_number<gmp_real<Digits10> > result;
|
||||
mpf_abs(result.backend().data(), val.backend().data());
|
||||
return result;
|
||||
mpf_ceil(result->data(), val.data());
|
||||
}
|
||||
template <unsigned Digits10>
|
||||
big_number<gmp_real<Digits10> > fabs(const big_number<gmp_real<Digits10> >& val)
|
||||
inline void floor(gmp_real<Digits10>* result, const gmp_real<Digits10>& val)
|
||||
{
|
||||
big_number<gmp_real<Digits10> > result;
|
||||
mpf_abs(result.backend().data(), val.backend().data());
|
||||
return result;
|
||||
mpf_floor(result->data(), val.data());
|
||||
}
|
||||
template <unsigned Digits10>
|
||||
big_number<gmp_real<Digits10> > ceil(const big_number<gmp_real<Digits10> >& val)
|
||||
inline void trunc(gmp_real<Digits10>* result, const gmp_real<Digits10>& val)
|
||||
{
|
||||
big_number<gmp_real<Digits10> > result;
|
||||
mpf_ceil(result.backend().data(), val.backend().data());
|
||||
return result;
|
||||
mpf_trunc(result->data(), val.data());
|
||||
}
|
||||
template <unsigned Digits10>
|
||||
big_number<gmp_real<Digits10> > floor(const big_number<gmp_real<Digits10> >& val)
|
||||
inline void ldexp(gmp_real<Digits10>* result, const gmp_real<Digits10>& val, long e)
|
||||
{
|
||||
big_number<gmp_real<Digits10> > result;
|
||||
mpf_floor(result.backend().data(), val.backend().data());
|
||||
return result;
|
||||
}
|
||||
template <unsigned Digits10>
|
||||
big_number<gmp_real<Digits10> > trunc(const big_number<gmp_real<Digits10> >& val)
|
||||
{
|
||||
big_number<gmp_real<Digits10> > result;
|
||||
mpf_trunc(result.backend().data(), val.backend().data());
|
||||
return result;
|
||||
}
|
||||
template <unsigned Digits10>
|
||||
big_number<gmp_real<Digits10> > ldexp(const big_number<gmp_real<Digits10> >& val, long e)
|
||||
{
|
||||
big_number<gmp_real<Digits10> > result;
|
||||
if(e > 0)
|
||||
mpf_mul_2exp(result.backend().data(), val.backend().data(), e);
|
||||
mpf_mul_2exp(result->data(), val.data(), e);
|
||||
else if(e < 0)
|
||||
mpf_div_2exp(result.backend().data(), val.backend().data(), -e);
|
||||
return result;
|
||||
mpf_div_2exp(result->data(), val.data(), -e);
|
||||
}
|
||||
template <unsigned Digits10>
|
||||
big_number<gmp_real<Digits10> > frexp(const big_number<gmp_real<Digits10> >& val, int* e)
|
||||
inline void frexp(gmp_real<Digits10>* result, const gmp_real<Digits10>& val, int* e)
|
||||
{
|
||||
long v;
|
||||
mpf_get_d_2exp(&v, val.backend().data());
|
||||
mpf_get_d_2exp(&v, val.data());
|
||||
*e = v;
|
||||
return ldexp(val, -v);
|
||||
return ldexp(result, val, -v);
|
||||
}
|
||||
template <unsigned Digits10>
|
||||
big_number<gmp_real<Digits10> > frexp(const big_number<gmp_real<Digits10> >& val, long* e)
|
||||
inline void frexp(gmp_real<Digits10>* result, const gmp_real<Digits10>& val, long* e)
|
||||
{
|
||||
mpf_get_d_2exp(e, val.backend().data());
|
||||
return ldexp(val, -*e);
|
||||
mpf_get_d_2exp(e, val.data());
|
||||
return ldexp(result, val, -*e);
|
||||
}
|
||||
|
||||
struct gmp_int
|
||||
@@ -582,163 +703,11 @@ struct gmp_int
|
||||
mpz_set_str(m_data, s, 10);
|
||||
return *this;
|
||||
}
|
||||
gmp_int& operator += (const gmp_int& o)
|
||||
{
|
||||
mpz_add(m_data, m_data, o.m_data);
|
||||
return *this;
|
||||
}
|
||||
template <class V>
|
||||
gmp_int& operator += (V v)
|
||||
{
|
||||
gmp_int d;
|
||||
d = v;
|
||||
return *this += d;
|
||||
}
|
||||
gmp_int& operator -= (const gmp_int& o)
|
||||
{
|
||||
mpz_sub(m_data, m_data, o.m_data);
|
||||
return *this;
|
||||
}
|
||||
template <class V>
|
||||
gmp_int& operator -= (V v)
|
||||
{
|
||||
gmp_int d;
|
||||
d = v;
|
||||
return *this -= d;
|
||||
}
|
||||
gmp_int& operator *= (const gmp_int& o)
|
||||
{
|
||||
mpz_mul(m_data, m_data, o.m_data);
|
||||
return *this;
|
||||
}
|
||||
template <class V>
|
||||
gmp_int& operator *= (V v)
|
||||
{
|
||||
gmp_int d;
|
||||
d = v;
|
||||
return *this *= d;
|
||||
}
|
||||
gmp_int& operator /= (const gmp_int& o)
|
||||
{
|
||||
mpz_div(m_data, m_data, o.m_data);
|
||||
return *this;
|
||||
}
|
||||
template <class V>
|
||||
gmp_int& operator /= (V v)
|
||||
{
|
||||
gmp_int d;
|
||||
d = v;
|
||||
return *this /= d;
|
||||
}
|
||||
gmp_int& operator %= (const gmp_int& o)
|
||||
{
|
||||
bool neg = mpz_sgn(m_data) < 0;
|
||||
bool neg2 = mpz_sgn(o.m_data) < 0;
|
||||
mpz_mod(m_data, m_data, o.m_data);
|
||||
if(neg)
|
||||
{
|
||||
if(!neg2)
|
||||
negate();
|
||||
mpz_add(m_data, m_data, o.m_data);
|
||||
if(!neg2)
|
||||
negate();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template <class V>
|
||||
gmp_int& operator %= (V v)
|
||||
{
|
||||
gmp_int d;
|
||||
d = v;
|
||||
return *this %= d;
|
||||
}
|
||||
gmp_int& operator += (unsigned long i)
|
||||
{
|
||||
mpz_add_ui(m_data, m_data, i);
|
||||
return *this;
|
||||
}
|
||||
gmp_int& operator -= (unsigned long i)
|
||||
{
|
||||
mpz_sub_ui(m_data, m_data, i);
|
||||
return *this;
|
||||
}
|
||||
gmp_int& operator *= (unsigned long i)
|
||||
{
|
||||
mpz_mul_ui(m_data, m_data, i);
|
||||
return *this;
|
||||
}
|
||||
gmp_int& operator %= (unsigned long i)
|
||||
{
|
||||
bool neg = mpz_sgn(m_data) < 0;
|
||||
mpz_mod_ui(m_data, m_data, i);
|
||||
if(neg)
|
||||
{
|
||||
negate();
|
||||
mpz_add_ui(m_data, m_data, i);
|
||||
negate();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
gmp_int& operator /= (unsigned long i)
|
||||
{
|
||||
mpz_div_ui(m_data, m_data, i);
|
||||
return *this;
|
||||
}
|
||||
gmp_int& operator += (long i)
|
||||
{
|
||||
if(i > 0)
|
||||
mpz_add_ui(m_data, m_data, i);
|
||||
else
|
||||
mpz_sub_ui(m_data, m_data, std::abs(i));
|
||||
return *this;
|
||||
}
|
||||
gmp_int& operator -= (long i)
|
||||
{
|
||||
if(i > 0)
|
||||
mpz_sub_ui(m_data, m_data, i);
|
||||
else
|
||||
mpz_add_ui(m_data, m_data, std::abs(i));
|
||||
return *this;
|
||||
}
|
||||
gmp_int& operator *= (long i)
|
||||
{
|
||||
mpz_mul_ui(m_data, m_data, std::abs(i));
|
||||
if(i < 0)
|
||||
mpz_neg(m_data, m_data);
|
||||
return *this;
|
||||
}
|
||||
gmp_int& operator %= (long i)
|
||||
{
|
||||
bool neg = mpz_sgn(m_data) < 0;
|
||||
bool neg2 = i < 0;
|
||||
mpz_mod_ui(m_data, m_data, std::abs(i));
|
||||
if(neg)
|
||||
{
|
||||
if(!neg2)
|
||||
{
|
||||
negate();
|
||||
mpz_add_ui(m_data, m_data, std::abs(i));
|
||||
negate();
|
||||
}
|
||||
else
|
||||
{
|
||||
mpz_sub_ui(m_data, m_data, std::abs(i));
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
gmp_int& operator /= (long i)
|
||||
{
|
||||
mpz_div_ui(m_data, m_data, std::abs(i));
|
||||
if(i < 0)
|
||||
mpz_neg(m_data, m_data);
|
||||
return *this;
|
||||
}
|
||||
void swap(gmp_int& o)
|
||||
{
|
||||
mpz_swap(m_data, o.m_data);
|
||||
}
|
||||
std::string str(unsigned)const
|
||||
std::string str(unsigned /*digits*/, bool /*scientific*/)const
|
||||
{
|
||||
void *(*alloc_func_ptr) (size_t);
|
||||
void *(*realloc_func_ptr) (void *, size_t, size_t);
|
||||
@@ -776,10 +745,218 @@ struct gmp_int
|
||||
d = v;
|
||||
return compare(d);
|
||||
}
|
||||
mpz_t& data() { return m_data; }
|
||||
const mpz_t& data()const { return m_data; }
|
||||
protected:
|
||||
mpz_t m_data;
|
||||
};
|
||||
|
||||
inline void add(gmp_int& t, const gmp_int& o)
|
||||
{
|
||||
mpz_add(t.data(), t.data(), o.data());
|
||||
}
|
||||
inline void subtract(gmp_int& t, const gmp_int& o)
|
||||
{
|
||||
mpz_sub(t.data(), t.data(), o.data());
|
||||
}
|
||||
inline void multiply(gmp_int& t, const gmp_int& o)
|
||||
{
|
||||
mpz_mul(t.data(), t.data(), o.data());
|
||||
}
|
||||
inline void divide(gmp_int& t, const gmp_int& o)
|
||||
{
|
||||
mpz_div(t.data(), t.data(), o.data());
|
||||
}
|
||||
inline void modulus(gmp_int& t, const gmp_int& o)
|
||||
{
|
||||
bool neg = mpz_sgn(t.data()) < 0;
|
||||
bool neg2 = mpz_sgn(o.data()) < 0;
|
||||
mpz_mod(t.data(), t.data(), o.data());
|
||||
if(neg)
|
||||
{
|
||||
if(!neg2)
|
||||
t.negate();
|
||||
mpz_add(t.data(), t.data(), o.data());
|
||||
if(!neg2)
|
||||
t.negate();
|
||||
}
|
||||
}
|
||||
inline void add(gmp_int& t, unsigned long i)
|
||||
{
|
||||
mpz_add_ui(t.data(), t.data(), i);
|
||||
}
|
||||
inline void subtract(gmp_int& t, unsigned long i)
|
||||
{
|
||||
mpz_sub_ui(t.data(), t.data(), i);
|
||||
}
|
||||
inline void multiply(gmp_int& t, unsigned long i)
|
||||
{
|
||||
mpz_mul_ui(t.data(), t.data(), i);
|
||||
}
|
||||
inline void modulus(gmp_int& t, unsigned long i)
|
||||
{
|
||||
bool neg = mpz_sgn(t.data()) < 0;
|
||||
mpz_mod_ui(t.data(), t.data(), i);
|
||||
if(neg)
|
||||
{
|
||||
t.negate();
|
||||
mpz_add_ui(t.data(), t.data(), i);
|
||||
t.negate();
|
||||
}
|
||||
}
|
||||
inline void divide(gmp_int& t, unsigned long i)
|
||||
{
|
||||
mpz_div_ui(t.data(), t.data(), i);
|
||||
}
|
||||
inline void add(gmp_int& t, long i)
|
||||
{
|
||||
if(i > 0)
|
||||
mpz_add_ui(t.data(), t.data(), i);
|
||||
else
|
||||
mpz_sub_ui(t.data(), t.data(), -i);
|
||||
}
|
||||
inline void subtract(gmp_int& t, long i)
|
||||
{
|
||||
if(i > 0)
|
||||
mpz_sub_ui(t.data(), t.data(), i);
|
||||
else
|
||||
mpz_add_ui(t.data(), t.data(), -i);
|
||||
}
|
||||
inline void multiply(gmp_int& t, long i)
|
||||
{
|
||||
mpz_mul_ui(t.data(), t.data(), std::abs(i));
|
||||
if(i < 0)
|
||||
mpz_neg(t.data(), t.data());
|
||||
}
|
||||
inline void modulus(gmp_int& t, long i)
|
||||
{
|
||||
bool neg = mpz_sgn(t.data()) < 0;
|
||||
bool neg2 = i < 0;
|
||||
mpz_mod_ui(t.data(), t.data(), std::abs(i));
|
||||
if(neg)
|
||||
{
|
||||
if(!neg2)
|
||||
{
|
||||
t.negate();
|
||||
mpz_add_ui(t.data(), t.data(), std::abs(i));
|
||||
t.negate();
|
||||
}
|
||||
else
|
||||
{
|
||||
mpz_sub_ui(t.data(), t.data(), std::abs(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
inline void divide(gmp_int& t, long i)
|
||||
{
|
||||
mpz_div_ui(t.data(), t.data(), std::abs(i));
|
||||
if(i < 0)
|
||||
mpz_neg(t.data(), t.data());
|
||||
}
|
||||
|
||||
inline void add(gmp_int& t, const gmp_int& p, const gmp_int& o)
|
||||
{
|
||||
mpz_add(t.data(), p.data(), o.data());
|
||||
}
|
||||
inline void subtract(gmp_int& t, const gmp_int& p, const gmp_int& o)
|
||||
{
|
||||
mpz_sub(t.data(), p.data(), o.data());
|
||||
}
|
||||
inline void multiply(gmp_int& t, const gmp_int& p, const gmp_int& o)
|
||||
{
|
||||
mpz_mul(t.data(), p.data(), o.data());
|
||||
}
|
||||
inline void divide(gmp_int& t, const gmp_int& p, const gmp_int& o)
|
||||
{
|
||||
mpz_div(t.data(), p.data(), o.data());
|
||||
}
|
||||
inline void modulus(gmp_int& t, const gmp_int& p, const gmp_int& o)
|
||||
{
|
||||
bool neg = mpz_sgn(p.data()) < 0;
|
||||
bool neg2 = mpz_sgn(o.data()) < 0;
|
||||
mpz_mod(t.data(), p.data(), o.data());
|
||||
if(neg)
|
||||
{
|
||||
if(!neg2)
|
||||
t.negate();
|
||||
mpz_add(t.data(), t.data(), o.data());
|
||||
if(!neg2)
|
||||
t.negate();
|
||||
}
|
||||
}
|
||||
inline void add(gmp_int& t, const gmp_int& p, unsigned long i)
|
||||
{
|
||||
mpz_add_ui(t.data(), p.data(), i);
|
||||
}
|
||||
inline void subtract(gmp_int& t, const gmp_int& p, unsigned long i)
|
||||
{
|
||||
mpz_sub_ui(t.data(), p.data(), i);
|
||||
}
|
||||
inline void multiply(gmp_int& t, const gmp_int& p, unsigned long i)
|
||||
{
|
||||
mpz_mul_ui(t.data(), p.data(), i);
|
||||
}
|
||||
inline void modulus(gmp_int& t, const gmp_int& p, unsigned long i)
|
||||
{
|
||||
bool neg = mpz_sgn(p.data()) < 0;
|
||||
mpz_mod_ui(t.data(), p.data(), i);
|
||||
if(neg)
|
||||
{
|
||||
t.negate();
|
||||
mpz_add_ui(t.data(), t.data(), i);
|
||||
t.negate();
|
||||
}
|
||||
}
|
||||
inline void divide(gmp_int& t, const gmp_int& p, unsigned long i)
|
||||
{
|
||||
mpz_div_ui(t.data(), p.data(), i);
|
||||
}
|
||||
inline void add(gmp_int& t, const gmp_int& p, long i)
|
||||
{
|
||||
if(i > 0)
|
||||
mpz_add_ui(t.data(), p.data(), i);
|
||||
else
|
||||
mpz_sub_ui(t.data(), p.data(), -i);
|
||||
}
|
||||
inline void subtract(gmp_int& t, const gmp_int& p, long i)
|
||||
{
|
||||
if(i > 0)
|
||||
mpz_sub_ui(t.data(), p.data(), i);
|
||||
else
|
||||
mpz_add_ui(t.data(), p.data(), -i);
|
||||
}
|
||||
inline void multiply(gmp_int& t, const gmp_int& p, long i)
|
||||
{
|
||||
mpz_mul_ui(t.data(), p.data(), std::abs(i));
|
||||
if(i < 0)
|
||||
mpz_neg(t.data(), t.data());
|
||||
}
|
||||
inline void modulus(gmp_int& t, const gmp_int& p, long i)
|
||||
{
|
||||
bool neg = mpz_sgn(p.data()) < 0;
|
||||
bool neg2 = i < 0;
|
||||
mpz_mod_ui(t.data(), p.data(), std::abs(i));
|
||||
if(neg)
|
||||
{
|
||||
if(!neg2)
|
||||
{
|
||||
t.negate();
|
||||
mpz_add_ui(t.data(), t.data(), std::abs(i));
|
||||
t.negate();
|
||||
}
|
||||
else
|
||||
{
|
||||
mpz_sub_ui(t.data(), t.data(), std::abs(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
inline void divide(gmp_int& t, const gmp_int& p, long i)
|
||||
{
|
||||
mpz_div_ui(t.data(), p.data(), std::abs(i));
|
||||
if(i < 0)
|
||||
mpz_neg(t.data(), t.data());
|
||||
}
|
||||
|
||||
template<>
|
||||
struct is_extended_integer<gmp_int> : public mpl::true_ {};
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@ 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;
|
||||
typedef mpl::list<long long> signed_types;
|
||||
typedef mpl::list<unsigned long long> unsigned_types;
|
||||
typedef mpl::list<long double> real_types;
|
||||
|
||||
big_number_backend_real_architype()
|
||||
{
|
||||
@@ -49,24 +49,6 @@ struct big_number_backend_real_architype
|
||||
std::cout << "Int Assignment (" << i << ")" << std::endl;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator = (unsigned i)
|
||||
{
|
||||
m_value = i;
|
||||
std::cout << "UInt Assignment (" << i << ")" << std::endl;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator = (int i)
|
||||
{
|
||||
m_value = i;
|
||||
std::cout << "Int Assignment (" << i << ")" << std::endl;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator = (double d)
|
||||
{
|
||||
m_value = d;
|
||||
std::cout << "double Assignment (" << d << ")" << std::endl;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator = (long double d)
|
||||
{
|
||||
m_value = d;
|
||||
@@ -79,182 +61,29 @@ struct big_number_backend_real_architype
|
||||
std::cout << "const char* Assignment (" << s << ")" << std::endl;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator += (const big_number_backend_real_architype& o)
|
||||
{
|
||||
std::cout << "Addition (" << m_value << " += " << o.m_value << ")" << std::endl;
|
||||
m_value += o.m_value;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator -= (const big_number_backend_real_architype& o)
|
||||
{
|
||||
std::cout << "Subtraction (" << m_value << " -= " << o.m_value << ")" << std::endl;
|
||||
m_value -= o.m_value;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator *= (const big_number_backend_real_architype& o)
|
||||
{
|
||||
std::cout << "Multiplication (" << m_value << " *= " << o.m_value << ")" << std::endl;
|
||||
m_value *= o.m_value;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator /= (const big_number_backend_real_architype& o)
|
||||
{
|
||||
std::cout << "Division (" << m_value << " /= " << o.m_value << ")" << std::endl;
|
||||
m_value /= o.m_value;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator += (boost::uintmax_t i)
|
||||
{
|
||||
std::cout << "UIntmax_t Addition (" << m_value << " += " << i << ")" << std::endl;
|
||||
m_value += i;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator -= (boost::uintmax_t i)
|
||||
{
|
||||
std::cout << "UIntmax_t Subtraction (" << m_value << " -= " << i << ")" << std::endl;
|
||||
m_value -= i;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator *= (boost::uintmax_t i)
|
||||
{
|
||||
std::cout << "UIntmax_t Multiplication (" << m_value << " *= " << i << ")" << std::endl;
|
||||
m_value *= i;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator /= (boost::uintmax_t i)
|
||||
{
|
||||
std::cout << "UIntmax_t Division (" << m_value << " /= " << i << ")" << std::endl;
|
||||
m_value /= i;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator += (boost::intmax_t i)
|
||||
{
|
||||
std::cout << "Intmax_t Addition (" << m_value << " += " << i << ")" << std::endl;
|
||||
m_value += i;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator -= (boost::intmax_t i)
|
||||
{
|
||||
std::cout << "Intmax_t Subtraction (" << m_value << " -= " << i << ")" << std::endl;
|
||||
m_value -= i;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator *= (boost::intmax_t i)
|
||||
{
|
||||
std::cout << "Intmax_t Multiplication (" << m_value << " *= " << i << ")" << std::endl;
|
||||
m_value *= i;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator /= (boost::intmax_t i)
|
||||
{
|
||||
std::cout << "Intmax_t Division (" << m_value << " /= " << i << ")" << std::endl;
|
||||
m_value /= i;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator += (unsigned i)
|
||||
{
|
||||
std::cout << "UInt Addition (" << m_value << " += " << i << ")" << std::endl;
|
||||
m_value += i;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator -= (unsigned i)
|
||||
{
|
||||
std::cout << "UInt Subtraction (" << m_value << " -= " << i << ")" << std::endl;
|
||||
m_value -= i;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator *= (unsigned i)
|
||||
{
|
||||
std::cout << "UInt Multiplication (" << m_value << " *= " << i << ")" << std::endl;
|
||||
m_value *= i;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator /= (unsigned i)
|
||||
{
|
||||
std::cout << "UInt Division (" << m_value << " /= " << i << ")" << std::endl;
|
||||
m_value /= i;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator += (int i)
|
||||
{
|
||||
std::cout << "Int Addition (" << m_value << " += " << i << ")" << std::endl;
|
||||
m_value += i;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator -= (int i)
|
||||
{
|
||||
std::cout << "Int Subtraction (" << m_value << " -= " << i << ")" << std::endl;
|
||||
m_value -= i;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator *= (int i)
|
||||
{
|
||||
std::cout << "Int Multiplication (" << m_value << " *= " << i << ")" << std::endl;
|
||||
m_value *= i;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator /= (int i)
|
||||
{
|
||||
std::cout << "Int Division (" << m_value << " /= " << i << ")" << std::endl;
|
||||
m_value /= i;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator += (double d)
|
||||
{
|
||||
std::cout << "double Addition (" << m_value << " += " << d << ")" << std::endl;
|
||||
m_value += d;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator -= (double d)
|
||||
{
|
||||
std::cout << "double Subtraction (" << m_value << " -= " << d << ")" << std::endl;
|
||||
m_value -= d;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator *= (double d)
|
||||
{
|
||||
std::cout << "double Multiplication (" << m_value << " *= " << d << ")" << std::endl;
|
||||
m_value *= d;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator /= (double d)
|
||||
{
|
||||
std::cout << "double Division (" << m_value << " /= " << d << ")" << std::endl;
|
||||
m_value /= d;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator += (long double d)
|
||||
{
|
||||
std::cout << "long double Addition (" << m_value << " += " << d << ")" << std::endl;
|
||||
m_value += d;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator -= (long double d)
|
||||
{
|
||||
std::cout << "long double Subtraction (" << m_value << " -= " << d << ")" << std::endl;
|
||||
m_value -= d;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator *= (long double d)
|
||||
{
|
||||
std::cout << "long double Multiplication (" << m_value << " *= " << d << ")" << std::endl;
|
||||
m_value *= d;
|
||||
return *this;
|
||||
}
|
||||
big_number_backend_real_architype& operator /= (long double d)
|
||||
{
|
||||
std::cout << "long double Division (" << m_value << " /= " << d << ")" << std::endl;
|
||||
m_value /= d;
|
||||
return *this;
|
||||
}
|
||||
void swap(big_number_backend_real_architype& o)
|
||||
{
|
||||
std::cout << "Swapping (" << m_value << " with " << o.m_value << ")" << std::endl;
|
||||
std::swap(m_value, o.m_value);
|
||||
}
|
||||
std::string str(unsigned)const
|
||||
std::string str(unsigned digits, bool scientific)const
|
||||
{
|
||||
std::string s(boost::lexical_cast<std::string>(m_value));
|
||||
std::stringstream ss;
|
||||
if(scientific)
|
||||
ss.setf(ss.scientific);
|
||||
if(digits)
|
||||
ss.precision(digits);
|
||||
else
|
||||
ss.precision(std::numeric_limits<long double>::digits10 + 2);
|
||||
boost::intmax_t i = m_value;
|
||||
boost::uintmax_t u = m_value;
|
||||
if(!scientific && m_value == i)
|
||||
ss << i;
|
||||
else if(!scientific && m_value == u)
|
||||
ss << u;
|
||||
else
|
||||
ss << m_value;
|
||||
std::string s = ss.str();
|
||||
std::cout << "Converting to string (" << s << ")" << std::endl;
|
||||
return s;
|
||||
}
|
||||
@@ -268,16 +97,6 @@ struct big_number_backend_real_architype
|
||||
std::cout << "Comparison" << std::endl;
|
||||
return m_value > o.m_value ? 1 : (m_value < o.m_value ? -1 : 0);
|
||||
}
|
||||
int compare(int i)const
|
||||
{
|
||||
std::cout << "Comparison with int" << std::endl;
|
||||
return m_value > i ? 1 : (m_value < i ? -1 : 0);
|
||||
}
|
||||
int compare(unsigned i)const
|
||||
{
|
||||
std::cout << "Comparison with unsigned" << std::endl;
|
||||
return m_value > i ? 1 : (m_value < i ? -1 : 0);
|
||||
}
|
||||
int compare(boost::intmax_t i)const
|
||||
{
|
||||
std::cout << "Comparison with int" << std::endl;
|
||||
@@ -288,20 +107,35 @@ struct big_number_backend_real_architype
|
||||
std::cout << "Comparison with unsigned" << std::endl;
|
||||
return m_value > i ? 1 : (m_value < i ? -1 : 0);
|
||||
}
|
||||
int compare(double d)const
|
||||
{
|
||||
std::cout << "Comparison with double" << std::endl;
|
||||
return m_value > d ? 1 : (m_value < d ? -1 : 0);
|
||||
}
|
||||
int compare(long double d)const
|
||||
{
|
||||
std::cout << "Comparison with long double" << std::endl;
|
||||
return m_value > d ? 1 : (m_value < d ? -1 : 0);
|
||||
}
|
||||
private:
|
||||
long double m_value;
|
||||
};
|
||||
|
||||
inline void add(big_number_backend_real_architype& result, const big_number_backend_real_architype& o)
|
||||
{
|
||||
std::cout << "Addition (" << result.m_value << " += " << o.m_value << ")" << std::endl;
|
||||
result.m_value += o.m_value;
|
||||
}
|
||||
inline void subtract(big_number_backend_real_architype& result, const big_number_backend_real_architype& o)
|
||||
{
|
||||
std::cout << "Subtraction (" << result.m_value << " -= " << o.m_value << ")" << std::endl;
|
||||
result.m_value -= o.m_value;
|
||||
}
|
||||
inline void multiply(big_number_backend_real_architype& result, const big_number_backend_real_architype& o)
|
||||
{
|
||||
std::cout << "Multiplication (" << result.m_value << " *= " << o.m_value << ")" << std::endl;
|
||||
result.m_value *= o.m_value;
|
||||
}
|
||||
inline void divide(big_number_backend_real_architype& result, const big_number_backend_real_architype& o)
|
||||
{
|
||||
std::cout << "Division (" << result.m_value << " /= " << o.m_value << ")" << std::endl;
|
||||
result.m_value /= o.m_value;
|
||||
}
|
||||
|
||||
typedef boost::math::big_number<big_number_backend_real_architype> big_number_real_architype;
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
@@ -18,6 +18,7 @@ http://www.netlib.org/f2c/libf2c.zip
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cmath>
|
||||
|
||||
#ifdef TEST_BIG_NUMBER
|
||||
#include <boost/math/big_number/gmp.hpp>
|
||||
typedef boost::math::mpf_real_100 real_type;
|
||||
|
||||
@@ -50,6 +50,16 @@ void test_integer_ops(const boost::mpl::true_&)
|
||||
BOOST_TEST(a % -7 == 20 % -7);
|
||||
BOOST_TEST(-a % 7u == -20 % 7);
|
||||
|
||||
b = -b;
|
||||
BOOST_TEST(a % b == 20 % -7);
|
||||
a = -a;
|
||||
BOOST_TEST(a % b == -20 % -7);
|
||||
BOOST_TEST(a % -7 == -20 % -7);
|
||||
b = 7;
|
||||
BOOST_TEST(a % b == -20 % 7);
|
||||
BOOST_TEST(a % 7 == -20 % 7);
|
||||
BOOST_TEST(a % 7u == -20 % 7);
|
||||
|
||||
a = 20;
|
||||
a %= b;
|
||||
BOOST_TEST(a == 20 % 7);
|
||||
@@ -83,6 +93,7 @@ void test_real_ops(const boost::mpl::false_&){}
|
||||
template <class Real>
|
||||
void test_real_ops(const boost::mpl::true_&)
|
||||
{
|
||||
#if defined(TEST_MPF) || defined(TEST_MPF_50)
|
||||
std::cout << "Root2 = " << sqrt(Real(2)) << std::endl;
|
||||
BOOST_TEST(abs(Real(2)) == 2);
|
||||
BOOST_TEST(abs(Real(-2)) == 2);
|
||||
@@ -92,12 +103,8 @@ void test_real_ops(const boost::mpl::true_&)
|
||||
BOOST_TEST(ceil(Real(5) / 2) == 3);
|
||||
BOOST_TEST(floor(Real(-5) / 2) == -3);
|
||||
BOOST_TEST(ceil(Real(-5) / 2) == -2);
|
||||
#ifndef TEST_E_FLOAT
|
||||
BOOST_TEST(trunc(Real(5) / 2) == 2);
|
||||
BOOST_TEST(trunc(Real(-5) / 2) == -2);
|
||||
#endif
|
||||
|
||||
#ifndef TEST_E_FLOAT
|
||||
//
|
||||
// ldexp and frexp, these pretty much have to implemented by each backend:
|
||||
//
|
||||
@@ -108,6 +115,7 @@ void test_real_ops(const boost::mpl::true_&)
|
||||
Real r = frexp(v, &exp);
|
||||
BOOST_TEST(r == 0.5);
|
||||
BOOST_TEST(exp == 10);
|
||||
BOOST_TEST(v == 512);
|
||||
v = 1 / v;
|
||||
r = frexp(v, &exp);
|
||||
BOOST_TEST(r == 0.5);
|
||||
@@ -115,9 +123,24 @@ void test_real_ops(const boost::mpl::true_&)
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct lexical_cast_target_type
|
||||
{
|
||||
typedef typename boost::mpl::if_<
|
||||
boost::is_signed<T>,
|
||||
boost::intmax_t,
|
||||
typename boost::mpl::if_<
|
||||
boost::is_unsigned<T>,
|
||||
boost::uintmax_t,
|
||||
T
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class Real, class Num>
|
||||
void test_negative_mixed(boost::mpl::true_ const&)
|
||||
{
|
||||
typedef typename lexical_cast_target_type<Num>::type target_type;
|
||||
std::cout << "Testing mixed arithmetic with type: " << typeid(Real).name() << " and " << typeid(Num).name() << std::endl;
|
||||
Num n1 = -static_cast<Num>(1uLL << (std::numeric_limits<Num>::digits - 1));
|
||||
Num n2 = -1;
|
||||
@@ -133,10 +156,10 @@ void test_negative_mixed(boost::mpl::true_ const&)
|
||||
BOOST_TEST(n2 == Real(n2));
|
||||
BOOST_TEST(n3 == Real(n3));
|
||||
BOOST_TEST(n4 == Real(n4));
|
||||
BOOST_TEST(n1 == boost::lexical_cast<long double>(Real(n1)));
|
||||
BOOST_TEST(n2 == boost::lexical_cast<long double>(Real(n2)));
|
||||
BOOST_TEST(n3 == boost::lexical_cast<long double>(Real(n3)));
|
||||
BOOST_TEST(n4 == boost::lexical_cast<long double>(Real(n4)));
|
||||
BOOST_TEST(n1 == boost::lexical_cast<target_type>(Real(n1).str(0, boost::is_floating_point<Num>::value)));
|
||||
BOOST_TEST(n2 == boost::lexical_cast<target_type>(Real(n2).str(0, boost::is_floating_point<Num>::value)));
|
||||
BOOST_TEST(n3 == boost::lexical_cast<target_type>(Real(n3).str(0, boost::is_floating_point<Num>::value)));
|
||||
BOOST_TEST(n4 == boost::lexical_cast<target_type>(Real(n4).str(0, boost::is_floating_point<Num>::value)));
|
||||
// Assignment:
|
||||
Real r(0);
|
||||
BOOST_TEST(r != n1);
|
||||
@@ -172,6 +195,21 @@ void test_negative_mixed(boost::mpl::true_ const&)
|
||||
BOOST_TEST(Real(r / n5) == n1 / n5);
|
||||
r /= n5;
|
||||
BOOST_TEST(r == n1 / n5);
|
||||
//
|
||||
// Extra cases for full coverage:
|
||||
//
|
||||
r = Real(n4) + n5;
|
||||
BOOST_TEST(r == n4 + n5);
|
||||
r = n4 + Real(n5);
|
||||
BOOST_TEST(r == n4 + n5);
|
||||
r = Real(n4) - n5;
|
||||
BOOST_TEST(r == n4 - n5);
|
||||
r = n4 - Real(n5);
|
||||
BOOST_TEST(r == n4 - n5);
|
||||
r = n4 * Real(n5);
|
||||
BOOST_TEST(r == n4 * n5);
|
||||
r = (4 * n4) / Real(4);
|
||||
BOOST_TEST(r == n4);
|
||||
}
|
||||
|
||||
template <class Real, class Num>
|
||||
@@ -182,6 +220,7 @@ void test_negative_mixed(boost::mpl::false_ const&)
|
||||
template <class Real, class Num>
|
||||
void test_mixed()
|
||||
{
|
||||
typedef typename lexical_cast_target_type<Num>::type target_type;
|
||||
std::cout << "Testing mixed arithmetic with type: " << typeid(Real).name() << " and " << typeid(Num).name() << std::endl;
|
||||
Num n1 = static_cast<Num>(1uLL << (std::numeric_limits<Num>::digits - 1));
|
||||
Num n2 = 1;
|
||||
@@ -197,10 +236,10 @@ void test_mixed()
|
||||
BOOST_TEST(n2 == Real(n2));
|
||||
BOOST_TEST(n3 == Real(n3));
|
||||
BOOST_TEST(n4 == Real(n4));
|
||||
BOOST_TEST(n1 == boost::lexical_cast<long double>(Real(n1)));
|
||||
BOOST_TEST(n2 == boost::lexical_cast<long double>(Real(n2)));
|
||||
BOOST_TEST(n3 == boost::lexical_cast<long double>(Real(n3)));
|
||||
BOOST_TEST(n4 == boost::lexical_cast<long double>(Real(n4)));
|
||||
BOOST_TEST(n1 == boost::lexical_cast<target_type>(Real(n1).str(0, boost::is_floating_point<Num>::value)));
|
||||
BOOST_TEST(n2 == boost::lexical_cast<target_type>(Real(n2).str(0, boost::is_floating_point<Num>::value)));
|
||||
BOOST_TEST(n3 == boost::lexical_cast<target_type>(Real(n3).str(0, boost::is_floating_point<Num>::value)));
|
||||
BOOST_TEST(n4 == boost::lexical_cast<target_type>(Real(n4).str(0, boost::is_floating_point<Num>::value)));
|
||||
// Assignment:
|
||||
Real r(0);
|
||||
BOOST_TEST(r != n1);
|
||||
@@ -237,6 +276,18 @@ void test_mixed()
|
||||
r /= n5;
|
||||
BOOST_TEST(r == n1 / n5);
|
||||
|
||||
//
|
||||
// special cases for full coverage:
|
||||
//
|
||||
r = n5 + Real(n4);
|
||||
BOOST_TEST(r == n4 + n5);
|
||||
r = n4 - Real(n5);
|
||||
BOOST_TEST(r == n4 - n5);
|
||||
r = n4 * Real(n5);
|
||||
BOOST_TEST(r == n4 * n5);
|
||||
r = (4 * n4) / Real(4);
|
||||
BOOST_TEST(r == n4);
|
||||
|
||||
test_negative_mixed<Real, Num>(boost::mpl::bool_<std::numeric_limits<Num>::is_signed>());
|
||||
}
|
||||
|
||||
@@ -439,6 +490,28 @@ void test()
|
||||
ac = a + std::string("8");
|
||||
BOOST_TEST(ac == 16);
|
||||
#endif
|
||||
//
|
||||
// simple tests with immediate values, these calls can be optimised in many backends:
|
||||
//
|
||||
ac = a + b;
|
||||
BOOST_TEST(ac == 72);
|
||||
ac = a + +b;
|
||||
BOOST_TEST(ac == 72);
|
||||
ac = +a + b;
|
||||
BOOST_TEST(ac == 72);
|
||||
ac = +a + +b;
|
||||
BOOST_TEST(ac == 72);
|
||||
ac = a + -b;
|
||||
BOOST_TEST(ac == 8 - 64);
|
||||
ac = -a + b;
|
||||
BOOST_TEST(ac == -8+64);
|
||||
ac = -a + -b;
|
||||
BOOST_TEST(ac == -72);
|
||||
ac = a + - + -b; // lots of unary operators!!
|
||||
BOOST_TEST(ac == 72);
|
||||
ac = a;
|
||||
ac = b / ac;
|
||||
BOOST_TEST(ac == b / a);
|
||||
//
|
||||
// Comparisons:
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user