Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r80394 - in sandbox/big_number: boost/multiprecision boost/multiprecision/detail libs/multiprecision/test
From: john_at_[hidden]
Date: 2012-09-04 04:20:32


Author: johnmaddock
Date: 2012-09-04 04:20:26 EDT (Tue, 04 Sep 2012)
New Revision: 80394
URL: http://svn.boost.org/trac/boost/changeset/80394

Log:
Allow mixed precision binary operations.
Add tests for basic mixed precision usage.
Added:
   sandbox/big_number/boost/multiprecision/detail/et_ops.hpp (contents, props changed)
Text files modified:
   sandbox/big_number/boost/multiprecision/cpp_int.hpp | 9
   sandbox/big_number/boost/multiprecision/detail/default_ops.hpp | 106 +++--
   sandbox/big_number/boost/multiprecision/detail/no_et_ops.hpp | 90 +---
   sandbox/big_number/boost/multiprecision/detail/number_base.hpp | 644 ---------------------------------------
   sandbox/big_number/boost/multiprecision/detail/number_compare.hpp | 205 +++++++-----
   sandbox/big_number/boost/multiprecision/gmp.hpp | 14
   sandbox/big_number/boost/multiprecision/mpfr.hpp | 6
   sandbox/big_number/boost/multiprecision/number.hpp | 44 ++
   sandbox/big_number/boost/multiprecision/tommath.hpp | 14
   sandbox/big_number/libs/multiprecision/test/test_arithmetic.cpp | 86 +++++
   10 files changed, 354 insertions(+), 864 deletions(-)

Modified: sandbox/big_number/boost/multiprecision/cpp_int.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/cpp_int.hpp (original)
+++ sandbox/big_number/boost/multiprecision/cpp_int.hpp 2012-09-04 04:20:26 EDT (Tue, 04 Sep 2012)
@@ -3202,13 +3202,8 @@
       static number_type val;
       if(!init)
       {
- boost::multiprecision::limb_type l = ~static_cast<boost::multiprecision::limb_type>(0);
- unsigned c = MinBits / backend_type::limb_bits + (MinBits % backend_type::limb_bits ? 1 : 0);
- for(unsigned i = 0; i < c; ++i)
- {
- val <<= backend_type::limb_bits;
- val |= l;
- }
+ boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, false, void, trivial>, ExpressionTemplates> t(0);
+ val = ~t;
          init = true;
       }
       return val;

Modified: sandbox/big_number/boost/multiprecision/detail/default_ops.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/detail/default_ops.hpp (original)
+++ sandbox/big_number/boost/multiprecision/detail/default_ops.hpp 2012-09-04 04:20:26 EDT (Tue, 04 Sep 2012)
@@ -38,7 +38,7 @@
 // of each depending on whether the backend can be directly constructed from type V:
 //
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && !is_convertible<V, T>::value >::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value && !is_convertible<V, T>::value >::type
    eval_add(T& result, V const& v)
 {
    T t;
@@ -46,14 +46,14 @@
    eval_add(result, t);
 }
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && is_convertible<V, T>::value >::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value && is_convertible<V, T>::value >::type
    eval_add(T& result, V const& v)
 {
    T t(v);
    eval_add(result, t);
 }
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && !is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value && !is_convertible<V, T>::value>::type
    eval_subtract(T& result, V const& v)
 {
    T t;
@@ -61,14 +61,14 @@
    eval_subtract(result, t);
 }
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value && is_convertible<V, T>::value>::type
    eval_subtract(T& result, V const& v)
 {
    T t(v);
    eval_subtract(result, t);
 }
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && !is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value && !is_convertible<V, T>::value>::type
    eval_multiply(T& result, V const& v)
 {
    T t;
@@ -76,14 +76,14 @@
    eval_multiply(result, t);
 }
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value && is_convertible<V, T>::value>::type
    eval_multiply(T& result, V const& v)
 {
    T t(v);
    eval_multiply(result, t);
 }
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && !is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value && !is_convertible<V, T>::value>::type
    eval_divide(T& result, V const& v)
 {
    T t;
@@ -91,14 +91,14 @@
    eval_divide(result, t);
 }
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value && is_convertible<V, T>::value>::type
    eval_divide(T& result, V const& v)
 {
    T t(v);
    eval_divide(result, t);
 }
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && !is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value && !is_convertible<V, T>::value>::type
    eval_modulus(T& result, V const& v)
 {
    T t;
@@ -106,14 +106,14 @@
    eval_modulus(result, t);
 }
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value&& is_convertible<V, T>::value>::type
    eval_modulus(T& result, V const& v)
 {
    T t(v);
    eval_modulus(result, t);
 }
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && !is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value && !is_convertible<V, T>::value>::type
    eval_bitwise_and(T& result, V const& v)
 {
    T t;
@@ -121,14 +121,14 @@
    eval_bitwise_and(result, t);
 }
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value && is_convertible<V, T>::value>::type
    eval_bitwise_and(T& result, V const& v)
 {
    T t(v);
    eval_bitwise_and(result, t);
 }
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && !is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value && !is_convertible<V, T>::value>::type
    eval_bitwise_or(T& result, V const& v)
 {
    T t;
@@ -136,14 +136,14 @@
    eval_bitwise_or(result, t);
 }
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value && is_convertible<V, T>::value>::type
    eval_bitwise_or(T& result, V const& v)
 {
    T t(v);
    eval_bitwise_or(result, t);
 }
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && !is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value && !is_convertible<V, T>::value>::type
    eval_bitwise_xor(T& result, V const& v)
 {
    T t;
@@ -151,7 +151,7 @@
    eval_bitwise_xor(result, t);
 }
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value && is_convertible<V, T>::value>::type
    eval_bitwise_xor(T& result, V const& v)
 {
    T t(v);
@@ -159,7 +159,7 @@
 }
 
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && !is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value && !is_convertible<V, T>::value>::type
    eval_complement(T& result, V const& v)
 {
    T t;
@@ -167,7 +167,7 @@
    eval_complement(result, t);
 }
 template <class T, class V>
-inline typename enable_if_c<is_arithmetic<V>::value && is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, number<T> >::value && is_convertible<V, T>::value>::type
    eval_complement(T& result, V const& v)
 {
    T t(v);
@@ -195,20 +195,20 @@
    }
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && !is_convertible<U, T>::value>::type eval_add(T& t, const T& u, const U& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && !is_convertible<U, T>::value>::type eval_add(T& t, const T& u, const U& v)
 {
    T vv;
    vv = v;
    eval_add(t, u, vv);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && is_convertible<U, T>::value>::type eval_add(T& t, const T& u, const U& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && is_convertible<U, T>::value>::type eval_add(T& t, const T& u, const U& v)
 {
    T vv(v);
    eval_add(t, u, vv);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value>::type eval_add(T& t, const U& u, const T& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value>::type eval_add(T& t, const U& u, const T& v)
 {
    eval_add(t, v, u);
 }
@@ -232,20 +232,20 @@
    }
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && !is_convertible<U, T>::value>::type eval_subtract(T& t, const T& u, const U& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && !is_convertible<U, T>::value>::type eval_subtract(T& t, const T& u, const U& v)
 {
    T vv;
    vv = v;
    eval_subtract(t, u, vv);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && is_convertible<U, T>::value>::type eval_subtract(T& t, const T& u, const U& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && is_convertible<U, T>::value>::type eval_subtract(T& t, const T& u, const U& v)
 {
    T vv(v);
    eval_subtract(t, u, vv);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value>::type eval_subtract(T& t, const U& u, const T& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value>::type eval_subtract(T& t, const U& u, const T& v)
 {
    eval_subtract(t, v, u);
    t.negate();
@@ -269,20 +269,20 @@
    }
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && !is_convertible<U, T>::value>::type eval_multiply(T& t, const T& u, const U& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && !is_convertible<U, T>::value>::type eval_multiply(T& t, const T& u, const U& v)
 {
    T vv;
    vv = v;
    eval_multiply(t, u, vv);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && is_convertible<U, T>::value>::type eval_multiply(T& t, const T& u, const U& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && is_convertible<U, T>::value>::type eval_multiply(T& t, const T& u, const U& v)
 {
    T vv(v);
    eval_multiply(t, u, vv);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value>::type eval_multiply(T& t, const U& u, const T& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value>::type eval_multiply(T& t, const U& u, const T& v)
 {
    eval_multiply(t, v, u);
 }
@@ -305,27 +305,27 @@
    }
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && !is_convertible<U, T>::value>::type eval_divide(T& t, const T& u, const U& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && !is_convertible<U, T>::value>::type eval_divide(T& t, const T& u, const U& v)
 {
    T vv;
    vv = v;
    eval_divide(t, u, vv);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && is_convertible<U, T>::value>::type eval_divide(T& t, const T& u, const U& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && is_convertible<U, T>::value>::type eval_divide(T& t, const T& u, const U& v)
 {
    T vv(v);
    eval_divide(t, u, vv);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && !is_convertible<U, T>::value>::type eval_divide(T& t, const U& u, const T& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && !is_convertible<U, T>::value>::type eval_divide(T& t, const U& u, const T& v)
 {
    T uu;
    uu = u;
    eval_divide(t, uu, v);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && is_convertible<U, T>::value>::type eval_divide(T& t, const U& u, const T& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && is_convertible<U, T>::value>::type eval_divide(T& t, const U& u, const T& v)
 {
    T uu(u);
    eval_divide(t, uu, v);
@@ -350,27 +350,27 @@
    }
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && !is_convertible<U, T>::value>::type eval_modulus(T& t, const T& u, const U& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && !is_convertible<U, T>::value>::type eval_modulus(T& t, const T& u, const U& v)
 {
    T vv;
    vv = v;
    eval_modulus(t, u, vv);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && is_convertible<U, T>::value>::type eval_modulus(T& t, const T& u, const U& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && is_convertible<U, T>::value>::type eval_modulus(T& t, const T& u, const U& v)
 {
    T vv(v);
    eval_modulus(t, u, vv);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && !is_convertible<U, T>::value>::type eval_modulus(T& t, const U& u, const T& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && !is_convertible<U, T>::value>::type eval_modulus(T& t, const U& u, const T& v)
 {
    T uu;
    uu = u;
    eval_modulus(t, uu, v);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && is_convertible<U, T>::value>::type eval_modulus(T& t, const U& u, const T& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && is_convertible<U, T>::value>::type eval_modulus(T& t, const U& u, const T& v)
 {
    T uu(u);
    eval_modulus(t, uu, v);
@@ -394,20 +394,20 @@
    }
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && !is_convertible<U, T>::value>::type eval_bitwise_and(T& t, const T& u, const U& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && !is_convertible<U, T>::value>::type eval_bitwise_and(T& t, const T& u, const U& v)
 {
    T vv;
    vv = v;
    eval_bitwise_and(t, u, vv);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && is_convertible<U, T>::value>::type eval_bitwise_and(T& t, const T& u, const U& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && is_convertible<U, T>::value>::type eval_bitwise_and(T& t, const T& u, const U& v)
 {
    T vv(v);
    eval_bitwise_and(t, u, vv);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value>::type eval_bitwise_and(T& t, const U& u, const T& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value>::type eval_bitwise_and(T& t, const U& u, const T& v)
 {
    eval_bitwise_and(t, v, u);
 }
@@ -430,20 +430,20 @@
    }
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && !is_convertible<U, T>::value>::type eval_bitwise_or(T& t, const T& u, const U& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && !is_convertible<U, T>::value>::type eval_bitwise_or(T& t, const T& u, const U& v)
 {
    T vv;
    vv = v;
    eval_bitwise_or(t, u, vv);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && is_convertible<U, T>::value>::type eval_bitwise_or(T& t, const T& u, const U& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && is_convertible<U, T>::value>::type eval_bitwise_or(T& t, const T& u, const U& v)
 {
    T vv(v);
    eval_bitwise_or(t, u, vv);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value>::type eval_bitwise_or(T& t, const U& u, const T& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value>::type eval_bitwise_or(T& t, const U& u, const T& v)
 {
    eval_bitwise_or(t, v, u);
 }
@@ -466,20 +466,20 @@
    }
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && !is_convertible<U, T>::value>::type eval_bitwise_xor(T& t, const T& u, const U& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && !is_convertible<U, T>::value>::type eval_bitwise_xor(T& t, const T& u, const U& v)
 {
    T vv;
    vv = v;
    eval_bitwise_xor(t, u, vv);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value && is_convertible<U, T>::value>::type eval_bitwise_xor(T& t, const T& u, const U& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value && is_convertible<U, T>::value>::type eval_bitwise_xor(T& t, const T& u, const U& v)
 {
    T vv(v);
    eval_bitwise_xor(t, u, vv);
 }
 template <class T, class U>
-inline typename enable_if_c<is_arithmetic<U>::value>::type eval_bitwise_xor(T& t, const U& u, const T& v)
+inline typename enable_if_c<is_convertible<U, number<T> >::value>::type eval_bitwise_xor(T& t, const U& u, const T& v)
 {
    eval_bitwise_xor(t, v, u);
 }
@@ -580,13 +580,28 @@
>::type type;
 };
 
+template <class R, class T>
+inline bool check_in_range(const T& t)
+{
+ // Can t fit in an R?
+ if(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (t > (std::numeric_limits<R>::max)()))
+ return true;
+ return false;
+}
+
+template <class R, class T>
+inline bool check_in_range(const terminal<T>&)
+{
+ return false;
+}
+
 template <class R, class B>
 inline void eval_convert_to(R* result, const B& backend)
 {
    typedef typename calculate_next_larger_type<R, B>::type next_type;
    next_type n;
    eval_convert_to(&n, backend);
- if(std::numeric_limits<R>::is_specialized && (n > (std::numeric_limits<R>::max)()))
+ if(check_in_range<R>(n))
    {
       *result = (std::numeric_limits<R>::max)();
    }
@@ -1617,6 +1632,7 @@
 // This has to come last of all:
 //
 #include <boost/multiprecision/detail/no_et_ops.hpp>
+#include <boost/multiprecision/detail/et_ops.hpp>
 
 #endif
 

Added: sandbox/big_number/boost/multiprecision/detail/et_ops.hpp
==============================================================================
--- (empty file)
+++ sandbox/big_number/boost/multiprecision/detail/et_ops.hpp 2012-09-04 04:20:26 EDT (Tue, 04 Sep 2012)
@@ -0,0 +1,691 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2011 John Maddock. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_ET_OPS_HPP
+#define BOOST_MP_ET_OPS_HPP
+
+namespace boost{ namespace multiprecision{
+
+//
+// Non-member operators for number:
+//
+// Unary operators first:
+//
+template <class B, bool ExpressionTemplates>
+inline const number<B, ExpressionTemplates>& operator + (const number<B, ExpressionTemplates>& v) { return v; }
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& operator + (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return v; }
+template <class B>
+inline detail::expression<detail::negate, number<B, true> > operator - (const number<B, true>& v) { return detail::expression<detail::negate, number<B, true> >(v); }
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline detail::expression<detail::negate, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > operator - (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return detail::expression<detail::negate, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(v); }
+template <class B>
+inline detail::expression<detail::complement_immediates, number<B, true> > operator ~ (const number<B, true>& v) { return detail::expression<detail::complement_immediates, number<B, true> >(v); }
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline detail::expression<detail::bitwise_complement, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > operator ~ (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return detail::expression<detail::bitwise_complement, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(v); }
+//
+// Then addition:
+//
+template <class B>
+inline detail::expression<detail::add_immediates, number<B, true>, number<B, true> >
+ operator + (const number<B, true>& a, const number<B, true>& b)
+{
+ return detail::expression<detail::add_immediates, number<B, true>, number<B, true> >(a, b);
+}
+template <class B, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::add_immediates, number<B, true>, V > >::type
+ operator + (const number<B, true>& a, const V& b)
+{
+ return detail::expression<detail::add_immediates, number<B, true>, V >(a, b);
+}
+template <class V, class B>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::add_immediates, V, number<B, true> > >::type
+ operator + (const V& a, const number<B, true>& b)
+{
+ return detail::expression<detail::add_immediates, V, number<B, true> >(a, b);
+}
+template <class B, bool ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
+ operator + (const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, bool ET>
+inline detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
+ operator + (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+{
+ return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
+inline detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
+ operator + (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
+{
+ return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
+ operator + (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+{
+ return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
+}
+template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::plus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+ operator + (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::plus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+//
+// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
+//
+template <class B, bool ET, class Arg1, class Arg2, class Arg3, class Arg4>
+inline detail::expression<detail::minus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >
+ operator + (const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::minus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(a, b.left_ref());
+}
+template <class Arg1, class Arg2, class Arg3, class Arg4, class B, bool ET>
+inline detail::expression<detail::minus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >
+ operator + (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+{
+ return detail::expression<detail::minus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(b, a.left_ref());
+}
+template <class B>
+inline detail::expression<detail::subtract_immediates, number<B, true>, number<B, true> >
+ operator + (const number<B, true>& a, const detail::expression<detail::negate, number<B, true> >& b)
+{
+ return detail::expression<detail::subtract_immediates, number<B, true>, number<B, true> >(a, b.left_ref());
+}
+template <class B>
+inline detail::expression<detail::subtract_immediates, number<B, true>, number<B, true> >
+ operator + (const detail::expression<detail::negate, number<B, true> >& a, const number<B, true>& b)
+{
+ return detail::expression<detail::subtract_immediates, number<B, true>, number<B, true> >(b, a.left_ref());
+}
+template <class B, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::subtract_immediates, V, number<B, true> > >::type
+ operator + (const detail::expression<detail::negate, number<B, true> >& a, const V& b)
+{
+ return detail::expression<detail::subtract_immediates, V, number<B, true> >(b, a.left_ref());
+}
+template <class B, class B2, bool ET>
+inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, true> >, detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, true> > >::type
+ operator + (const detail::expression<detail::negate, number<B, true> >& a, const number<B2, ET>& b)
+{
+ return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, true> >(b, a.left_ref());
+}
+template <class B2, bool ET, class B>
+inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, true> >, detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, true> > >::type
+ operator + (const number<B2, ET>& a, const detail::expression<detail::negate, number<B, true> >& b)
+{
+ return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, true> >(a, b.left_ref());
+}
+template <class B>
+inline detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, true>, number<B, true> > >
+ operator + (const detail::expression<detail::negate, number<B, true> >& a, const detail::expression<detail::negate, number<B, true> >& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, true>, number<B, true> > >(detail::expression<detail::add_immediates, number<B, true>, number<B, true> >(a.left_ref(), b.left_ref()));
+}
+//
+// Subtraction:
+//
+template <class B>
+inline detail::expression<detail::subtract_immediates, number<B, true>, number<B, true> >
+ operator - (const number<B, true>& a, const number<B, true>& b)
+{
+ return detail::expression<detail::subtract_immediates, number<B, true>, number<B, true> >(a, b);
+}
+template <class B, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::subtract_immediates, number<B, true>, V > >::type
+ operator - (const number<B, true>& a, const V& b)
+{
+ return detail::expression<detail::subtract_immediates, number<B, true>, V >(a, b);
+}
+template <class V, class B>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::subtract_immediates, V, number<B, true> > >::type
+ operator - (const V& a, const number<B, true>& b)
+{
+ return detail::expression<detail::subtract_immediates, V, number<B, true> >(a, b);
+}
+template <class B, bool ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
+ operator - (const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, bool ET>
+inline detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
+ operator - (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+{
+ return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
+inline detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
+ operator - (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
+{
+ return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
+ operator - (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+{
+ return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
+}
+template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::minus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+ operator - (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::minus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+//
+// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
+//
+template <class B, bool ET, class Arg1, class Arg2, class Arg3, class Arg4>
+inline detail::expression<detail::plus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >
+ operator - (const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::plus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(a, b.left_ref());
+}
+template <class Arg1, class Arg2, class Arg3, class Arg4, class B, bool ET>
+inline detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >
+ operator - (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >(
+ detail::expression<detail::plus, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(b, a.left_ref()));
+}
+template <class B>
+inline detail::expression<detail::add_immediates, number<B, true>, number<B, true> >
+ operator - (const number<B, true>& a, const detail::expression<detail::negate, number<B, true> >& b)
+{
+ return detail::expression<detail::add_immediates, number<B, true>, number<B, true> >(a, b.left_ref());
+}
+template <class B>
+inline detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, true>, number<B, true> > >
+ operator - (const detail::expression<detail::negate, number<B, true> >& a, const number<B, true>& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, true>, number<B, true> > >(
+ detail::expression<detail::add_immediates, number<B, true>, number<B, true> >(b, a.left_ref()));
+}
+template <class B, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, true>, V > > >::type
+ operator - (const detail::expression<detail::negate, number<B, true> >& a, const V& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, true>, V > >(detail::expression<detail::add_immediates, number<B, true>, V >(a.left_ref(), b));
+}
+template <class B, class B2, bool ET>
+inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, true> >, detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, true>, number<B2, ET> > > >::type
+ operator - (const detail::expression<detail::negate, number<B, true> >& a, const number<B2, ET>& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, true>, number<B2, ET> > >(detail::expression<detail::add_immediates, number<B, true>, number<B2, ET> >(a.left_ref(), b));
+}
+template <class V, class B>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::add_immediates, V, number<B, true> > >::type
+ operator - (const V& a, const detail::expression<detail::negate, number<B, true> >& b)
+{
+ return detail::expression<detail::add_immediates, V, number<B, true> >(a, b.left_ref());
+}
+template <class B2, bool ET, class B>
+inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, true> >, detail::expression<detail::add_immediates, number<B2, ET>, number<B, true> > >::type
+ operator - (const number<B2, ET>& a, const detail::expression<detail::negate, number<B, true> >& b)
+{
+ return detail::expression<detail::add_immediates, number<B2, ET>, number<B, true> >(a, b.left_ref());
+}
+//
+// Multiplication:
+//
+template <class B>
+inline detail::expression<detail::multiply_immediates, number<B, true>, number<B, true> >
+ operator * (const number<B, true>& a, const number<B, true>& b)
+{
+ return detail::expression<detail::multiply_immediates, number<B, true>, number<B, true> >(a, b);
+}
+template <class B, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::multiply_immediates, number<B, true>, V > >::type
+ operator * (const number<B, true>& a, const V& b)
+{
+ return detail::expression<detail::multiply_immediates, number<B, true>, V >(a, b);
+}
+template <class V, class B>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::multiply_immediates, V, number<B, true> > >::type
+ operator * (const V& a, const number<B, true>& b)
+{
+ return detail::expression<detail::multiply_immediates, V, number<B, true> >(a, b);
+}
+template <class B, bool ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
+ operator * (const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, bool ET>
+inline detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
+ operator * (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+{
+ return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
+inline detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
+ operator * (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
+{
+ return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
+ operator * (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+{
+ return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
+}
+template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::multiplies, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+ operator * (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::multiplies, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+//
+// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
+//
+template <class B, bool ET, class Arg1, class Arg2, class Arg3, class Arg4>
+inline detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >
+ operator * (const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >(
+ detail::expression<detail::multiplies, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > (a, b.left_ref()));
+}
+template <class Arg1, class Arg2, class Arg3, class Arg4, class B, bool ET>
+inline detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >
+ operator * (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >(
+ detail::expression<detail::multiplies, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(b, a.left_ref()));
+}
+template <class B>
+inline detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, number<B, true> > >
+ operator * (const number<B, true>& a, const detail::expression<detail::negate, number<B, true> >& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, number<B, true> > >(
+ detail::expression<detail::multiply_immediates, number<B, true>, number<B, true> >(a, b.left_ref()));
+}
+template <class B>
+inline detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, number<B, true> > >
+ operator * (const detail::expression<detail::negate, number<B, true> >& a, const number<B, true>& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, number<B, true> > >(
+ detail::expression<detail::multiply_immediates, number<B, true>, number<B, true> >(b, a.left_ref()));
+}
+template <class B, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, V > > >::type
+ operator * (const detail::expression<detail::negate, number<B, true> >& a, const V& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, V > > (
+ detail::expression<detail::multiply_immediates, number<B, true>, V >(a.left_ref(), b));
+}
+template <class B, class B2, bool ET>
+inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, true> >, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, number<B2, ET> > > >::type
+ operator * (const detail::expression<detail::negate, number<B, true> >& a, const number<B2, ET>& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, number<B2, ET> > > (
+ detail::expression<detail::multiply_immediates, number<B, true>, number<B2, ET> >(a.left_ref(), b));
+}
+template <class V, class B>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, V > > >::type
+ operator * (const V& a, const detail::expression<detail::negate, number<B, true> >& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, V > >(
+ detail::expression<detail::multiply_immediates, number<B, true>, V >(b.left_ref(), a));
+}
+template <class B2, bool ET, class B>
+inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, true> >, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, number<B2, ET> > > >::type
+ operator * (const number<B2, ET>& a, const detail::expression<detail::negate, number<B, true> >& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, number<B2, ET> > >(
+ detail::expression<detail::multiply_immediates, number<B, true>, number<B2, ET> >(b.left_ref(), a));
+}
+//
+// Division:
+//
+template <class B>
+inline detail::expression<detail::divide_immediates, number<B, true>, number<B, true> >
+ operator / (const number<B, true>& a, const number<B, true>& b)
+{
+ return detail::expression<detail::divide_immediates, number<B, true>, number<B, true> >(a, b);
+}
+template <class B, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::divide_immediates, number<B, true>, V > >::type
+ operator / (const number<B, true>& a, const V& b)
+{
+ return detail::expression<detail::divide_immediates, number<B, true>, V >(a, b);
+}
+template <class V, class B>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::divide_immediates, V, number<B, true> > >::type
+ operator / (const V& a, const number<B, true>& b)
+{
+ return detail::expression<detail::divide_immediates, V, number<B, true> >(a, b);
+}
+template <class B, bool ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
+ operator / (const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, bool ET>
+inline detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
+ operator / (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+{
+ return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
+inline detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
+ operator / (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
+{
+ return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
+ operator / (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+{
+ return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
+}
+template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::divides, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+ operator / (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::divides, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+//
+// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
+//
+template <class B, bool ET, class Arg1, class Arg2, class Arg3, class Arg4>
+inline detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >
+ operator / (const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >(
+ detail::expression<detail::divides, number<B, ET>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(a, b.left_ref()));
+}
+template <class Arg1, class Arg2, class Arg3, class Arg4, class B, bool ET>
+inline detail::expression<detail::negate, detail::expression<detail::divides, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type, number<B, ET> > >
+ operator / (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::divides, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type, number<B, ET> > >(
+ detail::expression<detail::divides, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type, number<B, ET> >(a.left_ref(), b));
+}
+template <class B>
+inline detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, true>, number<B, true> > >
+ operator / (const number<B, true>& a, const detail::expression<detail::negate, number<B, true> >& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, true>, number<B, true> > >(
+ detail::expression<detail::divide_immediates, number<B, true>, number<B, true> >(a, b.left_ref()));
+}
+template <class B>
+inline detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, true>, number<B, true> > >
+ operator / (const detail::expression<detail::negate, number<B, true> >& a, const number<B, true>& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, true>, number<B, true> > >(
+ detail::expression<detail::divide_immediates, number<B, true>, number<B, true> >(a.left_ref(), b));
+}
+template <class B, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, true>, V > > >::type
+ operator / (const detail::expression<detail::negate, number<B, true> >& a, const V& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, true>, V > >(
+ detail::expression<detail::divide_immediates, number<B, true>, V>(a.left_ref(), b));
+}
+template <class B, class B2, bool ET>
+inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, true> >, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, true>, number<B2, ET> > > >::type
+ operator / (const detail::expression<detail::negate, number<B, true> >& a, const number<B2, ET>& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, true>, number<B2, ET> > >(
+ detail::expression<detail::divide_immediates, number<B, true>, number<B2, ET> >(a.left_ref(), b));
+}
+template <class V, class B>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::negate, detail::expression<detail::divide_immediates, V, number<B, true> > > >::type
+ operator / (const V& a, const detail::expression<detail::negate, number<B, true> >& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::divide_immediates, V, number<B, true> > >(
+ detail::expression<detail::divide_immediates, V, number<B, true> >(a, b.left_ref()));
+}
+template <class B2, bool ET, class B>
+inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, true> >, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, true> > > >::type
+ operator / (const number<B2, ET>& a, const detail::expression<detail::negate, number<B, true> >& b)
+{
+ return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, true> > >(
+ detail::expression<detail::divide_immediates, number<B2, ET>, number<B, true> >(a, b.left_ref()));
+}
+//
+// Modulus:
+//
+template <class B>
+inline detail::expression<detail::modulus_immediates, number<B, true>, number<B, true> >
+ operator % (const number<B, true>& a, const number<B, true>& b)
+{
+ return detail::expression<detail::modulus_immediates, number<B, true>, number<B, true> >(a, b);
+}
+template <class B, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::modulus_immediates, number<B, true>, V > >::type
+ operator % (const number<B, true>& a, const V& b)
+{
+ return detail::expression<detail::modulus_immediates, number<B, true>, V >(a, b);
+}
+template <class V, class B>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::modulus_immediates, V, number<B, true> > >::type
+ operator % (const V& a, const number<B, true>& b)
+{
+ return detail::expression<detail::modulus_immediates, V, number<B, true> >(a, b);
+}
+template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline detail::expression<detail::modulus, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
+ operator % (const number<B, true>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::modulus, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
+inline detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >
+ operator % (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, true>& b)
+{
+ return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
+inline detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
+ operator % (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
+{
+ return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
+ operator % (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+{
+ return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
+}
+template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::modulus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+ operator % (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::modulus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+//
+// Left shift:
+//
+template <class B, class I>
+inline typename enable_if<is_integral<I>, detail::expression<detail::shift_left, number<B, true>, I > >::type
+ operator << (const number<B, true>& a, const I& b)
+{
+ return detail::expression<detail::shift_left, number<B, true>, I>(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
+inline typename enable_if<is_integral<I>, detail::expression<detail::shift_left, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
+ operator << (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
+{
+ return detail::expression<detail::shift_left, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I>(a, b);
+}
+//
+// Right shift:
+//
+template <class B, class I>
+inline typename enable_if<is_integral<I>, detail::expression<detail::shift_right, number<B, true>, I > >::type
+ operator >> (const number<B, true>& a, const I& b)
+{
+ return detail::expression<detail::shift_right, number<B, true>, I>(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
+inline typename enable_if<is_integral<I>, detail::expression<detail::shift_right, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
+ operator >> (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
+{
+ return detail::expression<detail::shift_right, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I>(a, b);
+}
+//
+// Bitwise AND:
+//
+template <class B>
+inline detail::expression<detail::bitwise_and_immediates, number<B, true>, number<B, true> >
+ operator & (const number<B, true>& a, const number<B, true>& b)
+{
+ return detail::expression<detail::bitwise_and_immediates, number<B, true>, number<B, true> >(a, b);
+}
+template <class B, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::bitwise_and_immediates, number<B, true>, V > >::type
+ operator & (const number<B, true>& a, const V& b)
+{
+ return detail::expression<detail::bitwise_and_immediates, number<B, true>, V >(a, b);
+}
+template <class V, class B>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::bitwise_and_immediates, V, number<B, true> > >::type
+ operator & (const V& a, const number<B, true>& b)
+{
+ return detail::expression<detail::bitwise_and_immediates, V, number<B, true> >(a, b);
+}
+template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline detail::expression<detail::bitwise_and, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
+ operator & (const number<B, true>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::bitwise_and, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
+inline detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >
+ operator & (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, true>& b)
+{
+ return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
+inline detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
+ operator & (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
+{
+ return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
+ operator & (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+{
+ return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
+}
+template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::bitwise_and, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+ operator & (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::bitwise_and, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+//
+// Bitwise OR:
+//
+template <class B>
+inline detail::expression<detail::bitwise_or_immediates, number<B, true>, number<B, true> >
+ operator| (const number<B, true>& a, const number<B, true>& b)
+{
+ return detail::expression<detail::bitwise_or_immediates, number<B, true>, number<B, true> >(a, b);
+}
+template <class B, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::bitwise_or_immediates, number<B, true>, V > >::type
+ operator| (const number<B, true>& a, const V& b)
+{
+ return detail::expression<detail::bitwise_or_immediates, number<B, true>, V >(a, b);
+}
+template <class V, class B>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::bitwise_or_immediates, V, number<B, true> > >::type
+ operator| (const V& a, const number<B, true>& b)
+{
+ return detail::expression<detail::bitwise_or_immediates, V, number<B, true> >(a, b);
+}
+template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline detail::expression<detail::bitwise_or, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
+ operator| (const number<B, true>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::bitwise_or, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
+inline detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >
+ operator| (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, true>& b)
+{
+ return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
+inline detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
+ operator| (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
+{
+ return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
+ operator| (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+{
+ return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
+}
+template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::bitwise_or, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+ operator| (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::bitwise_or, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+//
+// Bitwise XOR:
+//
+template <class B>
+inline detail::expression<detail::bitwise_xor_immediates, number<B, true>, number<B, true> >
+ operator^ (const number<B, true>& a, const number<B, true>& b)
+{
+ return detail::expression<detail::bitwise_xor_immediates, number<B, true>, number<B, true> >(a, b);
+}
+template <class B, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::bitwise_xor_immediates, number<B, true>, V > >::type
+ operator^ (const number<B, true>& a, const V& b)
+{
+ return detail::expression<detail::bitwise_xor_immediates, number<B, true>, V >(a, b);
+}
+template <class V, class B>
+inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::bitwise_xor_immediates, V, number<B, true> > >::type
+ operator^ (const V& a, const number<B, true>& b)
+{
+ return detail::expression<detail::bitwise_xor_immediates, V, number<B, true> >(a, b);
+}
+template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline detail::expression<detail::bitwise_xor, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
+ operator^ (const number<B, true>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::bitwise_xor, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
+inline detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >
+ operator^ (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, true>& b)
+{
+ return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
+inline detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
+ operator^ (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
+{
+ return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
+}
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
+inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
+ operator^ (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
+{
+ return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
+}
+template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::bitwise_xor, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
+ operator^ (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
+{
+ return detail::expression<detail::bitwise_xor, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
+}
+
+}} // namespaces
+
+#endif

Modified: sandbox/big_number/boost/multiprecision/detail/no_et_ops.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/detail/no_et_ops.hpp (original)
+++ sandbox/big_number/boost/multiprecision/detail/no_et_ops.hpp 2012-09-04 04:20:26 EDT (Tue, 04 Sep 2012)
@@ -43,20 +43,18 @@
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator + (const number<B, false>& a, const V& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    number<B, false> result;
    using default_ops::eval_add;
- eval_add(result.backend(), a.backend(), static_cast<canonical_type>(b));
+ eval_add(result.backend(), a.backend(), number<B, false>::canonical_value(b));
    return BOOST_MP_MOVE(result);
 }
 template <class V, class B>
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator + (const V& a, const number<B, false>& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    number<B, false> result;
    using default_ops::eval_add;
- eval_add(result.backend(), b.backend(), static_cast<canonical_type>(a));
+ eval_add(result.backend(), b.backend(), number<B, false>::canonical_value(a));
    return BOOST_MP_MOVE(result);
 }
 //
@@ -74,20 +72,18 @@
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator - (const number<B, false>& a, const V& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    number<B, false> result;
    using default_ops::eval_subtract;
- eval_subtract(result.backend(), a.backend(), static_cast<canonical_type>(b));
+ eval_subtract(result.backend(), a.backend(), number<B, false>::canonical_value(b));
    return BOOST_MP_MOVE(result);
 }
 template <class V, class B>
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator - (const V& a, const number<B, false>& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    number<B, false> result;
    using default_ops::eval_subtract;
- eval_subtract(result.backend(), static_cast<canonical_type>(a), b.backend());
+ eval_subtract(result.backend(), number<B, false>::canonical_value(a), b.backend());
    return BOOST_MP_MOVE(result);
 }
 //
@@ -105,20 +101,18 @@
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator * (const number<B, false>& a, const V& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    number<B, false> result;
    using default_ops::eval_multiply;
- eval_multiply(result.backend(), a.backend(), static_cast<canonical_type>(b));
+ eval_multiply(result.backend(), a.backend(), number<B, false>::canonical_value(b));
    return BOOST_MP_MOVE(result);
 }
 template <class V, class B>
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator * (const V& a, const number<B, false>& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    number<B, false> result;
    using default_ops::eval_multiply;
- eval_multiply(result.backend(), b.backend(), static_cast<canonical_type>(a));
+ eval_multiply(result.backend(), b.backend(), number<B, false>::canonical_value(a));
    return BOOST_MP_MOVE(result);
 }
 //
@@ -136,20 +130,18 @@
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator / (const number<B, false>& a, const V& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    number<B, false> result;
    using default_ops::eval_divide;
- eval_divide(result.backend(), a.backend(), static_cast<canonical_type>(b));
+ eval_divide(result.backend(), a.backend(), number<B, false>::canonical_value(b));
    return BOOST_MP_MOVE(result);
 }
 template <class V, class B>
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator / (const V& a, const number<B, false>& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    number<B, false> result;
    using default_ops::eval_divide;
- eval_divide(result.backend(), static_cast<canonical_type>(a), b.backend());
+ eval_divide(result.backend(), number<B, false>::canonical_value(a), b.backend());
    return BOOST_MP_MOVE(result);
 }
 //
@@ -167,20 +159,18 @@
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator % (const number<B, false>& a, const V& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    number<B, false> result;
    using default_ops::eval_modulus;
- eval_modulus(result.backend(), a.backend(), static_cast<canonical_type>(b));
+ eval_modulus(result.backend(), a.backend(), number<B, false>::canonical_value(b));
    return BOOST_MP_MOVE(result);
 }
 template <class V, class B>
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator % (const V& a, const number<B, false>& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    number<B, false> result;
    using default_ops::eval_modulus;
- eval_modulus(result.backend(), static_cast<canonical_type>(a), b.backend());
+ eval_modulus(result.backend(), number<B, false>::canonical_value(a), b.backend());
    return BOOST_MP_MOVE(result);
 }
 //
@@ -198,20 +188,18 @@
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator | (const number<B, false>& a, const V& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    number<B, false> result;
    using default_ops::eval_bitwise_or;
- eval_bitwise_or(result.backend(), a.backend(), static_cast<canonical_type>(b));
+ eval_bitwise_or(result.backend(), a.backend(), number<B, false>::canonical_value(b));
    return BOOST_MP_MOVE(result);
 }
 template <class V, class B>
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator | (const V& a, const number<B, false>& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    number<B, false> result;
    using default_ops::eval_bitwise_or;
- eval_bitwise_or(result.backend(), b.backend(), static_cast<canonical_type>(a));
+ eval_bitwise_or(result.backend(), b.backend(), number<B, false>::canonical_value(a));
    return BOOST_MP_MOVE(result);
 }
 //
@@ -229,20 +217,18 @@
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator ^ (const number<B, false>& a, const V& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    number<B, false> result;
    using default_ops::eval_bitwise_xor;
- eval_bitwise_xor(result.backend(), a.backend(), static_cast<canonical_type>(b));
+ eval_bitwise_xor(result.backend(), a.backend(), number<B, false>::canonical_value(b));
    return BOOST_MP_MOVE(result);
 }
 template <class V, class B>
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator ^ (const V& a, const number<B, false>& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    number<B, false> result;
    using default_ops::eval_bitwise_xor;
- eval_bitwise_xor(result.backend(), b.backend(), static_cast<canonical_type>(a));
+ eval_bitwise_xor(result.backend(), b.backend(), number<B, false>::canonical_value(a));
    return BOOST_MP_MOVE(result);
 }
 //
@@ -260,20 +246,18 @@
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator & (const number<B, false>& a, const V& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    number<B, false> result;
    using default_ops::eval_bitwise_and;
- eval_bitwise_and(result.backend(), a.backend(), static_cast<canonical_type>(b));
+ eval_bitwise_and(result.backend(), a.backend(), number<B, false>::canonical_value(b));
    return BOOST_MP_MOVE(result);
 }
 template <class V, class B>
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator & (const V& a, const number<B, false>& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    number<B, false> result;
    using default_ops::eval_bitwise_and;
- eval_bitwise_and(result.backend(), b.backend(), static_cast<canonical_type>(a));
+ eval_bitwise_and(result.backend(), b.backend(), number<B, false>::canonical_value(a));
    return BOOST_MP_MOVE(result);
 }
 //
@@ -352,18 +336,16 @@
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator + (number<B, false>&& a, const V& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    using default_ops::eval_add;
- eval_add(a.backend(), static_cast<canonical_type>(b));
+ eval_add(a.backend(), number<B, false>::canonical_value(b));
    return static_cast<number<B, false>&&>(a);
 }
 template <class V, class B>
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator + (const V& a, number<B, false>&& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    using default_ops::eval_add;
- eval_add(b.backend(), static_cast<canonical_type>(a));
+ eval_add(b.backend(), number<B, false>::canonical_value(a));
    return static_cast<number<B, false>&&>(b);
 }
 //
@@ -395,18 +377,16 @@
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator - (number<B, false>&& a, const V& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    using default_ops::eval_subtract;
- eval_subtract(a.backend(), static_cast<canonical_type>(b));
+ eval_subtract(a.backend(), number<B, false>::canonical_value(b));
    return static_cast<number<B, false>&&>(a);
 }
 template <class V, class B>
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator - (const V& a, number<B, false>&& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    using default_ops::eval_subtract;
- eval_subtract(b.backend(), static_cast<canonical_type>(a));
+ eval_subtract(b.backend(), number<B, false>::canonical_value(a));
    b.backend().negate();
    return static_cast<number<B, false>&&>(b);
 }
@@ -438,18 +418,16 @@
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator * (number<B, false>&& a, const V& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    using default_ops::eval_multiply;
- eval_multiply(a.backend(), static_cast<canonical_type>(b));
+ eval_multiply(a.backend(), number<B, false>::canonical_value(b));
    return static_cast<number<B, false>&&>(a);
 }
 template <class V, class B>
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator * (const V& a, number<B, false>&& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    using default_ops::eval_multiply;
- eval_multiply(b.backend(), static_cast<canonical_type>(a));
+ eval_multiply(b.backend(), number<B, false>::canonical_value(a));
    return static_cast<number<B, false>&&>(b);
 }
 //
@@ -466,9 +444,8 @@
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator / (number<B, false>&& a, const V& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    using default_ops::eval_divide;
- eval_divide(a.backend(), static_cast<canonical_type>(b));
+ eval_divide(a.backend(), number<B, false>::canonical_value(b));
    return static_cast<number<B, false>&&>(a);
 }
 //
@@ -485,9 +462,8 @@
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator % (number<B, false>&& a, const V& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    using default_ops::eval_modulus;
- eval_modulus(a.backend(), static_cast<canonical_type>(b));
+ eval_modulus(a.backend(), number<B, false>::canonical_value(b));
    return static_cast<number<B, false>&&>(a);
 }
 //
@@ -518,18 +494,16 @@
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator | (number<B, false>&& a, const V& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    using default_ops::eval_bitwise_or;
- eval_bitwise_or(a.backend(), static_cast<canonical_type>(b));
+ eval_bitwise_or(a.backend(), number<B, false>::canonical_value(b));
    return static_cast<number<B, false>&&>(a);
 }
 template <class V, class B>
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator | (const V& a, number<B, false>&& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    using default_ops::eval_bitwise_or;
- eval_bitwise_or(b.backend(), static_cast<canonical_type>(a));
+ eval_bitwise_or(b.backend(), number<B, false>::canonical_value(a));
    return static_cast<number<B, false>&&>(b);
 }
 //
@@ -560,18 +534,16 @@
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator ^ (number<B, false>&& a, const V& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    using default_ops::eval_bitwise_xor;
- eval_bitwise_xor(a.backend(), static_cast<canonical_type>(b));
+ eval_bitwise_xor(a.backend(), number<B, false>::canonical_value(b));
    return static_cast<number<B, false>&&>(a);
 }
 template <class V, class B>
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator ^ (const V& a, number<B, false>&& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    using default_ops::eval_bitwise_xor;
- eval_bitwise_xor(b.backend(), static_cast<canonical_type>(a));
+ eval_bitwise_xor(b.backend(), number<B, false>::canonical_value(a));
    return static_cast<number<B, false>&&>(b);
 }
 //
@@ -602,18 +574,16 @@
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator & (number<B, false>&& a, const V& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    using default_ops::eval_bitwise_and;
- eval_bitwise_and(a.backend(), static_cast<canonical_type>(b));
+ eval_bitwise_and(a.backend(), number<B, false>::canonical_value(b));
    return static_cast<number<B, false>&&>(a);
 }
 template <class V, class B>
 inline typename enable_if<is_compatible_arithmetic_type<V, number<B, false> >, number<B, false> >::type
    operator & (const V& a, number<B, false>&& b)
 {
- typedef typename detail::canonical<V, B>::type canonical_type;
    using default_ops::eval_bitwise_and;
- eval_bitwise_and(b.backend(), static_cast<canonical_type>(a));
+ eval_bitwise_and(b.backend(), number<B, false>::canonical_value(a));
    return static_cast<number<B, false>&&>(b);
 }
 //

Modified: sandbox/big_number/boost/multiprecision/detail/number_base.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/detail/number_base.hpp (original)
+++ sandbox/big_number/boost/multiprecision/detail/number_base.hpp 2012-09-04 04:20:26 EDT (Tue, 04 Sep 2012)
@@ -41,7 +41,7 @@
 struct is_compatible_arithmetic_type
    : public mpl::bool_<
          is_convertible<T, Num>::value
- && !is_number<T>::value
+ && !is_same<T, Num>::value
          && !is_number_expression<T>::value>
 {};
 
@@ -221,6 +221,16 @@
    typedef number<T, ExpressionTemplates> type;
 };
 
+template <class T1, bool ExpressionTemplates1, class T2, bool ExpressionTemplates2>
+struct combine_expression<number<T1, ExpressionTemplates1>, number<T2, ExpressionTemplates2> >
+{
+ typedef typename mpl::if_c<
+ is_convertible<number<T2, ExpressionTemplates2>, number<T1, ExpressionTemplates2> >::value,
+ number<T1, ExpressionTemplates1>,
+ number<T2, ExpressionTemplates2>
+ >::type type;
+};
+
 template <class T>
 struct arg_type
 {
@@ -620,638 +630,6 @@
 } // namespace detail
 
 //
-// Non-member operators for number:
-//
-// Unary operators first:
-//
-template <class B, bool ExpressionTemplates>
-inline const number<B, ExpressionTemplates>& operator + (const number<B, ExpressionTemplates>& v) { return v; }
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& operator + (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return v; }
-template <class B>
-inline detail::expression<detail::negate, number<B, true> > operator - (const number<B, true>& v) { return detail::expression<detail::negate, number<B, true> >(v); }
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::negate, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > operator - (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return detail::expression<detail::negate, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(v); }
-template <class B>
-inline detail::expression<detail::complement_immediates, number<B, true> > operator ~ (const number<B, true>& v) { return detail::expression<detail::complement_immediates, number<B, true> >(v); }
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::bitwise_complement, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > operator ~ (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return detail::expression<detail::bitwise_complement, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(v); }
-//
-// Then addition:
-//
-template <class B>
-inline detail::expression<detail::add_immediates, number<B, true>, number<B, true> >
- operator + (const number<B, true>& a, const number<B, true>& b)
-{
- return detail::expression<detail::add_immediates, number<B, true>, number<B, true> >(a, b);
-}
-template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::add_immediates, number<B, true>, V > >::type
- operator + (const number<B, true>& a, const V& b)
-{
- return detail::expression<detail::add_immediates, number<B, true>, V >(a, b);
-}
-template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::add_immediates, V, number<B, true> > >::type
- operator + (const V& a, const number<B, true>& b)
-{
- return detail::expression<detail::add_immediates, V, number<B, true> >(a, b);
-}
-template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::plus, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
- operator + (const number<B, true>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::plus, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
-inline detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >
- operator + (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, true>& b)
-{
- return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
-inline detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
- operator + (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
-{
- return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
- operator + (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
-{
- return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
-}
-template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::plus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator + (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::plus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
-}
-//
-// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
-//
-template <class B, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::minus, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >
- operator + (const number<B, true>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::minus, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(a, b.left_ref());
-}
-template <class Arg1, class Arg2, class Arg3, class Arg4, class B>
-inline detail::expression<detail::minus, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >
- operator + (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, true>& b)
-{
- return detail::expression<detail::minus, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(b, a.left_ref());
-}
-template <class B>
-inline detail::expression<detail::subtract_immediates, number<B, true>, number<B, true> >
- operator + (const number<B, true>& a, const detail::expression<detail::negate, number<B, true> >& b)
-{
- return detail::expression<detail::subtract_immediates, number<B, true>, number<B, true> >(a, b.left_ref());
-}
-template <class B>
-inline detail::expression<detail::subtract_immediates, number<B, true>, number<B, true> >
- operator + (const detail::expression<detail::negate, number<B, true> >& a, const number<B, true>& b)
-{
- return detail::expression<detail::subtract_immediates, number<B, true>, number<B, true> >(b, a.left_ref());
-}
-template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::subtract_immediates, V, number<B, true> > >::type
- operator + (const detail::expression<detail::negate, number<B, true> >& a, const V& b)
-{
- return detail::expression<detail::subtract_immediates, V, number<B, true> >(b, a.left_ref());
-}
-template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::subtract_immediates, V, number<B, true> > >::type
- operator + (const V& a, const detail::expression<detail::negate, number<B, true> >& b)
-{
- return detail::expression<detail::subtract_immediates, V, number<B, true> >(a, b.left_ref());
-}
-template <class B>
-inline detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, true>, number<B, true> > >
- operator + (const detail::expression<detail::negate, number<B, true> >& a, const detail::expression<detail::negate, number<B, true> >& b)
-{
- return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, true>, number<B, true> > >(detail::expression<detail::add_immediates, number<B, true>, number<B, true> >(a.left_ref(), b.left_ref()));
-}
-//
-// Subtraction:
-//
-template <class B>
-inline detail::expression<detail::subtract_immediates, number<B, true>, number<B, true> >
- operator - (const number<B, true>& a, const number<B, true>& b)
-{
- return detail::expression<detail::subtract_immediates, number<B, true>, number<B, true> >(a, b);
-}
-template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::subtract_immediates, number<B, true>, V > >::type
- operator - (const number<B, true>& a, const V& b)
-{
- return detail::expression<detail::subtract_immediates, number<B, true>, V >(a, b);
-}
-template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::subtract_immediates, V, number<B, true> > >::type
- operator - (const V& a, const number<B, true>& b)
-{
- return detail::expression<detail::subtract_immediates, V, number<B, true> >(a, b);
-}
-template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::minus, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
- operator - (const number<B, true>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::minus, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
-inline detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >
- operator - (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, true>& b)
-{
- return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
-inline detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
- operator - (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
-{
- return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
- operator - (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
-{
- return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
-}
-template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::minus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator - (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::minus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
-}
-//
-// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
-//
-template <class B, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::plus, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >
- operator - (const number<B, true>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::plus, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(a, b.left_ref());
-}
-template <class Arg1, class Arg2, class Arg3, class Arg4, class B>
-inline detail::expression<detail::negate, detail::expression<detail::plus, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >
- operator - (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, true>& b)
-{
- return detail::expression<detail::negate, detail::expression<detail::plus, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >(
- detail::expression<detail::plus, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(b, a.left_ref()));
-}
-template <class B>
-inline detail::expression<detail::add_immediates, number<B, true>, number<B, true> >
- operator - (const number<B, true>& a, const detail::expression<detail::negate, number<B, true> >& b)
-{
- return detail::expression<detail::add_immediates, number<B, true>, number<B, true> >(a, b.left_ref());
-}
-template <class B>
-inline detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, true>, number<B, true> > >
- operator - (const detail::expression<detail::negate, number<B, true> >& a, const number<B, true>& b)
-{
- return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, true>, number<B, true> > >(
- detail::expression<detail::add_immediates, number<B, true>, number<B, true> >(b, a.left_ref()));
-}
-template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, true>, V > > >::type
- operator - (const detail::expression<detail::negate, number<B, true> >& a, const V& b)
-{
- return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, true>, V > >(detail::expression<detail::add_immediates, number<B, true>, V >(a.left_ref(), b));
-}
-template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::add_immediates, V, number<B, true> > >::type
- operator - (const V& a, const detail::expression<detail::negate, number<B, true> >& b)
-{
- return detail::expression<detail::add_immediates, V, number<B, true> >(a, b.left_ref());
-}
-//
-// Multiplication:
-//
-template <class B>
-inline detail::expression<detail::multiply_immediates, number<B, true>, number<B, true> >
- operator * (const number<B, true>& a, const number<B, true>& b)
-{
- return detail::expression<detail::multiply_immediates, number<B, true>, number<B, true> >(a, b);
-}
-template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::multiply_immediates, number<B, true>, V > >::type
- operator * (const number<B, true>& a, const V& b)
-{
- return detail::expression<detail::multiply_immediates, number<B, true>, V >(a, b);
-}
-template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::multiply_immediates, V, number<B, true> > >::type
- operator * (const V& a, const number<B, true>& b)
-{
- return detail::expression<detail::multiply_immediates, V, number<B, true> >(a, b);
-}
-template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::multiplies, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
- operator * (const number<B, true>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::multiplies, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
-inline detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >
- operator * (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, true>& b)
-{
- return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
-inline detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
- operator * (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
-{
- return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
- operator * (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
-{
- return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
-}
-template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::multiplies, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator * (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::multiplies, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
-}
-//
-// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
-//
-template <class B, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >
- operator * (const number<B, true>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >(
- detail::expression<detail::multiplies, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > (a, b.left_ref()));
-}
-template <class Arg1, class Arg2, class Arg3, class Arg4, class B>
-inline detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >
- operator * (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, true>& b)
-{
- return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >(
- detail::expression<detail::multiplies, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(b, a.left_ref()));
-}
-template <class B>
-inline detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, number<B, true> > >
- operator * (const number<B, true>& a, const detail::expression<detail::negate, number<B, true> >& b)
-{
- return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, number<B, true> > >(
- detail::expression<detail::multiply_immediates, number<B, true>, number<B, true> >(a, b.left_ref()));
-}
-template <class B>
-inline detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, number<B, true> > >
- operator * (const detail::expression<detail::negate, number<B, true> >& a, const number<B, true>& b)
-{
- return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, number<B, true> > >(
- detail::expression<detail::multiply_immediates, number<B, true>, number<B, true> >(b, a.left_ref()));
-}
-template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, V > > >::type
- operator * (const detail::expression<detail::negate, number<B, true> >& a, const V& b)
-{
- return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, V > > (
- detail::expression<detail::multiply_immediates, number<B, true>, V >(a.left_ref(), b));
-}
-template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, V > > >::type
- operator * (const V& a, const detail::expression<detail::negate, number<B, true> >& b)
-{
- return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, true>, V > >(
- detail::expression<detail::multiply_immediates, number<B, true>, V >(b.left_ref(), a));
-}
-//
-// Division:
-//
-template <class B>
-inline detail::expression<detail::divide_immediates, number<B, true>, number<B, true> >
- operator / (const number<B, true>& a, const number<B, true>& b)
-{
- return detail::expression<detail::divide_immediates, number<B, true>, number<B, true> >(a, b);
-}
-template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::divide_immediates, number<B, true>, V > >::type
- operator / (const number<B, true>& a, const V& b)
-{
- return detail::expression<detail::divide_immediates, number<B, true>, V >(a, b);
-}
-template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::divide_immediates, V, number<B, true> > >::type
- operator / (const V& a, const number<B, true>& b)
-{
- return detail::expression<detail::divide_immediates, V, number<B, true> >(a, b);
-}
-template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::divides, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
- operator / (const number<B, true>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::divides, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
-inline detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >
- operator / (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, true>& b)
-{
- return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
-inline detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
- operator / (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
-{
- return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
- operator / (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
-{
- return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
-}
-template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::divides, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator / (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::divides, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
-}
-//
-// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
-//
-template <class B, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::negate, detail::expression<detail::divides, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >
- operator / (const number<B, true>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::negate, detail::expression<detail::divides, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type > >(
- detail::expression<detail::divides, number<B, true>, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type >(a, b.left_ref()));
-}
-template <class Arg1, class Arg2, class Arg3, class Arg4, class B>
-inline detail::expression<detail::negate, detail::expression<detail::divides, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type, number<B, true> > >
- operator / (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, true>& b)
-{
- return detail::expression<detail::negate, detail::expression<detail::divides, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type, number<B, true> > >(
- detail::expression<detail::divides, typename detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>::left_type, number<B, true> >(a.left_ref(), b));
-}
-template <class B>
-inline detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, true>, number<B, true> > >
- operator / (const number<B, true>& a, const detail::expression<detail::negate, number<B, true> >& b)
-{
- return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, true>, number<B, true> > >(
- detail::expression<detail::divide_immediates, number<B, true>, number<B, true> >(a, b.left_ref()));
-}
-template <class B>
-inline detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, true>, number<B, true> > >
- operator / (const detail::expression<detail::negate, number<B, true> >& a, const number<B, true>& b)
-{
- return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, true>, number<B, true> > >(
- detail::expression<detail::divide_immediates, number<B, true>, number<B, true> >(a.left_ref(), b));
-}
-template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, true>, V > > >::type
- operator / (const detail::expression<detail::negate, number<B, true> >& a, const V& b)
-{
- return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, true>, V > >(
- detail::expression<detail::divide_immediates, number<B, true>, V>(a.left_ref(), b));
-}
-template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::negate, detail::expression<detail::divide_immediates, V, number<B, true> > > >::type
- operator / (const V& a, const detail::expression<detail::negate, number<B, true> >& b)
-{
- return detail::expression<detail::negate, detail::expression<detail::divide_immediates, V, number<B, true> > >(
- detail::expression<detail::divide_immediates, V, number<B, true> >(a, b.left_ref()));
-}
-//
-// Modulus:
-//
-template <class B>
-inline detail::expression<detail::modulus_immediates, number<B, true>, number<B, true> >
- operator % (const number<B, true>& a, const number<B, true>& b)
-{
- return detail::expression<detail::modulus_immediates, number<B, true>, number<B, true> >(a, b);
-}
-template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::modulus_immediates, number<B, true>, V > >::type
- operator % (const number<B, true>& a, const V& b)
-{
- return detail::expression<detail::modulus_immediates, number<B, true>, V >(a, b);
-}
-template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::modulus_immediates, V, number<B, true> > >::type
- operator % (const V& a, const number<B, true>& b)
-{
- return detail::expression<detail::modulus_immediates, V, number<B, true> >(a, b);
-}
-template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::modulus, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
- operator % (const number<B, true>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::modulus, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
-inline detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >
- operator % (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, true>& b)
-{
- return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
-inline detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
- operator % (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
-{
- return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
- operator % (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
-{
- return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
-}
-template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::modulus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator % (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::modulus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
-}
-//
-// Left shift:
-//
-template <class B, class I>
-inline typename enable_if<is_integral<I>, detail::expression<detail::shift_left, number<B, true>, I > >::type
- operator << (const number<B, true>& a, const I& b)
-{
- return detail::expression<detail::shift_left, number<B, true>, I>(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
-inline typename enable_if<is_integral<I>, detail::expression<detail::shift_left, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
- operator << (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
-{
- return detail::expression<detail::shift_left, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I>(a, b);
-}
-//
-// Right shift:
-//
-template <class B, class I>
-inline typename enable_if<is_integral<I>, detail::expression<detail::shift_right, number<B, true>, I > >::type
- operator >> (const number<B, true>& a, const I& b)
-{
- return detail::expression<detail::shift_right, number<B, true>, I>(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
-inline typename enable_if<is_integral<I>, detail::expression<detail::shift_right, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
- operator >> (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
-{
- return detail::expression<detail::shift_right, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I>(a, b);
-}
-//
-// Bitwise AND:
-//
-template <class B>
-inline detail::expression<detail::bitwise_and_immediates, number<B, true>, number<B, true> >
- operator & (const number<B, true>& a, const number<B, true>& b)
-{
- return detail::expression<detail::bitwise_and_immediates, number<B, true>, number<B, true> >(a, b);
-}
-template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::bitwise_and_immediates, number<B, true>, V > >::type
- operator & (const number<B, true>& a, const V& b)
-{
- return detail::expression<detail::bitwise_and_immediates, number<B, true>, V >(a, b);
-}
-template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::bitwise_and_immediates, V, number<B, true> > >::type
- operator & (const V& a, const number<B, true>& b)
-{
- return detail::expression<detail::bitwise_and_immediates, V, number<B, true> >(a, b);
-}
-template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::bitwise_and, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
- operator & (const number<B, true>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::bitwise_and, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
-inline detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >
- operator & (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, true>& b)
-{
- return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
-inline detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
- operator & (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
-{
- return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
- operator & (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
-{
- return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
-}
-template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::bitwise_and, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator & (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::bitwise_and, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
-}
-//
-// Bitwise OR:
-//
-template <class B>
-inline detail::expression<detail::bitwise_or_immediates, number<B, true>, number<B, true> >
- operator| (const number<B, true>& a, const number<B, true>& b)
-{
- return detail::expression<detail::bitwise_or_immediates, number<B, true>, number<B, true> >(a, b);
-}
-template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::bitwise_or_immediates, number<B, true>, V > >::type
- operator| (const number<B, true>& a, const V& b)
-{
- return detail::expression<detail::bitwise_or_immediates, number<B, true>, V >(a, b);
-}
-template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::bitwise_or_immediates, V, number<B, true> > >::type
- operator| (const V& a, const number<B, true>& b)
-{
- return detail::expression<detail::bitwise_or_immediates, V, number<B, true> >(a, b);
-}
-template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::bitwise_or, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
- operator| (const number<B, true>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::bitwise_or, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
-inline detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >
- operator| (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, true>& b)
-{
- return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
-inline detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
- operator| (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
-{
- return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
- operator| (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
-{
- return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
-}
-template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::bitwise_or, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator| (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::bitwise_or, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
-}
-//
-// Bitwise XOR:
-//
-template <class B>
-inline detail::expression<detail::bitwise_xor_immediates, number<B, true>, number<B, true> >
- operator^ (const number<B, true>& a, const number<B, true>& b)
-{
- return detail::expression<detail::bitwise_xor_immediates, number<B, true>, number<B, true> >(a, b);
-}
-template <class B, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::bitwise_xor_immediates, number<B, true>, V > >::type
- operator^ (const number<B, true>& a, const V& b)
-{
- return detail::expression<detail::bitwise_xor_immediates, number<B, true>, V >(a, b);
-}
-template <class V, class B>
-inline typename enable_if<is_compatible_arithmetic_type<V, number<B, true> >, detail::expression<detail::bitwise_xor_immediates, V, number<B, true> > >::type
- operator^ (const V& a, const number<B, true>& b)
-{
- return detail::expression<detail::bitwise_xor_immediates, V, number<B, true> >(a, b);
-}
-template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline detail::expression<detail::bitwise_xor, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
- operator^ (const number<B, true>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::bitwise_xor, number<B, true>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
-inline detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >
- operator^ (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, true>& b)
-{
- return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, true> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
-inline detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
- operator^ (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
-{
- return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
-}
-template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
- operator^ (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
-{
- return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
-}
-template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
-inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::bitwise_xor, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
- operator^ (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
-{
- return detail::expression<detail::bitwise_xor, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
-}
-
-//
 // Traits class, lets us know what kind of number we have, defaults to a floating point type:
 //
 enum number_category_type

Modified: sandbox/big_number/boost/multiprecision/detail/number_compare.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/detail/number_compare.hpp (original)
+++ sandbox/big_number/boost/multiprecision/detail/number_compare.hpp 2012-09-04 04:20:26 EDT (Tue, 04 Sep 2012)
@@ -19,14 +19,21 @@
 {
    return a.compare(b) == 0;
 }
+//
+// For the default version which compares to some arbitrary type convertible to
+// our number type, we don't know what value the ExpressionTemplates parameter to
+// class number should be. We generally prefer ExpressionTemplates to be enabled
+// in case type A is itself an expression template, but we need to test both options
+// with is_convertible in case A has an implicit conversion operator to number<B,something>.
+// This is the case with many uBlas types for example.
+//
 template <class B, class A>
 inline bool eval_eq(const B& a, const A& b)
 {
- typedef typename mpl::if_<
- is_convertible<A, number<B, false> >,
- number<B, false>,
- number<B, true>
- >::type mp_type;
+ typedef typename mpl::if_c<
+ is_convertible<A, number<B, true> >::value,
+ number<B, true>,
+ number<B, false> >::type mp_type;
    mp_type t(b);
    return eval_eq(a, t.backend());
 }
@@ -39,11 +46,10 @@
 template <class B, class A>
 inline bool eval_lt(const B& a, const A& b)
 {
- typedef typename mpl::if_<
- is_convertible<A, number<B, false> >,
- number<B, false>,
- number<B, true>
- >::type mp_type;
+ typedef typename mpl::if_c<
+ is_convertible<A, number<B, true> >::value,
+ number<B, true>,
+ number<B, false> >::type mp_type;
    mp_type t(b);
    return eval_lt(a, t.backend());
 }
@@ -56,15 +62,38 @@
 template <class B, class A>
 inline bool eval_gt(const B& a, const A& b)
 {
- typedef typename mpl::if_<
- is_convertible<A, number<B, false> >,
- number<B, false>,
- number<B, true>
- >::type mp_type;
+ typedef typename mpl::if_c<
+ is_convertible<A, number<B, true> >::value,
+ number<B, true>,
+ number<B, false> >::type mp_type;
    mp_type t(b);
    return eval_gt(a, t.backend());
 }
 
+} // namespace default_ops
+
+namespace detail{
+
+template <class Num, class Val>
+struct is_valid_mixed_compare : public mpl::false_ {};
+
+template <class B, bool ET, class Val>
+struct is_valid_mixed_compare<number<B, ET>, Val> : public is_convertible<Val, number<B, ET>> {};
+/*
+template <class Val, class B, bool ET>
+struct is_valid_mixed_compare<Val, number<B, ET> > : public is_convertible<Val, number<B, ET>> {};
+*/
+template <class B, bool ET>
+struct is_valid_mixed_compare<number<B, ET>, number<B, ET> > : public mpl::false_ {};
+
+template <class B, bool ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+struct is_valid_mixed_compare<number<B, ET>, expression<tag, Arg1, Arg2, Arg3, Arg4> >
+ : public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value> {};
+
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, bool ET>
+struct is_valid_mixed_compare<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
+ : public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value> {};
+
 }
 
 template <class Backend, bool ExpressionTemplates>
@@ -74,13 +103,13 @@
    return eval_eq(a.backend(), b.backend());
 }
 template <class Backend, bool ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<(is_convertible<Arithmetic, number<Backend, ExpressionTemplates> >::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
    operator == (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
 {
- typedef typename detail::canonical<Arithmetic, Backend>::type ct;
    using default_ops::eval_eq;
- return eval_eq(a.backend(), ct(b));
+ return eval_eq(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
 }
+/*
 template <class Backend, bool ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
 inline typename enable_if<is_same<number<Backend, ExpressionTemplates>, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>, bool>::type
    operator == (const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
@@ -89,24 +118,24 @@
    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(b);
    return eval_eq(a.backend(), t.backend());
 }
+*/
 template <class Arithmetic, class Backend, bool ExpressionTemplates>
-inline typename enable_if_c<(is_convertible<Arithmetic, number<Backend, ExpressionTemplates> >::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
    operator == (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
 {
- typedef typename detail::canonical<Arithmetic, Backend>::type ct;
    using default_ops::eval_eq;
- return eval_eq(b.backend(), ct(a));
+ return eval_eq(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
 }
 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<(is_convertible<Arithmetic, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
    operator == (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
 {
    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
- typedef typename detail::canonical<Arithmetic, typename result_type::backend_type>::type ct;
    using default_ops::eval_eq;
    result_type t(b);
- return eval_eq(t.backend(), ct(a));
+ return eval_eq(t.backend(), result_type::canonical_value(a));
 }
+/*
 template <class Tag, class A1, class A2, class A3, class A4, class Backend, bool ExpressionTemplates>
 inline typename enable_if<is_same<number<Backend, ExpressionTemplates>, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>, bool>::type
    operator == (const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
@@ -114,16 +143,15 @@
    using default_ops::eval_eq;
    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
    return eval_eq(t.backend(), b.backend());
-}
+}*/
 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<(is_convertible<Arithmetic, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
    operator == (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
 {
    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
- typedef typename detail::canonical<Arithmetic, typename result_type::backend_type>::type ct;
    using default_ops::eval_eq;
    result_type t(a);
- return eval_eq(t.backend(), ct(b));
+ return eval_eq(t.backend(), result_type::canonical_value(b));
 }
 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
@@ -142,13 +170,13 @@
    return !eval_eq(a.backend(), b.backend());
 }
 template <class Backend, bool ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<(is_convertible<Arithmetic, number<Backend, ExpressionTemplates> >::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
    operator != (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
 {
- typedef typename detail::canonical<Arithmetic, Backend>::type ct;
    using default_ops::eval_eq;
- return !eval_eq(a.backend(), ct(b));
+ return !eval_eq(a.backend(), number<Backend>::canonical_value(b));
 }
+/*
 template <class Backend, bool ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
 inline typename enable_if<is_same<number<Backend, ExpressionTemplates>, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>, bool>::type
    operator != (const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
@@ -157,24 +185,24 @@
    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(b);
    return !eval_eq(a.backend(), t.backend());
 }
+*/
 template <class Arithmetic, class Backend, bool ExpressionTemplates>
-inline typename enable_if_c<(is_convertible<Arithmetic, number<Backend, ExpressionTemplates> >::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
    operator != (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
 {
- typedef typename detail::canonical<Arithmetic, Backend>::type ct;
    using default_ops::eval_eq;
- return !eval_eq(b.backend(), ct(a));
+ return !eval_eq(b.backend(), number<Backend>::canonical_value(a));
 }
 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<(is_convertible<Arithmetic, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
    operator != (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
 {
    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
- typedef typename detail::canonical<Arithmetic, typename result_type::backend_type>::type ct;
    using default_ops::eval_eq;
    result_type t(b);
- return !eval_eq(t.backend(), ct(a));
+ return !eval_eq(t.backend(), result_type::canonical_value(a));
 }
+/*
 template <class Tag, class A1, class A2, class A3, class A4, class Backend, bool ExpressionTemplates>
 inline typename enable_if<is_same<number<Backend, ExpressionTemplates>, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>, bool>::type
    operator != (const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
@@ -182,16 +210,15 @@
    using default_ops::eval_eq;
    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
    return !eval_eq(t.backend(), b.backend());
-}
+}*/
 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<(is_convertible<Arithmetic, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
    operator != (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
 {
    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
- typedef typename detail::canonical<Arithmetic, typename result_type::backend_type>::type ct;
    using default_ops::eval_eq;
    result_type t(a);
- return !eval_eq(t.backend(), ct(b));
+ return !eval_eq(t.backend(), result_type::canonical_value(b));
 }
 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
@@ -210,13 +237,13 @@
    return eval_lt(a.backend(), b.backend());
 }
 template <class Backend, bool ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<(is_convertible<Arithmetic, number<Backend, ExpressionTemplates> >::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
    operator < (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
 {
- typedef typename detail::canonical<Arithmetic, Backend>::type ct;
    using default_ops::eval_lt;
- return eval_lt(a.backend(), ct(b));
+ return eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
 }
+/*
 template <class Backend, bool ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
 inline typename enable_if<is_same<number<Backend, ExpressionTemplates>, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>, bool>::type
    operator < (const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
@@ -225,24 +252,24 @@
    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(b);
    return eval_lt(a.backend(), t.backend());
 }
+*/
 template <class Arithmetic, class Backend, bool ExpressionTemplates>
-inline typename enable_if_c<(is_convertible<Arithmetic, number<Backend, ExpressionTemplates> >::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
    operator < (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
 {
- typedef typename detail::canonical<Arithmetic, Backend>::type ct;
    using default_ops::eval_gt;
- return eval_gt(b.backend(), ct(a));
+ return eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
 }
 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<(is_convertible<Arithmetic, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
    operator < (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
 {
    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
- typedef typename detail::canonical<Arithmetic, typename result_type::backend_type>::type ct;
    using default_ops::eval_gt;
    result_type t(b);
- return eval_gt(t.backend(), ct(a));
+ return eval_gt(t.backend(), result_type::canonical_value(a));
 }
+/*
 template <class Tag, class A1, class A2, class A3, class A4, class Backend, bool ExpressionTemplates>
 inline typename enable_if<is_same<number<Backend, ExpressionTemplates>, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>, bool>::type
    operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
@@ -251,15 +278,15 @@
    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
    return eval_lt(t.backend(), b.backend());
 }
+*/
 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<(is_convertible<Arithmetic, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
    operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
 {
    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
- typedef typename detail::canonical<Arithmetic, typename result_type::backend_type>::type ct;
    using default_ops::eval_lt;
    result_type t(a);
- return eval_lt(t.backend(), ct(b));
+ return eval_lt(t.backend(), result_type::canonical_value(b));
 }
 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
@@ -278,13 +305,13 @@
    return eval_gt(a.backend(), b.backend());
 }
 template <class Backend, bool ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<(is_convertible<Arithmetic, number<Backend, ExpressionTemplates> >::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
    operator > (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
 {
- typedef typename detail::canonical<Arithmetic, Backend>::type ct;
    using default_ops::eval_gt;
- return eval_gt(a.backend(), ct(b));
+ return eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
 }
+/*
 template <class Backend, bool ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
 inline typename enable_if<is_same<number<Backend, ExpressionTemplates>, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>, bool>::type
    operator > (const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
@@ -293,24 +320,24 @@
    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(b);
    return eval_gt(a.backend(), t.backend());
 }
+*/
 template <class Arithmetic, class Backend, bool ExpressionTemplates>
-inline typename enable_if_c<(is_convertible<Arithmetic, number<Backend, ExpressionTemplates> >::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
    operator > (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
 {
- typedef typename detail::canonical<Arithmetic, Backend>::type ct;
    using default_ops::eval_lt;
- return eval_lt(b.backend(), ct(a));
+ return eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
 }
 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<(is_convertible<Arithmetic, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
    operator > (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
 {
    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
- typedef typename detail::canonical<Arithmetic, typename result_type::backend_type>::type ct;
    using default_ops::eval_lt;
    result_type t(b);
- return eval_lt(t.backend(), ct(a));
+ return eval_lt(t.backend(), result_type::canonical_value(a));
 }
+/*
 template <class Tag, class A1, class A2, class A3, class A4, class Backend, bool ExpressionTemplates>
 inline typename enable_if<is_same<number<Backend, ExpressionTemplates>, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>, bool>::type
    operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
@@ -319,15 +346,15 @@
    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
    return eval_gt(t.backend(), b.backend());
 }
+*/
 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<(is_convertible<Arithmetic, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
    operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
 {
    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
- typedef typename detail::canonical<Arithmetic, typename result_type::backend_type>::type ct;
    using default_ops::eval_gt;
    result_type t(a);
- return eval_gt(t.backend(), ct(b));
+ return eval_gt(t.backend(), result_type::canonical_value(b));
 }
 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
@@ -346,13 +373,13 @@
    return !eval_gt(a.backend(), b.backend());
 }
 template <class Backend, bool ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<(is_convertible<Arithmetic, number<Backend, ExpressionTemplates> >::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
    operator <= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
 {
- typedef typename detail::canonical<Arithmetic, Backend>::type ct;
    using default_ops::eval_gt;
- return !eval_gt(a.backend(), ct(b));
+ return !eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
 }
+/*
 template <class Backend, bool ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
 inline typename enable_if<is_same<number<Backend, ExpressionTemplates>, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>, bool>::type
    operator <= (const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
@@ -361,24 +388,24 @@
    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(b);
    return !eval_gt(a.backend(), t.backend());
 }
+*/
 template <class Arithmetic, class Backend, bool ExpressionTemplates>
-inline typename enable_if_c<(is_convertible<Arithmetic, number<Backend, ExpressionTemplates> >::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
    operator <= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
 {
- typedef typename detail::canonical<Arithmetic, Backend>::type ct;
    using default_ops::eval_lt;
- return !eval_lt(b.backend(), ct(a));
+ return !eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
 }
 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<(is_convertible<Arithmetic, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
    operator <= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
 {
    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
- typedef typename detail::canonical<Arithmetic, typename result_type::backend_type>::type ct;
    using default_ops::eval_lt;
    result_type t(b);
- return !eval_lt(t.backend(), ct(a));
+ return !eval_lt(t.backend(), result_type::canonical_value(a));
 }
+/*
 template <class Tag, class A1, class A2, class A3, class A4, class Backend, bool ExpressionTemplates>
 inline typename enable_if<is_same<number<Backend, ExpressionTemplates>, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>, bool>::type
    operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
@@ -387,15 +414,15 @@
    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
    return !eval_gt(t.backend(), b.backend());
 }
+*/
 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<(is_convertible<Arithmetic, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
    operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
 {
    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
- typedef typename detail::canonical<Arithmetic, typename result_type::backend_type>::type ct;
    using default_ops::eval_gt;
    result_type t(a);
- return !eval_gt(t.backend(), ct(b));
+ return !eval_gt(t.backend(), result_type::canonical_value(b));
 }
 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
@@ -414,13 +441,13 @@
    return !eval_lt(a.backend(), b.backend());
 }
 template <class Backend, bool ExpressionTemplates, class Arithmetic>
-inline typename enable_if_c<(is_convertible<Arithmetic, number<Backend, ExpressionTemplates> >::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
    operator >= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
 {
- typedef typename detail::canonical<Arithmetic, Backend>::type ct;
    using default_ops::eval_lt;
- return !eval_lt(a.backend(), ct(b));
+ return !eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
 }
+/*
 template <class Backend, bool ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
 inline typename enable_if<is_same<number<Backend, ExpressionTemplates>, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>, bool>::type
    operator >= (const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
@@ -429,24 +456,24 @@
    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(b);
    return !eval_lt(a.backend(), t.backend());
 }
+*/
 template <class Arithmetic, class Backend, bool ExpressionTemplates>
-inline typename enable_if_c<(is_convertible<Arithmetic, number<Backend, ExpressionTemplates> >::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
    operator >= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
 {
- typedef typename detail::canonical<Arithmetic, Backend>::type ct;
    using default_ops::eval_gt;
- return !eval_gt(b.backend(), ct(a));
+ return !eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
 }
 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
-inline typename enable_if_c<(is_convertible<Arithmetic, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
    operator >= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
 {
    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
- typedef typename detail::canonical<Arithmetic, typename result_type::backend_type>::type ct;
    using default_ops::eval_gt;
    result_type t(b);
- return !eval_gt(t.backend(), ct(a));
+ return !eval_gt(t.backend(), result_type::canonical_value(a));
 }
+/*
 template <class Tag, class A1, class A2, class A3, class A4, class Backend, bool ExpressionTemplates>
 inline typename enable_if<is_same<number<Backend, ExpressionTemplates>, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>, bool>::type
    operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
@@ -455,15 +482,15 @@
    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
    return !eval_lt(t.backend(), b.backend());
 }
+*/
 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
-inline typename enable_if_c<(is_convertible<Arithmetic, typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value && !is_number_expression<Arithmetic>::value && !is_number<Arithmetic>::value), bool>::type
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
    operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
 {
    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
- typedef typename detail::canonical<Arithmetic, typename result_type::backend_type>::type ct;
    using default_ops::eval_lt;
    result_type t(a);
- return !eval_lt(t.backend(), ct(b));
+ return !eval_lt(t.backend(), result_type::canonical_value(b));
 }
 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type

Modified: sandbox/big_number/boost/multiprecision/gmp.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/gmp.hpp (original)
+++ sandbox/big_number/boost/multiprecision/gmp.hpp 2012-09-04 04:20:26 EDT (Tue, 04 Sep 2012)
@@ -331,7 +331,7 @@
       return mpf_cmp_ui(m_data, i);
    }
    template <class V>
- int compare(V v)const
+ typename enable_if<is_arithmetic<V>, int>::type compare(V v)const
    {
       gmp_float<digits10> d;
       d = v;
@@ -552,17 +552,17 @@
 };
 
 template <unsigned digits10, class T>
-inline typename disable_if<is_same<gmp_float<digits10>, T>, bool>::type eval_eq(const gmp_float<digits10>& a, const T& b) BOOST_NOEXCEPT
+inline typename enable_if_c<is_arithmetic<T>::value, bool>::type eval_eq(const gmp_float<digits10>& a, const T& b) BOOST_NOEXCEPT
 {
    return a.compare(b) == 0;
 }
 template <unsigned digits10, class T>
-inline typename disable_if<is_same<gmp_float<digits10>, T>, bool>::type eval_lt(const gmp_float<digits10>& a, const T& b) BOOST_NOEXCEPT
+inline typename enable_if_c<is_arithmetic<T>::value, bool>::type eval_lt(const gmp_float<digits10>& a, const T& b) BOOST_NOEXCEPT
 {
    return a.compare(b) < 0;
 }
 template <unsigned digits10, class T>
-inline typename disable_if<is_same<gmp_float<digits10>, T>, bool>::type eval_gt(const gmp_float<digits10>& a, const T& b) BOOST_NOEXCEPT
+inline typename enable_if_c<is_arithmetic<T>::value, bool>::type eval_gt(const gmp_float<digits10>& a, const T& b) BOOST_NOEXCEPT
 {
    return a.compare(b) > 0;
 }
@@ -1265,17 +1265,17 @@
 };
 
 template <class T>
-inline typename disable_if<is_same<gmp_int, T>, bool>::type eval_eq(const gmp_int& a, const T& b)
+inline typename enable_if<is_arithmetic<T>, bool>::type eval_eq(const gmp_int& a, const T& b)
 {
    return a.compare(b) == 0;
 }
 template <class T>
-inline typename disable_if<is_same<gmp_int, T>, bool>::type eval_lt(const gmp_int& a, const T& b)
+inline typename enable_if<is_arithmetic<T>, bool>::type eval_lt(const gmp_int& a, const T& b)
 {
    return a.compare(b) < 0;
 }
 template <class T>
-inline typename disable_if<is_same<gmp_int, T>, bool>::type eval_gt(const gmp_int& a, const T& b)
+inline typename enable_if<is_arithmetic<T>, bool>::type eval_gt(const gmp_int& a, const T& b)
 {
    return a.compare(b) > 0;
 }

Modified: sandbox/big_number/boost/multiprecision/mpfr.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/mpfr.hpp (original)
+++ sandbox/big_number/boost/multiprecision/mpfr.hpp 2012-09-04 04:20:26 EDT (Tue, 04 Sep 2012)
@@ -594,17 +594,17 @@
 };
 
 template <unsigned digits10, class T>
-inline typename disable_if<is_same<mpfr_float_backend<digits10>, T>, bool>::type eval_eq(const mpfr_float_backend<digits10>& a, const T& b) BOOST_NOEXCEPT
+inline typename enable_if<is_arithmetic<T>, bool>::type eval_eq(const mpfr_float_backend<digits10>& a, const T& b) BOOST_NOEXCEPT
 {
    return a.compare(b) == 0;
 }
 template <unsigned digits10, class T>
-inline typename disable_if<is_same<mpfr_float_backend<digits10>, T>, bool>::type eval_lt(const mpfr_float_backend<digits10>& a, const T& b) BOOST_NOEXCEPT
+inline typename enable_if<is_arithmetic<T>, bool>::type eval_lt(const mpfr_float_backend<digits10>& a, const T& b) BOOST_NOEXCEPT
 {
    return a.compare(b) < 0;
 }
 template <unsigned digits10, class T>
-inline typename disable_if<is_same<mpfr_float_backend<digits10>, T>, bool>::type eval_gt(const mpfr_float_backend<digits10>& a, const T& b) BOOST_NOEXCEPT
+inline typename enable_if<is_arithmetic<T>, bool>::type eval_gt(const mpfr_float_backend<digits10>& a, const T& b) BOOST_NOEXCEPT
 {
    return a.compare(b) > 0;
 }

Modified: sandbox/big_number/boost/multiprecision/number.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/number.hpp (original)
+++ sandbox/big_number/boost/multiprecision/number.hpp 2012-09-04 04:20:26 EDT (Tue, 04 Sep 2012)
@@ -161,7 +161,7 @@
       return *this;
    }
    template <class Other>
- typename disable_if<is_convertible<Other, Backend>, number<Backend, ExpressionTemplates>& >::type
+ typename disable_if<boost::multiprecision::detail::is_explicitly_convertible<Other, Backend>, number<Backend, ExpressionTemplates>& >::type
       assign(const number<Other>& v)
    {
       //
@@ -540,12 +540,28 @@
    {
       return m_backend.str(digits, f);
    }
+private:
    template <class T>
- T convert_to()const
+ void convert_to_imp(T* result)const
    {
       using default_ops::eval_convert_to;
+ eval_convert_to(result, m_backend);
+ }
+ template <class B2, bool ET>
+ void convert_to_imp(number<B2, ET>* result)const
+ {
+ result->assign(*this);
+ }
+ void convert_to_imp(std::string* result)const
+ {
+ *result = this->str();
+ }
+public:
+ template <class T>
+ T convert_to()const
+ {
       T result;
- eval_convert_to(&result, m_backend);
+ convert_to_imp(&result);
       return result;
    }
 #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
@@ -1553,6 +1569,20 @@
    BOOST_FORCEINLINE BOOST_CONSTEXPR bool is_realy_self(const Val&)const BOOST_NOEXCEPT{ return false; }
    BOOST_FORCEINLINE BOOST_CONSTEXPR bool is_realy_self(const self_type& v)const BOOST_NOEXCEPT{ return &v == this; }
 
+ static BOOST_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const self_type& v) BOOST_NOEXCEPT { return v.backend(); }
+ template <class V>
+ static BOOST_FORCEINLINE BOOST_CONSTEXPR const V& function_arg_value(const V& v) BOOST_NOEXCEPT { return v; }
+ template <class A1, class A2, class A3, class A4>
+ static BOOST_FORCEINLINE const A1& function_arg_value(const detail::expression<detail::terminal, A1, A2, A3, A4>& exp) BOOST_NOEXCEPT { return exp.value(); }
+ template <class A2, class A3, class A4>
+ static BOOST_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const detail::expression<detail::terminal, number<Backend>, A2, A3, A4>& exp) BOOST_NOEXCEPT { return exp.value().backend(); }
+ Backend m_backend;
+
+public:
+ //
+ // These shouldn't really need to be public, or even member functions, but it makes implementing
+ // the non-member operators way easier if they are:
+ //
    static BOOST_FORCEINLINE BOOST_CONSTEXPR const Backend& canonical_value(const self_type& v) BOOST_NOEXCEPT { return v.m_backend; }
    template <class B2, bool ET>
    static BOOST_FORCEINLINE BOOST_CONSTEXPR const B2& canonical_value(const number<B2, ET>& v) BOOST_NOEXCEPT { return v.backend(); }
@@ -1564,14 +1594,6 @@
       canonical_value(const V& v) BOOST_NOEXCEPT { return v; }
    static BOOST_FORCEINLINE typename detail::canonical<std::string, Backend>::type canonical_value(const std::string& v) BOOST_NOEXCEPT { return v.c_str(); }
 
- static BOOST_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const self_type& v) BOOST_NOEXCEPT { return v.backend(); }
- template <class V>
- static BOOST_FORCEINLINE BOOST_CONSTEXPR const V& function_arg_value(const V& v) BOOST_NOEXCEPT { return v; }
- template <class A1, class A2, class A3, class A4>
- static BOOST_FORCEINLINE const A1& function_arg_value(const detail::expression<detail::terminal, A1, A2, A3, A4>& exp) BOOST_NOEXCEPT { return exp.value(); }
- template <class A2, class A3, class A4>
- static BOOST_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const detail::expression<detail::terminal, number<Backend>, A2, A3, A4>& exp) BOOST_NOEXCEPT { return exp.value().backend(); }
- Backend m_backend;
 };
 
 template <class Backend, bool ExpressionTemplates>

Modified: sandbox/big_number/boost/multiprecision/tommath.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/tommath.hpp (original)
+++ sandbox/big_number/boost/multiprecision/tommath.hpp 2012-09-04 04:20:26 EDT (Tue, 04 Sep 2012)
@@ -32,6 +32,11 @@
 
 }
 
+struct tommath_int;
+
+void eval_multiply(tommath_int& t, const tommath_int& o);
+void eval_add(tommath_int& t, const tommath_int& o);
+
 struct tommath_int
 {
    typedef mpl::list<boost::int32_t, long long> signed_types;
@@ -186,8 +191,6 @@
       //
       // We don't use libtommath's own routine because it doesn't error check the input :-(
       //
- using default_ops::eval_multiply;
- using default_ops::eval_add;
       if(m_data.dp == 0)
          detail::check_tommath_result(mp_init(&m_data));
       std::size_t n = s ? std::strlen(s) : 0;
@@ -279,8 +282,11 @@
                      break;
                   }
                }
- eval_multiply(*this, block_mult);
- eval_add(*this, block);
+ tommath_int t;
+ t = block_mult;
+ eval_multiply(*this, t);
+ t = block;
+ eval_add(*this, t);
             }
          }
       }

Modified: sandbox/big_number/libs/multiprecision/test/test_arithmetic.cpp
==============================================================================
--- sandbox/big_number/libs/multiprecision/test/test_arithmetic.cpp (original)
+++ sandbox/big_number/libs/multiprecision/test/test_arithmetic.cpp 2012-09-04 04:20:26 EDT (Tue, 04 Sep 2012)
@@ -119,15 +119,31 @@
 bool isfloat(long double){ return true; }
 template <class T> bool isfloat(T){ return false; }
 
+namespace detail{
+
+template <class T>
+typename boost::disable_if<boost::is_unsigned<T>, T>::type abs(T v)
+{
+ return v < 0 ? -v : v;
+}
+template <class T>
+typename boost::enable_if<boost::is_unsigned<T>, T>::type abs(T v)
+{
+ return v;
+}
+
+}
+
 #define BOOST_TEST_CLOSE(x, y, tol)\
+ using std::abs; using detail::abs;\
    if(x == 0){\
       BOOST_TEST(y == 0); }\
    else if(!isfloat(x)){\
       BOOST_TEST(x == y); }\
- else if((x != y) && (::fabsl(static_cast<long double>((x-y)/x)) > tol))\
+ else if((x != y) && (abs((x-y)/x) > tol))\
    {\
        BOOST_ERROR("Expected tolerance was exceeded: ");\
- BOOST_LIGHTWEIGHT_TEST_OSTREAM << std::setprecision(34) << "(x-y)/x = " << ::fabsl(static_cast<long double>((x-y)/x)) \
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << std::setprecision(34) << "(x-y)/x = " << abs((x-y)/x) \
        << " tolerance = " << tol << std::endl;\
    }
 
@@ -141,6 +157,58 @@
 
 #define BOOST_TEST_EQUAL(a, b) BOOST_TEST((a) == (b))
 
+
+template <class T>
+struct related_type
+{
+ typedef T type;
+};
+
+#ifdef TEST_MPQ
+template <>
+struct related_type<boost::multiprecision::mpq_rational>
+{
+ typedef boost::multiprecision::mpz_int type;
+};
+#endif
+#if defined(TEST_MPF_50) || defined(TEST_MPF)
+template <unsigned D>
+struct related_type<boost::multiprecision::number< boost::multiprecision::gmp_float<D> > >
+{
+ typedef boost::multiprecision::number< boost::multiprecision::gmp_float<D/2> > type;
+};
+template <>
+struct related_type<boost::multiprecision::mpf_float >
+{
+ typedef boost::multiprecision::mpz_int type;
+};
+#endif
+#ifdef TEST_CPP_DEC_FLOAT
+template <unsigned D>
+struct related_type<boost::multiprecision::number< boost::multiprecision::cpp_dec_float<D> > >
+{
+ typedef boost::multiprecision::number< boost::multiprecision::cpp_dec_float<D/2> > type;
+};
+#endif
+#if defined(TEST_MPFR_50) || defined(TEST_MPFR)
+template <unsigned D>
+struct related_type<boost::multiprecision::number< boost::multiprecision::mpfr_float_backend<D> > >
+{
+ typedef boost::multiprecision::number< boost::multiprecision::mpfr_float_backend<D/2> > type;
+};
+#endif
+#if defined(TEST_CPP_INT_1) || defined(TEST_CPP_INT_2) || defined(TEST_CPP_INT_3) || defined(TEST_CPP_INT_BR)
+template <>
+struct related_type<boost::multiprecision::cpp_int>
+{
+ typedef boost::multiprecision::int256_t type;
+};
+template <unsigned D, bool S, bool ET>
+struct related_type<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<D, S, void>, ET> >
+{
+ typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<D/2, S, void>, ET> type;
+};
+#endif
 template <class Real, class Val>
 void test_comparisons(Val, Val, const boost::mpl::false_)
 {}
@@ -836,7 +904,8 @@
          Real
>::type simple_cast_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));
+ static const int left_shift = std::numeric_limits<Num>::digits - 1;
+ Num n1 = -static_cast<Num>(1uLL << ((left_shift < 63) && (left_shift > 0) ? left_shift : 10));
    Num n2 = -1;
    Num n3 = 0;
    Num n4 = -20;
@@ -1047,11 +1116,12 @@
          Real
>::type simple_cast_type;
    
- if(std::numeric_limits<Real>::digits < std::numeric_limits<Num>::digits)
+ if(std::numeric_limits<Real>::is_specialized && std::numeric_limits<Real>::is_bounded && std::numeric_limits<Real>::digits < std::numeric_limits<Num>::digits)
       return;
 
    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));
+ static const int left_shift = std::numeric_limits<Num>::digits - 1;
+ Num n1 = static_cast<Num>(1uLL << ((left_shift < 63) && (left_shift > 0) ? left_shift : 10));
    Num n2 = 1;
    Num n3 = 0;
    Num n4 = 20;
@@ -1198,6 +1268,12 @@
    test_mixed<Real, float>(tag);
    test_mixed<Real, double>(tag);
    test_mixed<Real, long double>(tag);
+
+ typedef typename related_type<Real>::type related_type;
+ boost::mpl::bool_<boost::multiprecision::is_number<Real>::value && !boost::is_same<related_type, Real>::value> tag2;
+
+ test_mixed<Real, related_type>(tag2);
+
 #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