Boost logo

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