|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r74089 - in sandbox/big_number: boost/math boost/math/big_number libs/math/test
From: john_at_[hidden]
Date: 2011-08-27 12:37:02
Author: johnmaddock
Date: 2011-08-27 12:37:01 EDT (Sat, 27 Aug 2011)
New Revision: 74089
URL: http://svn.boost.org/trac/boost/changeset/74089
Log:
Add bitwise integer ops.
Reorganise proto grammar.
Text files modified:
sandbox/big_number/boost/math/big_number.hpp | 353 ++++++++++++++++++++++++++++++++++-----
sandbox/big_number/boost/math/big_number/big_number_base.hpp | 181 +++++++++++++++++++-
sandbox/big_number/boost/math/big_number/default_ops.hpp | 74 ++++++++
sandbox/big_number/boost/math/big_number/gmp.hpp | 35 +++
sandbox/big_number/libs/math/test/test_arithmetic.cpp | 83 +++++++++
5 files changed, 668 insertions(+), 58 deletions(-)
Modified: sandbox/big_number/boost/math/big_number.hpp
==============================================================================
--- sandbox/big_number/boost/math/big_number.hpp (original)
+++ sandbox/big_number/boost/math/big_number.hpp 2011-08-27 12:37:01 EDT (Sat, 27 Aug 2011)
@@ -204,6 +204,16 @@
}
return *this;
}
+ template <class V>
+ typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type
+ operator%=(const V& v)
+ {
+ BOOST_STATIC_ASSERT_MSG(is_extended_integer<Backend>::value, "The modulus operation is only valid for integer types");
+ using big_num_default_ops::modulus;
+ modulus(m_backend, canonical_value(v));
+ return *this;
+ }
+
//
// These operators are *not* proto-ized.
// The issue is that the increment/decrement must happen
@@ -264,16 +274,6 @@
return *this;
}
- template <class V>
- typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type
- operator%=(const V& v)
- {
- BOOST_STATIC_ASSERT_MSG(is_extended_integer<Backend>::value, "The modulus operation is only valid for integer types");
- using big_num_default_ops::modulus;
- modulus(m_backend, canonical_value(v));
- return *this;
- }
-
template <class Exp>
big_number& operator/=(const detail::big_number_exp<Exp>& e)
{
@@ -299,6 +299,82 @@
return *this;
}
+ template <class Exp>
+ big_number& operator&=(const detail::big_number_exp<Exp>& e)
+ {
+ // Create a temporary if the RHS references *this, but not
+ // if we're just doing an x &= x;
+ if(contains_self(e) && !is_self(e))
+ {
+ self_type temp(e);
+ do_bitwise_and(temp, typename proto::tag_of<self_type>::type());
+ }
+ else
+ {
+ do_bitwise_and(e, typename proto::tag_of<Exp>::type());
+ }
+ return *this;
+ }
+
+ template <class V>
+ typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type
+ operator&=(const V& v)
+ {
+ using big_num_default_ops::bitwise_and;
+ bitwise_and(m_backend, canonical_value(v));
+ return *this;
+ }
+
+ template <class Exp>
+ big_number& operator|=(const detail::big_number_exp<Exp>& e)
+ {
+ // Create a temporary if the RHS references *this, but not
+ // if we're just doing an x |= x;
+ if(contains_self(e) && !is_self(e))
+ {
+ self_type temp(e);
+ do_bitwise_or(temp, typename proto::tag_of<self_type>::type());
+ }
+ else
+ {
+ do_bitwise_or(e, typename proto::tag_of<Exp>::type());
+ }
+ return *this;
+ }
+
+ template <class V>
+ typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type
+ operator|=(const V& v)
+ {
+ using big_num_default_ops::bitwise_or;
+ bitwise_or(m_backend, canonical_value(v));
+ return *this;
+ }
+
+ template <class Exp>
+ big_number& operator^=(const detail::big_number_exp<Exp>& e)
+ {
+ if(contains_self(e))
+ {
+ self_type temp(e);
+ do_bitwise_xor(temp, typename proto::tag_of<self_type>::type());
+ }
+ else
+ {
+ do_bitwise_xor(e, typename proto::tag_of<Exp>::type());
+ }
+ return *this;
+ }
+
+ template <class V>
+ typename enable_if<boost::is_arithmetic<V>, big_number<Backend>& >::type
+ operator^=(const V& v)
+ {
+ using big_num_default_ops::bitwise_xor;
+ bitwise_xor(m_backend, canonical_value(v));
+ return *this;
+ }
+
//
// swap:
//
@@ -474,16 +550,6 @@
}
template <class Exp>
- void do_assign(const Exp& e, const detail::modulus_immediates&)
- {
- BOOST_STATIC_ASSERT_MSG(is_extended_integer<Backend>::value, "The modulus operation is only valid for integer types");
- 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;
@@ -676,6 +742,142 @@
}
}
template <class Exp>
+ void do_assign(const Exp& e, const detail::modulus_immediates&)
+ {
+ BOOST_STATIC_ASSERT_MSG(is_extended_integer<Backend>::value, "The modulus operation is only valid for integer types");
+ 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::bitwise_and&)
+ {
+ //
+ // This operation is only valid for integer backends:
+ //
+ BOOST_STATIC_ASSERT_MSG(is_extended_integer<Backend>::value, "Bitwise operations are only valid for integer types");
+
+ typedef typename proto::result_of::left<Exp>::type left_type;
+ typedef typename proto::result_of::right<Exp>::type right_type;
+
+ static int const left_depth = boost::result_of<detail::CalcDepth(left_type)>::type::value;
+ static int const right_depth = boost::result_of<detail::CalcDepth(right_type)>::type::value;
+
+ bool bl = contains_self(proto::left(e));
+ bool br = contains_self(proto::right(e));
+
+ if(bl && is_self(proto::left(e)))
+ {
+ // Ignore the left node, it's *this, just add the right:
+ do_bitwise_and(proto::right(e), typename proto::tag_of<right_type>::type());
+ }
+ else if(br && is_self(proto::right(e)))
+ {
+ do_bitwise_and(proto::left(e), typename proto::tag_of<left_type>::type());
+ }
+ else
+ {
+ do_assign(proto::left(e), typename detail::assign_and_eval<left_type>::type());
+ do_bitwise_and(proto::right(e), typename proto::tag_of<right_type>::type());
+ }
+ }
+ template <class Exp>
+ void do_assign(const Exp& e, const detail::bitwise_and_immediates&)
+ {
+ BOOST_STATIC_ASSERT_MSG(is_extended_integer<Backend>::value, "Bitwise operations are only valid for integer types");
+ using big_num_default_ops::bitwise_and;
+ 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;
+ bitwise_and(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::bitwise_or&)
+ {
+ //
+ // This operation is only valid for integer backends:
+ //
+ BOOST_STATIC_ASSERT_MSG(is_extended_integer<Backend>::value, "Bitwise operations are only valid for integer types");
+
+ typedef typename proto::result_of::left<Exp>::type left_type;
+ typedef typename proto::result_of::right<Exp>::type right_type;
+
+ static int const left_depth = boost::result_of<detail::CalcDepth(left_type)>::type::value;
+ static int const right_depth = boost::result_of<detail::CalcDepth(right_type)>::type::value;
+
+ bool bl = contains_self(proto::left(e));
+ bool br = contains_self(proto::right(e));
+
+ if(bl && is_self(proto::left(e)))
+ {
+ // Ignore the left node, it's *this, just add the right:
+ do_bitwise_or(proto::right(e), typename proto::tag_of<right_type>::type());
+ }
+ else if(br && is_self(proto::right(e)))
+ {
+ do_bitwise_or(proto::left(e), typename proto::tag_of<left_type>::type());
+ }
+ else
+ {
+ do_assign(proto::left(e), typename detail::assign_and_eval<left_type>::type());
+ do_bitwise_or(proto::right(e), typename proto::tag_of<right_type>::type());
+ }
+ }
+ template <class Exp>
+ void do_assign(const Exp& e, const detail::bitwise_or_immediates&)
+ {
+ BOOST_STATIC_ASSERT_MSG(is_extended_integer<Backend>::value, "Bitwise operations are only valid for integer types");
+ using big_num_default_ops::bitwise_or;
+ 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;
+ bitwise_or(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::bitwise_xor&)
+ {
+ //
+ // This operation is only valid for integer backends:
+ //
+ BOOST_STATIC_ASSERT_MSG(is_extended_integer<Backend>::value, "Bitwise operations are only valid for integer types");
+
+ typedef typename proto::result_of::left<Exp>::type left_type;
+ typedef typename proto::result_of::right<Exp>::type right_type;
+
+ static int const left_depth = boost::result_of<detail::CalcDepth(left_type)>::type::value;
+ static int const right_depth = boost::result_of<detail::CalcDepth(right_type)>::type::value;
+
+ bool bl = contains_self(proto::left(e));
+ bool br = contains_self(proto::right(e));
+
+ if(bl && is_self(proto::left(e)))
+ {
+ // Ignore the left node, it's *this, just add the right:
+ do_bitwise_xor(proto::right(e), typename proto::tag_of<right_type>::type());
+ }
+ else if(br && is_self(proto::right(e)))
+ {
+ do_bitwise_xor(proto::left(e), typename proto::tag_of<left_type>::type());
+ }
+ else
+ {
+ do_assign(proto::left(e), typename detail::assign_and_eval<left_type>::type());
+ do_bitwise_xor(proto::right(e), typename proto::tag_of<right_type>::type());
+ }
+ }
+ template <class Exp>
+ void do_assign(const Exp& e, const detail::bitwise_xor_immediates&)
+ {
+ BOOST_STATIC_ASSERT_MSG(is_extended_integer<Backend>::value, "Bitwise operations are only valid for integer types");
+ using big_num_default_ops::bitwise_xor;
+ 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;
+ bitwise_xor(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::terminal&)
{
if(!is_self(e))
@@ -717,6 +919,21 @@
do_assign_right_shift(proto::left(e), canonical_value(proto::value(proto::right(e))), tag_type());
}
+ template <class Exp>
+ void do_assign(const Exp& e, const proto::tag::complement&)
+ {
+ using big_num_default_ops::complement;
+ self_type temp(proto::left(e));
+ complement(m_backend, temp.backend());
+ }
+
+ template <class Exp>
+ void do_assign(const Exp& e, const detail::complement_immediates&)
+ {
+ using big_num_default_ops::complement;
+ complement(m_backend, canonical_value(proto::left(e)));
+ }
+
template <class Exp, class Val>
void do_assign_right_shift(const Exp& e, const Val& val, const proto::tag::terminal&)
{
@@ -990,6 +1207,72 @@
modulus(m_backend, canonical_value(proto::value(temp)));
}
+ template <class Exp>
+ void do_bitwise_and(const Exp& e, const proto::tag::terminal&)
+ {
+ using big_num_default_ops::bitwise_and;
+ bitwise_and(m_backend, canonical_value(proto::value(e)));
+ }
+ template <class Exp>
+ void do_bitwise_and(const Exp& e, const proto::tag::bitwise_and&)
+ {
+ typedef typename proto::result_of::left<Exp>::type left_type;
+ typedef typename proto::result_of::right<Exp>::type right_type;
+ do_bitwise_and(proto::left(e), typename proto::tag_of<left_type>::type());
+ do_bitwise_and(proto::right(e), typename proto::tag_of<right_type>::type());
+ }
+ template <class Exp, class unknown>
+ void do_bitwise_and(const Exp& e, const unknown&)
+ {
+ using big_num_default_ops::bitwise_and;
+ self_type temp(e);
+ bitwise_and(m_backend, temp.m_backend);
+ }
+
+ template <class Exp>
+ void do_bitwise_or(const Exp& e, const proto::tag::terminal&)
+ {
+ using big_num_default_ops::bitwise_or;
+ bitwise_or(m_backend, canonical_value(proto::value(e)));
+ }
+ template <class Exp>
+ void do_bitwise_or(const Exp& e, const proto::tag::bitwise_or&)
+ {
+ typedef typename proto::result_of::left<Exp>::type left_type;
+ typedef typename proto::result_of::right<Exp>::type right_type;
+ do_bitwise_or(proto::left(e), typename proto::tag_of<left_type>::type());
+ do_bitwise_or(proto::right(e), typename proto::tag_of<right_type>::type());
+ }
+ template <class Exp, class unknown>
+ void do_bitwise_or(const Exp& e, const unknown&)
+ {
+ using big_num_default_ops::bitwise_or;
+ self_type temp(e);
+ bitwise_or(m_backend, temp.m_backend);
+ }
+
+ template <class Exp>
+ void do_bitwise_xor(const Exp& e, const proto::tag::terminal&)
+ {
+ using big_num_default_ops::bitwise_xor;
+ bitwise_xor(m_backend, canonical_value(proto::value(e)));
+ }
+ template <class Exp>
+ void do_bitwise_xor(const Exp& e, const proto::tag::bitwise_xor&)
+ {
+ typedef typename proto::result_of::left<Exp>::type left_type;
+ typedef typename proto::result_of::right<Exp>::type right_type;
+ do_bitwise_xor(proto::left(e), typename proto::tag_of<left_type>::type());
+ do_bitwise_xor(proto::right(e), typename proto::tag_of<right_type>::type());
+ }
+ template <class Exp, class unknown>
+ void do_bitwise_xor(const Exp& e, const unknown&)
+ {
+ using big_num_default_ops::bitwise_xor;
+ self_type temp(e);
+ bitwise_xor(m_backend, temp.m_backend);
+ }
+
// Tests if the expression contains a reference to *this:
template <class Exp>
bool contains_self(const Exp& e)const
@@ -1198,44 +1481,24 @@
{
return 0 < detail::big_number_compare(a, b);
}
-//
-// Because proto overloads these << operators, we need version that accept both
-// const and non-const RHS values, otherwise the proto version will be found
-// with unpleasant results... not only that, but the stream parameter has to be a template
-// otherwise the LHS of the expression would have to be *exactly* of type std::ostream
-// for the overload to be found (ie doesn't work for std::fstream etc unless we do this...)
-//
-template <class Stream, class Backend>
-inline typename enable_if<is_convertible<Stream*, std::ostream*>, std::ostream&>::type operator << (Stream& os, const big_number<Backend>& r)
-{
- return os << r.str(static_cast<unsigned>(os.precision(), os.flags() & os.scientific));
-}
-template <class Stream, class Backend>
-inline typename enable_if<is_convertible<Stream*, std::ostream*>, std::ostream&>::type operator << (Stream& os, big_number<Backend>& r)
+template <class Backend>
+inline std::ostream& operator << (std::ostream& os, const big_number<Backend>& r)
{
return os << r.str(static_cast<unsigned>(os.precision(), os.flags() & os.scientific));
}
namespace detail{
-template <class Stream, class Exp>
-inline typename enable_if<is_convertible<Stream*, std::ostream*>, std::ostream&>::type operator << (Stream& os, const big_number_exp<Exp>& r)
+template <class Exp>
+inline std::ostream& operator << (std::ostream& os, const big_number_exp<Exp>& r)
{
typedef typename expression_type<detail::big_number_exp<Exp> >::type value_type;
value_type temp(r);
return os << temp;
}
-template <class Stream, class Exp>
-inline typename enable_if<is_convertible<Stream*, std::ostream*>, std::ostream&>::type operator << (Stream& os, big_number_exp<Exp>& r)
-{
- typedef typename expression_type<detail::big_number_exp<Exp> >::type value_type;
- value_type temp(r);
- return os << temp;
-}
-
-}
+} // namespace detail
template <class Stream, class Backend>
inline typename enable_if<is_convertible<Stream*, std::ostream*>, std::istream&>::type operator >> (Stream& is, big_number<Backend>& r)
Modified: sandbox/big_number/boost/math/big_number/big_number_base.hpp
==============================================================================
--- sandbox/big_number/boost/math/big_number/big_number_base.hpp (original)
+++ sandbox/big_number/boost/math/big_number/big_number_base.hpp 2011-08-27 12:37:01 EDT (Sat, 27 Aug 2011)
@@ -19,21 +19,111 @@
//
// 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>
- , proto::shift_left<big_number_grammar, big_number_grammar>
- , proto::shift_right<big_number_grammar, big_number_grammar>
- >
+struct integer_terminal : public
+proto::and_<
+ proto::terminal< proto::_ >,
+ proto::if_ < boost::is_integral< proto::_value >() >
+ >
+{};
+
+struct big_number_grammar;
+
+template<typename T>
+struct is_big_number_ptr : mpl::false_ {};
+
+template<typename Backend>
+struct is_big_number_ptr<big_number<Backend>*> : mpl::true_ {};
+
+
+struct big_number_grammar_cases
+{
+ // The primary template matches nothing:
+ template<typename Tag>
+ struct case_
+ : proto::not_<proto::_>
+ {};
+};
+
+template<>
+struct big_number_grammar_cases::case_<proto::tag::terminal>
+ : proto::and_<
+ proto::terminal<proto::_ >,
+ proto::or_<
+ proto::if_ < is_big_number_ptr< proto::_value >() >,
+ proto::if_ < is_arithmetic< proto::_value >() >,
+ proto::if_ < is_same< proto::_value, std::string>() >,
+ proto::if_ < is_convertible< proto::_value, const char*>() >
+ >
+ >
+{};
+
+template<>
+struct big_number_grammar_cases::case_<proto::tag::plus>
+ : proto::plus< big_number_grammar, big_number_grammar >
+{};
+
+template<>
+struct big_number_grammar_cases::case_<proto::tag::multiplies>
+ : proto::multiplies< big_number_grammar, big_number_grammar >
+{};
+
+template<>
+struct big_number_grammar_cases::case_<proto::tag::minus>
+ : proto::minus< big_number_grammar, big_number_grammar >
+{};
+
+template<>
+struct big_number_grammar_cases::case_<proto::tag::divides>
+ : proto::divides< big_number_grammar, big_number_grammar >
+{};
+
+template<>
+struct big_number_grammar_cases::case_<proto::tag::unary_plus>
+ : proto::unary_plus< big_number_grammar>
+{};
+
+template<>
+struct big_number_grammar_cases::case_<proto::tag::negate>
+ : proto::negate< big_number_grammar>
+{};
+
+template<>
+struct big_number_grammar_cases::case_<proto::tag::modulus>
+ : proto::modulus< big_number_grammar, big_number_grammar >
+{};
+
+template<>
+struct big_number_grammar_cases::case_<proto::tag::bitwise_and>
+ : proto::bitwise_and< big_number_grammar, big_number_grammar >
+{};
+
+template<>
+struct big_number_grammar_cases::case_<proto::tag::bitwise_or>
+ : proto::bitwise_or< big_number_grammar, big_number_grammar >
+{};
+
+template<>
+struct big_number_grammar_cases::case_<proto::tag::bitwise_xor>
+ : proto::bitwise_xor< big_number_grammar, big_number_grammar >
+{};
+
+template<>
+struct big_number_grammar_cases::case_<proto::tag::shift_left>
+ : proto::shift_left< big_number_grammar, integer_terminal >
+{};
+
+template<>
+struct big_number_grammar_cases::case_<proto::tag::shift_right>
+ : proto::shift_right< big_number_grammar, integer_terminal >
{};
+template<>
+struct big_number_grammar_cases::case_<proto::tag::complement>
+ : proto::complement<big_number_grammar>
+{};
+
+struct big_number_grammar : proto::switch_<big_number_grammar_cases>{};
+
// Define a calculator domain. Expression within
// the calculator domain will be wrapped in the
// calculator<> expression wrapper.
@@ -146,6 +236,10 @@
struct divide_immediates{};
struct divide_and_negate_immediates{};
struct modulus_immediates{};
+struct bitwise_and_immediates{};
+struct bitwise_or_immediates{};
+struct bitwise_xor_immediates{};
+struct complement_immediates{};
struct immediate{};
struct negative_immediate{};
@@ -313,6 +407,67 @@
};
template <class Exp>
+struct assign_and_eval_imp<Exp, proto::tag::bitwise_and>
+{
+ 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> >,
+ bitwise_and_immediates,
+ proto::tag::bitwise_and
+ >::type type;
+};
+
+template <class Exp>
+struct assign_and_eval_imp<Exp, proto::tag::bitwise_or>
+{
+ 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> >,
+ bitwise_or_immediates,
+ proto::tag::bitwise_or
+ >::type type;
+};
+
+template <class Exp>
+struct assign_and_eval_imp<Exp, proto::tag::bitwise_xor>
+{
+ 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> >,
+ bitwise_xor_immediates,
+ proto::tag::bitwise_xor
+ >::type type;
+};
+
+template <class Exp>
+struct assign_and_eval_imp<Exp, proto::tag::complement>
+{
+ 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 left_imm;
+ typedef typename mpl::if_<
+ is_same<left_imm, immediate>,
+ complement_immediates,
+ proto::tag::complement
+ >::type type;
+};
+
+template <class Exp>
struct assign_and_eval
{
typedef typename proto::tag_of<Exp>::type tag_type;
Modified: sandbox/big_number/boost/math/big_number/default_ops.hpp
==============================================================================
--- sandbox/big_number/boost/math/big_number/default_ops.hpp (original)
+++ sandbox/big_number/boost/math/big_number/default_ops.hpp 2011-08-27 12:37:01 EDT (Sat, 27 Aug 2011)
@@ -54,6 +54,39 @@
t = v;
modulus(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
+ bitwise_and(T& result, V const& v)
+{
+ T t;
+ t = v;
+ bitwise_and(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
+ bitwise_or(T& result, V const& v)
+{
+ T t;
+ t = v;
+ bitwise_or(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
+ bitwise_xor(T& result, V const& v)
+{
+ T t;
+ t = v;
+ bitwise_xor(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
+ complement(T& result, V const& v)
+{
+ T t;
+ t = v;
+ complement(result, t);
+}
template <class T>
inline bool is_same_object(const T& u, const T&v)
@@ -145,6 +178,47 @@
modulus(t, v);
}
}
+template <class T, class U, class V>
+inline void bitwise_and(T& t, const U& u, const V& v)
+{
+ if(is_same_object(t, u))
+ bitwise_and(t, v);
+ else if(is_same_object(t, v))
+ bitwise_and(t, u);
+ else
+ {
+ t = u;
+ bitwise_and(t, v);
+ }
+}
+
+template <class T, class U, class V>
+inline void bitwise_or(T& t, const U& u, const V& v)
+{
+ if(is_same_object(t, u))
+ bitwise_or(t, v);
+ else if(is_same_object(t, v))
+ bitwise_or(t, u);
+ else
+ {
+ t = u;
+ bitwise_or(t, v);
+ }
+}
+
+template <class T, class U, class V>
+inline void bitwise_xor(T& t, const U& u, const V& v)
+{
+ if(is_same_object(t, u))
+ bitwise_xor(t, v);
+ else if(is_same_object(t, v))
+ bitwise_xor(t, u);
+ else
+ {
+ t = u;
+ bitwise_xor(t, v);
+ }
+}
template <class T>
inline void increment(T& val)
Modified: sandbox/big_number/boost/math/big_number/gmp.hpp
==============================================================================
--- sandbox/big_number/boost/math/big_number/gmp.hpp (original)
+++ sandbox/big_number/boost/math/big_number/gmp.hpp 2011-08-27 12:37:01 EDT (Sat, 27 Aug 2011)
@@ -910,6 +910,21 @@
mpz_fdiv_q_2exp(t.data(), v.data(), static_cast<mp_bitcnt_t>(i));
}
+inline void bitwise_and(gmp_int& result, const gmp_int& v)
+{
+ mpz_and(result.data(), result.data(), v.data());
+}
+
+inline void bitwise_or(gmp_int& result, const gmp_int& v)
+{
+ mpz_ior(result.data(), result.data(), v.data());
+}
+
+inline void bitwise_xor(gmp_int& result, const gmp_int& v)
+{
+ mpz_xor(result.data(), result.data(), v.data());
+}
+
inline void add(gmp_int& t, const gmp_int& p, const gmp_int& o)
{
mpz_add(t.data(), p.data(), o.data());
@@ -1013,6 +1028,26 @@
mpz_neg(t.data(), t.data());
}
+inline void bitwise_and(gmp_int& result, const gmp_int& u, const gmp_int& v)
+{
+ mpz_and(result.data(), u.data(), v.data());
+}
+
+inline void bitwise_or(gmp_int& result, const gmp_int& u, const gmp_int& v)
+{
+ mpz_ior(result.data(), u.data(), v.data());
+}
+
+inline void bitwise_xor(gmp_int& result, const gmp_int& u, const gmp_int& v)
+{
+ mpz_xor(result.data(), u.data(), v.data());
+}
+
+inline void complement(gmp_int& result, const gmp_int& u)
+{
+ mpz_com(result.data(), u.data());
+}
+
inline bool is_zero(const gmp_int& val)
{
return mpz_sgn(val.data()) == 0;
Modified: sandbox/big_number/libs/math/test/test_arithmetic.cpp
==============================================================================
--- sandbox/big_number/libs/math/test/test_arithmetic.cpp (original)
+++ sandbox/big_number/libs/math/test/test_arithmetic.cpp 2011-08-27 12:37:01 EDT (Sat, 27 Aug 2011)
@@ -59,6 +59,7 @@
{
Real a(20);
Real b(7);
+ Real c;
BOOST_TEST(a % b == 20 % 7);
BOOST_TEST(a % 7 == 20 % 7);
BOOST_TEST(a % 7u == 20 % 7);
@@ -155,6 +156,86 @@
b = (a + 3) >> 3;
BOOST_TEST(b == (23 >> 3));
//
+ // Bit fiddling:
+ //
+ int i = 1020304;
+ int j = 56789123;
+ int k = 4523187;
+ a = i;
+ b = j;
+ c = a;
+ c &= b;
+ BOOST_TEST(c == (i & j));
+ c = a;
+ c &= j;
+ BOOST_TEST(c == (i & j));
+ c = a;
+ c &= a + b;
+ BOOST_TEST(c == (i & (i + j)));
+ BOOST_TEST((a & b) == (i & j));
+ c = k;
+ a = a & (b + k);
+ BOOST_TEST(a == (i & (j + k)));
+ a = i;
+ a = (b + k) & a;
+ BOOST_TEST(a == (i & (j + k)));
+ a = i;
+ c = a & b & k;
+ BOOST_TEST(c == (i&j&k));
+
+ a = i;
+ b = j;
+ c = a;
+ c |= b;
+ BOOST_TEST(c == (i | j));
+ c = a;
+ c |= j;
+ BOOST_TEST(c == (i | j));
+ c = a;
+ c |= a + b;
+ BOOST_TEST(c == (i | (i + j)));
+ BOOST_TEST((a | b) == (i | j));
+ c = k;
+ a = a | (b + k);
+ BOOST_TEST(a == (i | (j + k)));
+ a = i;
+ a = (b + k) | a;
+ BOOST_TEST(a == (i | (j + k)));
+ a = i;
+ c = a | b | k;
+ BOOST_TEST(c == (i|j|k));
+
+ a = i;
+ b = j;
+ c = a;
+ c ^= b;
+ BOOST_TEST(c == (i ^ j));
+ c = a;
+ c ^= j;
+ BOOST_TEST(c == (i ^ j));
+ c = a;
+ c ^= a + b;
+ BOOST_TEST(c == (i ^ (i + j)));
+ BOOST_TEST((a ^ b) == (i ^ j));
+ c = k;
+ a = a ^ (b + k);
+ BOOST_TEST(a == (i ^ (j + k)));
+ a = i;
+ a = (b + k) ^ a;
+ BOOST_TEST(a == (i ^ (j + k)));
+ a = i;
+ c = a ^ b ^ k;
+ BOOST_TEST(c == (i^j^k));
+ a = i;
+ b = j;
+ c = k;
+ BOOST_TEST(~a == ~i);
+ c = a & ~b;
+ BOOST_TEST(c == (i & ~j));
+ c = ~(a | b);
+ BOOST_TEST(c == ~(i | j));
+
+ //
// Non-member functions:
//
a = -20;
@@ -389,6 +470,7 @@
template <class Real>
void test()
{
+#ifndef NO_MIXED_OPS
test_mixed<Real, unsigned char>();
test_mixed<Real, signed char>();
test_mixed<Real, char>();
@@ -405,6 +487,7 @@
test_mixed<Real, float>();
test_mixed<Real, double>();
test_mixed<Real, long double>();
+#endif
//
// Integer only functions:
//
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk