]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/multiprecision/detail/et_ops.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / multiprecision / detail / et_ops.hpp
CommitLineData
7c673cae
FG
1///////////////////////////////////////////////////////////////////////////////
2// Copyright 2011 John Maddock. Distributed under the Boost
3// Software License, Version 1.0. (See accompanying file
4// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef BOOST_MP_ET_OPS_HPP
7#define BOOST_MP_ET_OPS_HPP
8
92f5a8d4 9namespace boost { namespace multiprecision {
7c673cae
FG
10
11//
1e59de90
TL
12// Non-member operators for number which return expression templates.
13//
14// Note that operators taking rvalue-references DO NOT return expression templates
15// as this can lead to dangling references, see https://github.com/boostorg/multiprecision/issues/175.
7c673cae
FG
16//
17// Unary operators first.
18// Note that these *must* return by value, even though that's somewhat against
19// existing practice. The issue is that in C++11 land one could easily and legitimately
20// write:
21// auto x = +1234_my_user_defined_suffix;
22// which would result in a dangling-reference-to-temporary if unary + returned a reference
23// to it's argument. While return-by-value is obviously inefficient in other situations
24// the reality is that no one ever uses unary operator+ anyway...!
25//
26template <class B, expression_template_option ExpressionTemplates>
1e59de90 27inline constexpr const number<B, ExpressionTemplates> operator+(const number<B, ExpressionTemplates>& v) { return v; }
7c673cae 28template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90 29inline constexpr const detail::expression<tag, Arg1, Arg2, Arg3, Arg4> operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return v; }
7c673cae 30template <class B>
92f5a8d4 31inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, number<B, et_on> > operator-(const number<B, et_on>& v)
7c673cae 32{
1e59de90 33 static_assert(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
7c673cae
FG
34 return detail::expression<detail::negate, number<B, et_on> >(v);
35}
1e59de90 36// rvalue ops:
f67539c2
TL
37template <class B>
38inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on> operator-(number<B, et_on>&& v)
39{
1e59de90
TL
40 static_assert(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
41 v.backend().negate();
42 return std::move(v);
f67539c2 43}
1e59de90 44
7c673cae 45template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
92f5a8d4 46inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v)
7c673cae 47{
1e59de90 48 static_assert((is_signed_number<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value), "Negating an unsigned type results in ill-defined behavior.");
7c673cae
FG
49 return detail::expression<detail::negate, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(v);
50}
51template <class B>
1e59de90 52inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
92f5a8d4
TL
53 detail::expression<detail::complement_immediates, number<B, et_on> > >::type
54operator~(const number<B, et_on>& v) { return detail::expression<detail::complement_immediates, number<B, et_on> >(v); }
1e59de90 55
f67539c2 56template <class B>
1e59de90 57inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
f67539c2 58 number<B, et_on> >::type
1e59de90
TL
59operator~(number<B, et_on>&& v)
60{
61 using default_ops::eval_complement;
62 eval_complement(v.backend(), v.backend());
63 return std::move(v);
64}
65
7c673cae 66template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90 67inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
92f5a8d4
TL
68 detail::expression<detail::bitwise_complement, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
69operator~(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return detail::expression<detail::bitwise_complement, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(v); }
7c673cae
FG
70//
71// Then addition:
72//
73template <class B>
92f5a8d4
TL
74inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >
75operator+(const number<B, et_on>& a, const number<B, et_on>& b)
7c673cae
FG
76{
77 return detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(a, b);
78}
1e59de90 79
f67539c2
TL
80template <class B>
81inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
82operator+(number<B, et_on>&& a, const number<B, et_on>& b)
83{
1e59de90
TL
84 using default_ops::eval_add;
85 eval_add(a.backend(), b.backend());
86 return std::move(a);
f67539c2
TL
87}
88template <class B>
89inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
90operator+(const number<B, et_on>& a, number<B, et_on>&& b)
91{
1e59de90
TL
92 using default_ops::eval_add;
93 eval_add(b.backend(), a.backend());
94 return std::move(b);
f67539c2
TL
95}
96template <class B>
97inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
98operator+(number<B, et_on>&& a, number<B, et_on>&& b)
99{
1e59de90
TL
100 using default_ops::eval_add;
101 eval_add(a.backend(), b.backend());
102 return std::move(a);
f67539c2 103}
1e59de90 104
7c673cae 105template <class B, class V>
1e59de90 106inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, detail::expression<detail::add_immediates, number<B, et_on>, V> >::type
92f5a8d4 107operator+(const number<B, et_on>& a, const V& b)
7c673cae 108{
92f5a8d4 109 return detail::expression<detail::add_immediates, number<B, et_on>, V>(a, b);
7c673cae 110}
1e59de90 111
f67539c2 112template <class B, class V>
1e59de90 113inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, number<B, et_on> >::type
f67539c2
TL
114operator+(number<B, et_on>&& a, const V& b)
115{
1e59de90
TL
116 using default_ops::eval_add;
117 eval_add(a.backend(), number<B, et_on>::canonical_value(b));
118 return std::move(a);
f67539c2 119}
1e59de90 120
7c673cae 121template <class V, class B>
1e59de90 122inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::add_immediates, V, number<B, et_on> > >::type
92f5a8d4 123operator+(const V& a, const number<B, et_on>& b)
7c673cae
FG
124{
125 return detail::expression<detail::add_immediates, V, number<B, et_on> >(a, b);
126}
1e59de90 127
f67539c2 128template <class V, class B>
1e59de90 129inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, number<B, et_on> >::type
f67539c2
TL
130operator+(const V& a, number<B, et_on>&& b)
131{
1e59de90
TL
132 using default_ops::eval_add;
133 eval_add(b.backend(), number<B, et_on>::canonical_value(a));
134 return std::move(b);
f67539c2 135}
1e59de90 136
7c673cae 137template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
92f5a8d4
TL
138inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
139operator+(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
140{
141 return detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
142}
1e59de90
TL
143
144template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
145inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
146 std::is_same<typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET> >::value,
147 typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
148operator+(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
149{
150 a += b;
151 return std::move(a);
152}
f67539c2 153template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90
TL
154inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
155 !std::is_same<typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET> >::value,
156 typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
f67539c2
TL
157operator+(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
158{
159 return detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
160}
1e59de90 161
7c673cae 162template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
92f5a8d4
TL
163inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
164operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
7c673cae
FG
165{
166 return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
167}
1e59de90 168
f67539c2 169template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
1e59de90
TL
170inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
171 std::is_same<typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
172 typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
173operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
174{
175 b += a;
176 return std::move(b);
177}
178template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
179inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
180 !std::is_same<typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
181 typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
f67539c2
TL
182operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
183{
184 return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
185}
1e59de90 186
7c673cae 187template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
92f5a8d4
TL
188inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
189operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
7c673cae
FG
190{
191 return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
192}
193template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
1e59de90 194inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
92f5a8d4 195operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
7c673cae 196{
92f5a8d4 197 return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
7c673cae
FG
198}
199template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90 200inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::plus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
92f5a8d4 201operator+(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
202{
203 return detail::expression<detail::plus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
204}
205//
206// Fused multiply add:
207//
208template <class V, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90 209inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value,
92f5a8d4
TL
210 detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V> >::type
211operator+(const V& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
212{
213 return detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V>(b.left(), b.right(), a);
214}
215template <class Arg1, class Arg2, class Arg3, class Arg4, class V>
1e59de90 216inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value,
92f5a8d4
TL
217 detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V> >::type
218operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
7c673cae
FG
219{
220 return detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V>(a.left(), a.right(), b);
221}
222template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
92f5a8d4
TL
223inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >
224operator+(const number<B, ET>& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
225{
226 return detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(b.left(), b.right(), a);
227}
1e59de90 228
f67539c2 229template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90
TL
230inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
231 std::is_same<typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type, number<B, ET>>::value,
232 typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type>::type
233operator+(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
234{
235 a += b;
236 return std::move(a);
237}
238template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
239inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
240 !std::is_same<typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type, number<B, ET>>::value,
241 typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type>::type
f67539c2
TL
242operator+(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
243{
244 return detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(b.left(), b.right(), a);
245}
1e59de90 246
7c673cae 247template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
92f5a8d4
TL
248inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >
249operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
7c673cae
FG
250{
251 return detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(a.left(), a.right(), b);
252}
1e59de90
TL
253
254template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
255inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
256 std::is_same<typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type, number<B, ET>>::value,
257 typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type>::type
258operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
259{
260 b += a;
261 return std::move(b);
262}
f67539c2 263template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
1e59de90
TL
264inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
265 !std::is_same<typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type, number<B, ET>>::value,
266 typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type>::type
f67539c2
TL
267operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
268{
269 return detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(a.left(), a.right(), b);
270}
1e59de90 271
7c673cae
FG
272//
273// Fused multiply subtract:
274//
275template <class V, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90 276inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value,
92f5a8d4
TL
277 detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V> > >::type
278operator-(const V& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae 279{
92f5a8d4 280 return detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V> >(detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V>(b.left(), b.right(), a));
7c673cae
FG
281}
282template <class Arg1, class Arg2, class Arg3, class Arg4, class V>
1e59de90 283inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value,
92f5a8d4
TL
284 detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V> >::type
285operator-(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
7c673cae
FG
286{
287 return detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, V>(a.left(), a.right(), b);
288}
289template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
92f5a8d4
TL
290inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >
291operator-(const number<B, ET>& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae 292{
92f5a8d4 293 return detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >(detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(b.left(), b.right(), a));
7c673cae 294}
1e59de90
TL
295
296template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
297inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
298 std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >::result_type, number<B, ET>>::value,
299 typename detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >::result_type>::type
300operator-(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
301{
302 a -= b;
303 return std::move(a);
304}
f67539c2 305template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90
TL
306inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
307 !std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >::result_type, number<B, ET>>::value,
308 typename detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >::result_type>::type
f67539c2
TL
309operator-(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
310{
311 return detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >(detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(b.left(), b.right(), a));
312}
1e59de90 313
7c673cae 314template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
92f5a8d4
TL
315inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >
316operator-(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
7c673cae
FG
317{
318 return detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(a.left(), a.right(), b);
319}
1e59de90 320
f67539c2
TL
321template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
322inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type
323operator-(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
324{
325 return detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(a.left(), a.right(), b);
326}
1e59de90 327
7c673cae
FG
328//
329// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
330//
331template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
92f5a8d4
TL
332inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, number<B, ET>, Arg1>
333operator+(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
334{
335 return detail::expression<detail::minus, number<B, ET>, Arg1>(a, b.left_ref());
336}
1e59de90
TL
337
338template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
339inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
340 std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
341 typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type>::type
342operator+(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
343{
344 a -= b.left_ref();
345 return std::move(a);
346}
f67539c2 347template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90
TL
348inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
349 !std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
350 typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type>::type
f67539c2
TL
351operator+(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
352{
353 return detail::expression<detail::minus, number<B, ET>, Arg1>(a, b.left_ref());
354}
1e59de90 355
7c673cae 356template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
92f5a8d4
TL
357inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, number<B, ET>, Arg1>
358operator+(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
7c673cae
FG
359{
360 return detail::expression<detail::minus, number<B, ET>, Arg1>(b, a.left_ref());
361}
1e59de90 362
f67539c2 363template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
1e59de90
TL
364inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
365 std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
366 typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type>::type
367operator+(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
368{
369 b -= a.left_ref();
370 return std::move(b);
371}
372template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
373inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
374 !std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
375 typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type>::type
f67539c2
TL
376operator+(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
377{
378 return detail::expression<detail::minus, number<B, ET>, Arg1>(b, a.left_ref());
379}
1e59de90 380
7c673cae 381template <class B>
92f5a8d4
TL
382inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
383operator+(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
7c673cae
FG
384{
385 return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref());
386}
1e59de90 387
f67539c2
TL
388template <class B>
389inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >::result_type
390operator+(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
391{
1e59de90
TL
392 using default_ops::eval_subtract;
393 eval_subtract(a.backend(), b.left_ref().backend());
394 return std::move(a);
f67539c2 395}
1e59de90 396
7c673cae 397template <class B>
92f5a8d4
TL
398inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
399operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
7c673cae
FG
400{
401 return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref());
402}
1e59de90 403
f67539c2
TL
404template <class B>
405inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >::result_type
406operator+(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
407{
1e59de90
TL
408 using default_ops::eval_subtract;
409 eval_subtract(b.backend(), a.left_ref().backend());
410 return std::move(b);
f67539c2 411}
1e59de90 412
7c673cae 413template <class B, class V>
1e59de90 414inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::subtract_immediates, V, number<B, et_on> > >::type
92f5a8d4 415operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
7c673cae
FG
416{
417 return detail::expression<detail::subtract_immediates, V, number<B, et_on> >(b, a.left_ref());
418}
419template <class B, class B2, expression_template_option ET>
1e59de90 420inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> > >::type
92f5a8d4 421operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
7c673cae
FG
422{
423 return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(b, a.left_ref());
424}
1e59de90 425
f67539c2 426template <class B, class B2, expression_template_option ET>
1e59de90 427inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >::result_type>::type
f67539c2
TL
428operator+(const detail::expression<detail::negate, number<B, et_on> >& a, number<B2, ET>&& b)
429{
430 return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(b, a.left_ref());
431}
1e59de90 432
7c673cae 433template <class B2, expression_template_option ET, class B>
1e59de90 434inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> > >::type
92f5a8d4 435operator+(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
7c673cae
FG
436{
437 return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
438}
1e59de90 439
f67539c2 440template <class B2, expression_template_option ET, class B>
1e59de90 441inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >::result_type>::type
f67539c2
TL
442operator+(number<B2, ET>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
443{
444 return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
445}
1e59de90 446
7c673cae 447template <class B>
92f5a8d4
TL
448inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >
449operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const detail::expression<detail::negate, number<B, et_on> >& b)
7c673cae
FG
450{
451 return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >(detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(a.left_ref(), b.left_ref()));
452}
453//
454// Subtraction:
455//
456template <class B>
92f5a8d4
TL
457inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
458operator-(const number<B, et_on>& a, const number<B, et_on>& b)
7c673cae
FG
459{
460 return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(a, b);
461}
1e59de90 462
f67539c2
TL
463template <class B>
464inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
465operator-(number<B, et_on>&& a, const number<B, et_on>& b)
466{
1e59de90
TL
467 using default_ops::eval_subtract;
468 eval_subtract(a.backend(), b.backend());
469 return std::move(a);
f67539c2
TL
470}
471template <class B>
472inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
473operator-(const number<B, et_on>& a, number<B, et_on>&& b)
474{
1e59de90
TL
475 using default_ops::eval_subtract;
476 eval_subtract(b.backend(), a.backend());
477 b.backend().negate();
478 return std::move(b);
f67539c2
TL
479}
480template <class B>
481inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
482operator-(number<B, et_on>&& a, number<B, et_on>&& b)
483{
1e59de90
TL
484 using default_ops::eval_subtract;
485 eval_subtract(a.backend(), b.backend());
486 return std::move(a);
f67539c2 487}
1e59de90 488
7c673cae 489template <class B, class V>
1e59de90 490inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, detail::expression<detail::subtract_immediates, number<B, et_on>, V> >::type
92f5a8d4 491operator-(const number<B, et_on>& a, const V& b)
7c673cae 492{
92f5a8d4 493 return detail::expression<detail::subtract_immediates, number<B, et_on>, V>(a, b);
7c673cae 494}
1e59de90 495
f67539c2 496template <class B, class V>
1e59de90 497inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, number<B, et_on> >::type
f67539c2
TL
498operator-(number<B, et_on>&& a, const V& b)
499{
1e59de90
TL
500 using default_ops::eval_subtract;
501 eval_subtract(a.backend(), number<B, et_on>::canonical_value(b));
502 return std::move(a);
f67539c2 503}
1e59de90 504
7c673cae 505template <class V, class B>
1e59de90 506inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::subtract_immediates, V, number<B, et_on> > >::type
92f5a8d4 507operator-(const V& a, const number<B, et_on>& b)
7c673cae
FG
508{
509 return detail::expression<detail::subtract_immediates, V, number<B, et_on> >(a, b);
510}
1e59de90 511
f67539c2 512template <class V, class B>
1e59de90 513inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, number<B, et_on> >::type
f67539c2
TL
514operator-(const V& a, number<B, et_on>&& b)
515{
1e59de90
TL
516 using default_ops::eval_subtract;
517 eval_subtract(b.backend(), number<B, et_on>::canonical_value(a));
518 b.backend().negate();
519 return std::move(b);
f67539c2 520}
1e59de90 521
7c673cae 522template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
92f5a8d4
TL
523inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
524operator-(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
525{
526 return detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
527}
1e59de90
TL
528
529template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
530inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
531 std::is_same<typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
532 typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
533operator-(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
534{
535 a -= b;
536 return std::move(a);
537}
f67539c2 538template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90
TL
539inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
540 !std::is_same<typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
541 typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
f67539c2
TL
542operator-(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
543{
544 return detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
545}
1e59de90 546
7c673cae 547template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
92f5a8d4
TL
548inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
549operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
7c673cae
FG
550{
551 return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
552}
1e59de90 553
f67539c2 554template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
1e59de90
TL
555inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
556 std::is_same<typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
557 typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
558operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
559{
560 b -= a;
561 b.backend().negate();
562 return std::move(b);
563}
564template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
565inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
566 !std::is_same<typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
567 typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
f67539c2
TL
568operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
569{
570 return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
571}
1e59de90 572
7c673cae 573template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
92f5a8d4
TL
574inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
575operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
7c673cae
FG
576{
577 return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
578}
579template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
1e59de90 580inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
92f5a8d4 581operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
7c673cae 582{
92f5a8d4 583 return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
7c673cae
FG
584}
585template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90 586inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::minus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
92f5a8d4 587operator-(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
588{
589 return detail::expression<detail::minus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
590}
591//
592// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
593//
594template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
92f5a8d4
TL
595inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::plus, number<B, ET>, Arg1>
596operator-(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
597{
598 return detail::expression<detail::plus, number<B, ET>, Arg1>(a, b.left_ref());
599}
1e59de90 600
f67539c2 601template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90
TL
602inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
603 std::is_same<typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
604 typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type>::type
605operator-(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
606{
607 a += b.left_ref();
608 return std::move(a);
609}
610template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
611inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
612 !std::is_same<typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
613 typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type>::type
f67539c2
TL
614operator-(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
615{
616 return detail::expression<detail::plus, number<B, ET>, Arg1>(a, b.left_ref());
617}
1e59de90 618
7c673cae 619template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
92f5a8d4
TL
620inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >
621operator-(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
7c673cae
FG
622{
623 return detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >(
92f5a8d4 624 detail::expression<detail::plus, number<B, ET>, Arg1>(b, a.left_ref()));
7c673cae 625}
1e59de90 626
f67539c2 627template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
1e59de90
TL
628inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
629 std::is_same<typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value,
630 typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type>::type
f67539c2
TL
631operator-(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
632{
1e59de90
TL
633 b += a.left_ref();
634 b.backend().negate();
635 return std::move(b);
f67539c2 636}
1e59de90
TL
637template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
638inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
639 !std::is_same<typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value,
640 typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type>::type
641operator-(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
642{
643 return detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >(detail::expression<detail::plus, number<B, ET>, Arg1>(b, a.left_ref()));
644}
645
7c673cae 646template <class B>
92f5a8d4
TL
647inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >
648operator-(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
7c673cae
FG
649{
650 return detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref());
651}
1e59de90 652
f67539c2
TL
653template <class B>
654inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >::result_type
655operator-(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
656{
1e59de90
TL
657 using default_ops::eval_add;
658 eval_add(a.backend(), b.left_ref().backend());
659 return std::move(a);
f67539c2 660}
1e59de90 661
7c673cae 662template <class B>
92f5a8d4
TL
663inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >
664operator-(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
7c673cae
FG
665{
666 return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >(
92f5a8d4 667 detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
7c673cae 668}
1e59de90
TL
669
670template <class B>
671inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
672 std::is_same<typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
673 typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
674operator-(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
675{
676 using default_ops::eval_add;
677 eval_add(b.backend(), a.left_ref().backend());
678 b.backend().negate();
679 return std::move(b);
680}
f67539c2 681template <class B>
1e59de90
TL
682inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
683 !std::is_same<typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
684 typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
f67539c2
TL
685operator-(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
686{
687 return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >(
1e59de90 688 detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
f67539c2 689}
1e59de90 690
7c673cae 691template <class B, class V>
1e59de90 692inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, V> > >::type
92f5a8d4 693operator-(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
7c673cae 694{
92f5a8d4 695 return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, V> >(detail::expression<detail::add_immediates, number<B, et_on>, V>(a.left_ref(), b));
7c673cae
FG
696}
697template <class B, class B2, expression_template_option ET>
1e59de90 698inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B2, ET> > > >::type
92f5a8d4 699operator-(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
7c673cae
FG
700{
701 return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B2, ET> > >(detail::expression<detail::add_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
702}
1e59de90 703
f67539c2 704template <class B, class B2, expression_template_option ET>
1e59de90 705inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B2, ET> > >::result_type>::type
f67539c2
TL
706operator-(const detail::expression<detail::negate, number<B, et_on> >& a, number<B2, ET>&& b)
707{
708 return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B2, ET> > >(detail::expression<detail::add_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
709}
1e59de90 710
7c673cae 711template <class V, class B>
1e59de90 712inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::add_immediates, V, number<B, et_on> > >::type
92f5a8d4 713operator-(const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
7c673cae
FG
714{
715 return detail::expression<detail::add_immediates, V, number<B, et_on> >(a, b.left_ref());
716}
717template <class B2, expression_template_option ET, class B>
1e59de90 718inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> > >::type
92f5a8d4 719operator-(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
7c673cae
FG
720{
721 return detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
722}
1e59de90 723
f67539c2 724template <class B2, expression_template_option ET, class B>
1e59de90 725inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> >::result_type>::type
f67539c2
TL
726operator-(number<B2, ET>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
727{
728 return detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
729}
1e59de90 730
7c673cae
FG
731//
732// Multiplication:
733//
734template <class B>
92f5a8d4
TL
735inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >
736operator*(const number<B, et_on>& a, const number<B, et_on>& b)
7c673cae
FG
737{
738 return detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b);
739}
1e59de90 740
f67539c2
TL
741template <class B>
742inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
743operator*(number<B, et_on>&& a, const number<B, et_on>& b)
744{
1e59de90
TL
745 using default_ops::eval_multiply;
746 eval_multiply(a.backend(), b.backend());
747 return std::move(a);
f67539c2
TL
748}
749template <class B>
750inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
751operator*(const number<B, et_on>& a, number<B, et_on>&& b)
752{
1e59de90
TL
753 using default_ops::eval_multiply;
754 eval_multiply(b.backend(), a.backend());
755 return std::move(b);
f67539c2
TL
756}
757template <class B>
758inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
759operator*(number<B, et_on>&& a, number<B, et_on>&& b)
760{
1e59de90
TL
761 using default_ops::eval_multiply;
762 eval_multiply(a.backend(), b.backend());
763 return std::move(a);
f67539c2 764}
1e59de90 765
7c673cae 766template <class B, class V>
1e59de90 767inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, detail::expression<detail::multiply_immediates, number<B, et_on>, V> >::type
92f5a8d4 768operator*(const number<B, et_on>& a, const V& b)
7c673cae 769{
92f5a8d4 770 return detail::expression<detail::multiply_immediates, number<B, et_on>, V>(a, b);
7c673cae 771}
1e59de90 772
f67539c2 773template <class B, class V>
1e59de90 774inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, number<B, et_on> >::type
f67539c2
TL
775operator*(number<B, et_on>&& a, const V& b)
776{
1e59de90
TL
777 using default_ops::eval_multiply;
778 eval_multiply(a.backend(), number<B, et_on>::canonical_value(b));
779 return std::move(a);
f67539c2 780}
1e59de90 781
7c673cae 782template <class V, class B>
1e59de90 783inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::multiply_immediates, V, number<B, et_on> > >::type
92f5a8d4 784operator*(const V& a, const number<B, et_on>& b)
7c673cae
FG
785{
786 return detail::expression<detail::multiply_immediates, V, number<B, et_on> >(a, b);
787}
1e59de90 788
f67539c2 789template <class V, class B>
1e59de90 790inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, number<B, et_on> >::type
f67539c2
TL
791operator*(const V& a, number<B, et_on>&& b)
792{
1e59de90
TL
793 using default_ops::eval_multiply;
794 eval_multiply(b.backend(), number<B, et_on>::canonical_value(a));
795 return std::move(b);
f67539c2 796}
1e59de90 797
7c673cae 798template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
92f5a8d4
TL
799inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
800operator*(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
801{
802 return detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
803}
1e59de90
TL
804
805template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
806inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
807 std::is_same<typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
808 typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
809operator*(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
810{
811 a *= b;
812 return std::move(a);
813}
f67539c2 814template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90
TL
815inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
816 !std::is_same<typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
817 typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
f67539c2
TL
818operator*(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
819{
820 return detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
821}
1e59de90 822
7c673cae 823template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
92f5a8d4
TL
824inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
825operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
7c673cae
FG
826{
827 return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
828}
1e59de90 829
f67539c2 830template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
1e59de90
TL
831inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
832 std::is_same<typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
833 typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
834operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
835{
836 b *= a;
837 return std::move(b);
838}
839template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
840inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
841 !std::is_same<typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
842 typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
f67539c2
TL
843operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
844{
845 return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
846}
1e59de90 847
7c673cae 848template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
92f5a8d4
TL
849inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
850operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
7c673cae
FG
851{
852 return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
853}
854template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
1e59de90 855inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
92f5a8d4 856operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
7c673cae 857{
92f5a8d4 858 return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
7c673cae
FG
859}
860template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90 861inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::multiplies, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
92f5a8d4 862operator*(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
863{
864 return detail::expression<detail::multiplies, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
865}
866//
867// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
868//
869template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
92f5a8d4
TL
870inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >
871operator*(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
872{
873 return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
92f5a8d4 874 detail::expression<detail::multiplies, number<B, ET>, Arg1>(a, b.left_ref()));
7c673cae 875}
1e59de90 876
f67539c2
TL
877template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
878inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >::result_type
879operator*(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
880{
881 return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
882 detail::expression<detail::multiplies, number<B, ET>, Arg1>(a, b.left_ref()));
883}
1e59de90 884
7c673cae 885template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
92f5a8d4
TL
886inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >
887operator*(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
7c673cae
FG
888{
889 return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
92f5a8d4 890 detail::expression<detail::multiplies, number<B, ET>, Arg1>(b, a.left_ref()));
7c673cae 891}
1e59de90 892
f67539c2
TL
893template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
894inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >::result_type
895operator*(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
896{
897 return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
898 detail::expression<detail::multiplies, number<B, ET>, Arg1>(b, a.left_ref()));
899}
1e59de90 900
7c673cae 901template <class B>
92f5a8d4
TL
902inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >
903operator*(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
7c673cae
FG
904{
905 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
92f5a8d4 906 detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
7c673cae 907}
1e59de90 908
f67539c2 909template <class B>
1e59de90
TL
910inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
911 std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
912 typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
913operator*(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
914{
915 a *= b.left_ref();
916 a.backend().negate();
917 return std::move(a);
918}
919template <class B>
920inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
921 !std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
922 typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
f67539c2
TL
923operator*(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
924{
925 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
1e59de90 926 detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
f67539c2 927}
1e59de90 928
7c673cae 929template <class B>
92f5a8d4
TL
930inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >
931operator*(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
7c673cae
FG
932{
933 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
92f5a8d4 934 detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
7c673cae 935}
1e59de90 936
f67539c2 937template <class B>
1e59de90
TL
938inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
939 std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
940 typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
941operator*(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
942{
943 b *= a.left_ref();
944 b.backend().negate();
945 return std::move(b);
946}
947template <class B>
948inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
949 !std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
950 typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
f67539c2
TL
951operator*(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
952{
953 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
1e59de90 954 detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
f67539c2 955}
1e59de90 956
7c673cae 957template <class B, class V>
1e59de90 958inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V> > >::type
92f5a8d4 959operator*(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
7c673cae 960{
92f5a8d4
TL
961 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V> >(
962 detail::expression<detail::multiply_immediates, number<B, et_on>, V>(a.left_ref(), b));
7c673cae
FG
963}
964template <class B, class B2, expression_template_option ET>
1e59de90 965inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > > >::type
92f5a8d4 966operator*(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
7c673cae 967{
92f5a8d4
TL
968 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
969 detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
7c673cae 970}
1e59de90 971
f67539c2 972template <class B, class B2, expression_template_option ET>
1e59de90 973inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >::result_type>::type
f67539c2
TL
974operator*(const detail::expression<detail::negate, number<B, et_on> >& a, number<B2, ET>&& b)
975{
976 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
977 detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
978}
1e59de90 979
7c673cae 980template <class V, class B>
1e59de90 981inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V> > >::type
92f5a8d4 982operator*(const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
7c673cae 983{
92f5a8d4
TL
984 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V> >(
985 detail::expression<detail::multiply_immediates, number<B, et_on>, V>(b.left_ref(), a));
7c673cae
FG
986}
987template <class B2, expression_template_option ET, class B>
1e59de90 988inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > > >::type
92f5a8d4 989operator*(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
7c673cae
FG
990{
991 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
92f5a8d4 992 detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(b.left_ref(), a));
7c673cae 993}
1e59de90 994
f67539c2 995template <class B2, expression_template_option ET, class B>
1e59de90 996inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >::result_type>::type
f67539c2
TL
997operator*(number<B2, ET>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
998{
999 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
1000 detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(b.left_ref(), a));
1001}
1e59de90 1002
7c673cae
FG
1003//
1004// Division:
1005//
1006template <class B>
92f5a8d4
TL
1007inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >
1008operator/(const number<B, et_on>& a, const number<B, et_on>& b)
7c673cae
FG
1009{
1010 return detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b);
1011}
f67539c2
TL
1012template <class B>
1013inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
1014operator/(number<B, et_on>&& a, const number<B, et_on>& b)
1015{
1e59de90
TL
1016 using default_ops::eval_divide;
1017 eval_divide(a.backend(), b.backend());
1018 return std::move(a);
f67539c2
TL
1019}
1020template <class B>
1021inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
1022operator/(const number<B, et_on>& a, number<B, et_on>&& b)
1023{
1024 return detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b);
1025}
1026template <class B>
1027inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
1028operator/(number<B, et_on>&& a, number<B, et_on>&& b)
1029{
1e59de90
TL
1030 using default_ops::eval_divide;
1031 eval_divide(a.backend(), b.backend());
1032 return std::move(a);
f67539c2 1033}
7c673cae 1034template <class B, class V>
1e59de90 1035inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, detail::expression<detail::divide_immediates, number<B, et_on>, V> >::type
92f5a8d4 1036operator/(const number<B, et_on>& a, const V& b)
7c673cae 1037{
92f5a8d4 1038 return detail::expression<detail::divide_immediates, number<B, et_on>, V>(a, b);
7c673cae 1039}
f67539c2 1040template <class B, class V>
1e59de90 1041inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, number<B, et_on> >::type
f67539c2
TL
1042operator/(number<B, et_on>&& a, const V& b)
1043{
1e59de90
TL
1044 using default_ops::eval_divide;
1045 eval_divide(a.backend(), number<B, et_on>::canonical_value(b));
1046 return std::move(a);
f67539c2 1047}
7c673cae 1048template <class V, class B>
1e59de90 1049inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::divide_immediates, V, number<B, et_on> > >::type
92f5a8d4 1050operator/(const V& a, const number<B, et_on>& b)
7c673cae
FG
1051{
1052 return detail::expression<detail::divide_immediates, V, number<B, et_on> >(a, b);
1053}
f67539c2 1054template <class V, class B>
1e59de90 1055inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, number<B, et_on> >::type
f67539c2
TL
1056operator/(const V& a, number<B, et_on>&& b)
1057{
1058 return detail::expression<detail::divide_immediates, V, number<B, et_on> >(a, b);
1059}
7c673cae 1060template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
92f5a8d4
TL
1061inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
1062operator/(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
1063{
1064 return detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
1065}
f67539c2 1066template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90
TL
1067inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
1068 std::is_same<typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
1069 typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
1070operator/(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
1071{
1072 a /= b;
1073 return std::move(a);
1074}
1075template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1076inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
1077 !std::is_same<typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
1078 typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
f67539c2
TL
1079operator/(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
1080{
1081 return detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
1082}
7c673cae 1083template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
92f5a8d4
TL
1084inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
1085operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
7c673cae
FG
1086{
1087 return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
1088}
f67539c2
TL
1089template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
1090inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type
1091operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
1092{
1093 return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
1094}
7c673cae 1095template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
92f5a8d4
TL
1096inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
1097operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
7c673cae
FG
1098{
1099 return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
1100}
1101template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
1e59de90 1102inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
92f5a8d4 1103operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
7c673cae 1104{
92f5a8d4 1105 return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
7c673cae
FG
1106}
1107template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90 1108inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::divides, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
92f5a8d4 1109operator/(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
1110{
1111 return detail::expression<detail::divides, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
1112}
1113//
1114// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
1115//
1116template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
92f5a8d4
TL
1117inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >
1118operator/(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
1119{
1120 return detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >(
92f5a8d4 1121 detail::expression<detail::divides, number<B, ET>, Arg1>(a, b.left_ref()));
7c673cae 1122}
f67539c2 1123template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90
TL
1124inline typename std::enable_if<
1125 std::is_same<typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value,
1126 typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type>::type
1127operator/(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
1128{
1129 a /= b.left_ref();
1130 a.backend().negate();
1131 return std::move(a);
1132}
1133template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
1134inline typename std::enable_if<
1135 !std::is_same<typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value,
1136 typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type>::type
f67539c2
TL
1137operator/(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
1138{
1139 return detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >(
1e59de90 1140 detail::expression<detail::divides, number<B, ET>, Arg1>(a, b.left_ref()));
f67539c2 1141}
7c673cae 1142template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
92f5a8d4
TL
1143inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >
1144operator/(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
7c673cae
FG
1145{
1146 return detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >(
92f5a8d4 1147 detail::expression<detail::divides, Arg1, number<B, ET> >(a.left_ref(), b));
7c673cae 1148}
f67539c2
TL
1149template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
1150inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >::result_type
1151operator/(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
1152{
1153 return detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >(
1154 detail::expression<detail::divides, Arg1, number<B, ET> >(a.left_ref(), b));
1155}
7c673cae 1156template <class B>
92f5a8d4
TL
1157inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >
1158operator/(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
7c673cae
FG
1159{
1160 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >(
92f5a8d4 1161 detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
7c673cae 1162}
f67539c2
TL
1163template <class B>
1164inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >::result_type
1165operator/(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
1166{
1e59de90
TL
1167 a /= b.left_ref();
1168 a.backend().negate();
1169 return std::move(a);
f67539c2 1170}
7c673cae 1171template <class B>
92f5a8d4
TL
1172inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >
1173operator/(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
7c673cae
FG
1174{
1175 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >(
92f5a8d4 1176 detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a.left_ref(), b));
7c673cae 1177}
f67539c2
TL
1178template <class B>
1179inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >::result_type
1180operator/(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
1181{
1182 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >(
1183 detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a.left_ref(), b));
1184}
7c673cae 1185template <class B, class V>
1e59de90 1186inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, V> > >::type
92f5a8d4 1187operator/(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
7c673cae 1188{
92f5a8d4
TL
1189 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, V> >(
1190 detail::expression<detail::divide_immediates, number<B, et_on>, V>(a.left_ref(), b));
7c673cae
FG
1191}
1192template <class B, class B2, expression_template_option ET>
1e59de90 1193inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > > >::type
92f5a8d4 1194operator/(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
7c673cae
FG
1195{
1196 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > >(
92f5a8d4 1197 detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
7c673cae 1198}
f67539c2 1199template <class B, class B2, expression_template_option ET>
1e59de90 1200inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > >::result_type>::type
f67539c2
TL
1201operator/(const detail::expression<detail::negate, number<B, et_on> >& a, number<B2, ET>&& b)
1202{
1203 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > >(
1204 detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
1205}
7c673cae 1206template <class V, class B>
1e59de90 1207inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::divide_immediates, V, number<B, et_on> > > >::type
92f5a8d4 1208operator/(const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
7c673cae
FG
1209{
1210 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, V, number<B, et_on> > >(
92f5a8d4 1211 detail::expression<detail::divide_immediates, V, number<B, et_on> >(a, b.left_ref()));
7c673cae
FG
1212}
1213template <class B2, expression_template_option ET, class B>
1e59de90 1214inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > > >::type
92f5a8d4 1215operator/(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
7c673cae
FG
1216{
1217 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > >(
92f5a8d4 1218 detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref()));
7c673cae 1219}
f67539c2 1220template <class B2, expression_template_option ET, class B>
1e59de90 1221inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, typename detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > >::result_type>::value, number<B, et_on> >::type
f67539c2
TL
1222operator/(number<B2, ET>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
1223{
1224 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > >(
1225 detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref()));
1226}
7c673cae
FG
1227//
1228// Modulus:
1229//
1230template <class B>
1e59de90 1231inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
92f5a8d4
TL
1232 detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> > >::type
1233operator%(const number<B, et_on>& a, const number<B, et_on>& b)
7c673cae
FG
1234{
1235 return detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> >(a, b);
1236}
f67539c2 1237template <class B>
1e59de90 1238inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
f67539c2
TL
1239 number<B, et_on> >::type
1240operator%(number<B, et_on>&& a, const number<B, et_on>& b)
1241{
1e59de90
TL
1242 using default_ops::eval_modulus;
1243 eval_modulus(a.backend(), b.backend());
1244 return std::move(a);
f67539c2
TL
1245}
1246template <class B>
1e59de90 1247inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
f67539c2
TL
1248 number<B, et_on> >::type
1249operator%(const number<B, et_on>& a, number<B, et_on>&& b)
1250{
1251 return detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> >(a, b);
1252}
1253template <class B>
1e59de90 1254inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
f67539c2
TL
1255 number<B, et_on> >::type
1256operator%(number<B, et_on>&& a, number<B, et_on>&& b)
1257{
1e59de90
TL
1258 using default_ops::eval_modulus;
1259 eval_modulus(a.backend(), b.backend());
1260 return std::move(a);
f67539c2 1261}
7c673cae 1262template <class B, class V>
1e59de90 1263inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, number<B, et_on> >::value,
92f5a8d4
TL
1264 detail::expression<detail::modulus_immediates, number<B, et_on>, V> >::type
1265operator%(const number<B, et_on>& a, const V& b)
7c673cae 1266{
92f5a8d4 1267 return detail::expression<detail::modulus_immediates, number<B, et_on>, V>(a, b);
7c673cae 1268}
f67539c2 1269template <class B, class V>
1e59de90 1270inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, number<B, et_on> >::value,
f67539c2
TL
1271 number<B, et_on> >::type
1272operator%(number<B, et_on>&& a, const V& b)
1273{
1e59de90
TL
1274 using default_ops::eval_modulus;
1275 eval_modulus(a.backend(), number<B, et_on>::canonical_value(b));
1276 return std::move(a);
f67539c2 1277}
7c673cae 1278template <class V, class B>
1e59de90 1279inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
92f5a8d4
TL
1280 detail::expression<detail::modulus_immediates, V, number<B, et_on> > >::type
1281operator%(const V& a, const number<B, et_on>& b)
7c673cae
FG
1282{
1283 return detail::expression<detail::modulus_immediates, V, number<B, et_on> >(a, b);
1284}
f67539c2 1285template <class V, class B>
1e59de90 1286inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
f67539c2
TL
1287 number<B, et_on> >::type
1288operator%(const V& a, number<B, et_on>&& b)
1289{
1290 return detail::expression<detail::modulus_immediates, V, number<B, et_on> >(a, b);
1291}
7c673cae 1292template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90 1293inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
92f5a8d4
TL
1294 detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
1295operator%(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
1296{
1297 return detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
1298}
f67539c2 1299template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90
TL
1300inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
1301 std::is_same<typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
1302 && number_category<B>::value == number_kind_integer,
1303 typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
1304operator%(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
1305{
1306 a %= b;
1307 return std::move(a);
1308}
1309template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1310inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
1311 !std::is_same<typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
1312 && number_category<B>::value == number_kind_integer,
f67539c2
TL
1313 typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
1314operator%(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
1315{
1316 return detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
1317}
7c673cae 1318template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
1e59de90 1319inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
92f5a8d4
TL
1320 detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
1321operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
7c673cae
FG
1322{
1323 return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
1324}
f67539c2 1325template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
1e59de90 1326inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
f67539c2
TL
1327 typename detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type >::type
1328operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
1329{
1330 return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
1331}
7c673cae 1332template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
1e59de90 1333inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
92f5a8d4
TL
1334 detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
1335operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
7c673cae
FG
1336{
1337 return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
1338}
1339template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
1e59de90 1340inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
92f5a8d4
TL
1341 detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
1342operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
7c673cae 1343{
92f5a8d4 1344 return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
7c673cae
FG
1345}
1346template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90 1347inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
92f5a8d4
TL
1348 detail::expression<detail::modulus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
1349operator%(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
1350{
1351 return detail::expression<detail::modulus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
1352}
1353//
1354// Left shift:
1355//
1356template <class B, class I>
1e59de90 1357inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer), detail::expression<detail::shift_left, number<B, et_on>, I> >::type
92f5a8d4 1358operator<<(const number<B, et_on>& a, const I& b)
7c673cae
FG
1359{
1360 return detail::expression<detail::shift_left, number<B, et_on>, I>(a, b);
1361}
f67539c2 1362template <class B, class I>
1e59de90 1363inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_on> >::type
f67539c2
TL
1364operator<<(number<B, et_on>&& a, const I& b)
1365{
1e59de90
TL
1366 using default_ops::eval_left_shift;
1367 eval_left_shift(a.backend(), b);
1368 return std::move(a);
f67539c2 1369}
7c673cae 1370template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
1e59de90 1371inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
92f5a8d4
TL
1372 detail::expression<detail::shift_left, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
1373operator<<(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
7c673cae
FG
1374{
1375 return detail::expression<detail::shift_left, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I>(a, b);
1376}
1377//
1378// Right shift:
1379//
1380template <class B, class I>
1e59de90 1381inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer),
92f5a8d4
TL
1382 detail::expression<detail::shift_right, number<B, et_on>, I> >::type
1383operator>>(const number<B, et_on>& a, const I& b)
7c673cae
FG
1384{
1385 return detail::expression<detail::shift_right, number<B, et_on>, I>(a, b);
1386}
f67539c2 1387template <class B, class I>
1e59de90 1388inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer),
f67539c2
TL
1389 number<B, et_on> >::type
1390operator>>(number<B, et_on>&& a, const I& b)
1391{
1e59de90
TL
1392 using default_ops::eval_right_shift;
1393 eval_right_shift(a.backend(), b);
1394 return std::move(a);
f67539c2 1395}
7c673cae 1396template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
1e59de90 1397inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
92f5a8d4
TL
1398 detail::expression<detail::shift_right, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
1399operator>>(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
7c673cae
FG
1400{
1401 return detail::expression<detail::shift_right, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I>(a, b);
1402}
1403//
1404// Bitwise AND:
1405//
1406template <class B>
1e59de90 1407inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
92f5a8d4
TL
1408 detail::expression<detail::bitwise_and_immediates, number<B, et_on>, number<B, et_on> > >::type
1409operator&(const number<B, et_on>& a, const number<B, et_on>& b)
7c673cae
FG
1410{
1411 return detail::expression<detail::bitwise_and_immediates, number<B, et_on>, number<B, et_on> >(a, b);
1412}
f67539c2 1413template <class B>
1e59de90 1414inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
f67539c2
TL
1415 number<B, et_on> >::type
1416operator&(number<B, et_on>&& a, const number<B, et_on>& b)
1417{
1e59de90
TL
1418 using default_ops::eval_bitwise_and;
1419 eval_bitwise_and(a.backend(), b.backend());
1420 return std::move(a);
f67539c2
TL
1421}
1422template <class B>
1e59de90 1423inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
f67539c2
TL
1424 number<B, et_on> >::type
1425operator&(const number<B, et_on>& a, number<B, et_on>&& b)
1426{
1e59de90
TL
1427 using default_ops::eval_bitwise_and;
1428 eval_bitwise_and(b.backend(), a.backend());
1429 return std::move(b);
f67539c2
TL
1430}
1431template <class B>
1e59de90 1432inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
f67539c2
TL
1433 number<B, et_on> >::type
1434operator&(number<B, et_on>&& a, number<B, et_on>&& b)
1435{
1e59de90
TL
1436 using default_ops::eval_bitwise_and;
1437 eval_bitwise_and(a.backend(), b.backend());
1438 return std::move(a);
f67539c2 1439}
7c673cae 1440template <class B, class V>
1e59de90 1441inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
92f5a8d4
TL
1442 detail::expression<detail::bitwise_and_immediates, number<B, et_on>, V> >::type
1443operator&(const number<B, et_on>& a, const V& b)
7c673cae 1444{
92f5a8d4 1445 return detail::expression<detail::bitwise_and_immediates, number<B, et_on>, V>(a, b);
7c673cae 1446}
f67539c2 1447template <class B, class V>
1e59de90 1448inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
f67539c2
TL
1449 number<B, et_on> >::type
1450operator&(number<B, et_on>&& a, const V& b)
1451{
1e59de90
TL
1452 using default_ops::eval_bitwise_and;
1453 eval_bitwise_and(a.backend(), number<B, et_on>::canonical_value(b));
1454 return std::move(a);
f67539c2 1455}
7c673cae 1456template <class V, class B>
1e59de90 1457inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
92f5a8d4
TL
1458 detail::expression<detail::bitwise_and_immediates, V, number<B, et_on> > >::type
1459operator&(const V& a, const number<B, et_on>& b)
7c673cae
FG
1460{
1461 return detail::expression<detail::bitwise_and_immediates, V, number<B, et_on> >(a, b);
1462}
f67539c2 1463template <class V, class B>
1e59de90 1464inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
f67539c2
TL
1465 number<B, et_on> >::type
1466operator&(const V& a, number<B, et_on>&& b)
1467{
1e59de90
TL
1468 using default_ops::eval_bitwise_and;
1469 eval_bitwise_and(b.backend(), number<B, et_on>::canonical_value(a));
1470 return std::move(b);
f67539c2 1471}
7c673cae 1472template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90 1473inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
92f5a8d4
TL
1474 detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
1475operator&(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
1476{
1477 return detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
1478}
f67539c2 1479template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90
TL
1480inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
1481 std::is_same<typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
1482 && number_category<B>::value == number_kind_integer,
1483 typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
1484operator&(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
1485{
1486 a &= b;
1487 return std::move(a);
1488}
1489template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1490inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
1491 !std::is_same<typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
1492 && number_category<B>::value == number_kind_integer,
f67539c2
TL
1493 typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
1494operator&(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
1495{
1496 return detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
1497}
7c673cae 1498template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
1e59de90 1499inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
92f5a8d4
TL
1500 detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
1501operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
7c673cae
FG
1502{
1503 return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
1504}
f67539c2 1505template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
1e59de90
TL
1506inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
1507 std::is_same<typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
1508 && number_category<B>::value == number_kind_integer,
1509 typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type >::type
1510operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
1511{
1512 b &= a;
1513 return std::move(b);
1514}
1515template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
1516inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
1517 !std::is_same<typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
1518 && number_category<B>::value == number_kind_integer,
f67539c2
TL
1519 typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type >::type
1520operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
1521{
1522 return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
1523}
7c673cae 1524template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
1e59de90 1525inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
92f5a8d4
TL
1526 detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
1527operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
7c673cae
FG
1528{
1529 return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
1530}
1531template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
1e59de90 1532inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
92f5a8d4
TL
1533 detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
1534operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
7c673cae 1535{
92f5a8d4 1536 return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
7c673cae
FG
1537}
1538template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90 1539inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
92f5a8d4
TL
1540 detail::expression<detail::bitwise_and, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
1541operator&(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
1542{
1543 return detail::expression<detail::bitwise_and, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
1544}
1545//
1546// Bitwise OR:
1547//
1548template <class B>
1e59de90 1549inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
92f5a8d4
TL
1550 detail::expression<detail::bitwise_or_immediates, number<B, et_on>, number<B, et_on> > >::type
1551operator|(const number<B, et_on>& a, const number<B, et_on>& b)
7c673cae
FG
1552{
1553 return detail::expression<detail::bitwise_or_immediates, number<B, et_on>, number<B, et_on> >(a, b);
1554}
f67539c2 1555template <class B>
1e59de90 1556inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
f67539c2
TL
1557 number<B, et_on> >::type
1558operator|(number<B, et_on>&& a, const number<B, et_on>& b)
1559{
1e59de90
TL
1560 using default_ops::eval_bitwise_or;
1561 eval_bitwise_or(a.backend(), b.backend());
1562 return std::move(a);
f67539c2
TL
1563}
1564template <class B>
1e59de90 1565inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
f67539c2
TL
1566 number<B, et_on> >::type
1567operator|(const number<B, et_on>& a, number<B, et_on>&& b)
1568{
1e59de90
TL
1569 using default_ops::eval_bitwise_or;
1570 eval_bitwise_or(b.backend(), a.backend());
1571 return std::move(b);
f67539c2
TL
1572}
1573template <class B>
1e59de90 1574inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
f67539c2
TL
1575 number<B, et_on> >::type
1576operator|(number<B, et_on>&& a, number<B, et_on>&& b)
1577{
1e59de90
TL
1578 using default_ops::eval_bitwise_or;
1579 eval_bitwise_or(a.backend(), b.backend());
1580 return std::move(a);
f67539c2 1581}
7c673cae 1582template <class B, class V>
1e59de90 1583inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
92f5a8d4
TL
1584 detail::expression<detail::bitwise_or_immediates, number<B, et_on>, V> >::type
1585operator|(const number<B, et_on>& a, const V& b)
7c673cae 1586{
92f5a8d4 1587 return detail::expression<detail::bitwise_or_immediates, number<B, et_on>, V>(a, b);
7c673cae 1588}
f67539c2 1589template <class B, class V>
1e59de90 1590inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
f67539c2
TL
1591 number<B, et_on> >::type
1592operator|(number<B, et_on>&& a, const V& b)
1593{
1e59de90
TL
1594 using default_ops::eval_bitwise_or;
1595 eval_bitwise_or(a.backend(), number<B, et_on>::canonical_value(b));
1596 return std::move(a);
f67539c2 1597}
7c673cae 1598template <class V, class B>
1e59de90 1599inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
92f5a8d4
TL
1600 detail::expression<detail::bitwise_or_immediates, V, number<B, et_on> > >::type
1601operator|(const V& a, const number<B, et_on>& b)
7c673cae
FG
1602{
1603 return detail::expression<detail::bitwise_or_immediates, V, number<B, et_on> >(a, b);
1604}
f67539c2 1605template <class V, class B>
1e59de90 1606inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
f67539c2
TL
1607 number<B, et_on> >::type
1608operator|(const V& a, number<B, et_on>&& b)
1609{
1e59de90
TL
1610 using default_ops::eval_bitwise_or;
1611 eval_bitwise_or(b.backend(), number<B, et_on>::canonical_value(a));
1612 return std::move(b);
f67539c2 1613}
7c673cae 1614template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90 1615inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
92f5a8d4
TL
1616 detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
1617operator|(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
1618{
1619 return detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
1620}
f67539c2 1621template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90
TL
1622inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
1623 std::is_same<typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
1624 && number_category<B>::value == number_kind_integer,
1625 typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
1626operator|(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
1627{
1628 a |= b;
1629 return std::move(a);
1630}
1631template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1632inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
1633 !std::is_same<typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
1634 && number_category<B>::value == number_kind_integer,
f67539c2
TL
1635 typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
1636operator|(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
1637{
1638 return detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
1639}
7c673cae 1640template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
1e59de90 1641inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
92f5a8d4
TL
1642 detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
1643operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
7c673cae
FG
1644{
1645 return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
1646}
f67539c2 1647template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
1e59de90
TL
1648inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
1649 std::is_same<typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
1650 && number_category<B>::value == number_kind_integer,
1651 typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
1652operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
1653{
1654 b |= a;
1655 return std::move(b);
1656}
1657template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
1658inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
1659 !std::is_same<typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
1660 && number_category<B>::value == number_kind_integer,
f67539c2
TL
1661 typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
1662operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
1663{
1664 return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
1665}
7c673cae 1666template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
1e59de90 1667inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
92f5a8d4
TL
1668 detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
1669operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
7c673cae
FG
1670{
1671 return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
1672}
1673template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
1e59de90 1674inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
92f5a8d4
TL
1675 detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
1676operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
7c673cae 1677{
92f5a8d4 1678 return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
7c673cae
FG
1679}
1680template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90 1681inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
92f5a8d4
TL
1682 detail::expression<detail::bitwise_or, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
1683operator|(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
1684{
1685 return detail::expression<detail::bitwise_or, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
1686}
1687//
1688// Bitwise XOR:
1689//
1690template <class B>
1e59de90 1691inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
92f5a8d4
TL
1692 detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, number<B, et_on> > >::type
1693operator^(const number<B, et_on>& a, const number<B, et_on>& b)
7c673cae
FG
1694{
1695 return detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, number<B, et_on> >(a, b);
1696}
f67539c2 1697template <class B>
1e59de90 1698inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
f67539c2
TL
1699 number<B, et_on> >::type
1700operator^(number<B, et_on>&& a, const number<B, et_on>& b)
1701{
1e59de90
TL
1702 using default_ops::eval_bitwise_xor;
1703 eval_bitwise_xor(a.backend(), b.backend());
1704 return std::move(a);
f67539c2
TL
1705}
1706template <class B>
1e59de90 1707inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
f67539c2
TL
1708 number<B, et_on> >::type
1709operator^(const number<B, et_on>& a, number<B, et_on>&& b)
1710{
1e59de90
TL
1711 using default_ops::eval_bitwise_xor;
1712 eval_bitwise_xor(b.backend(), a.backend());
1713 return std::move(b);
f67539c2
TL
1714}
1715template <class B>
1e59de90 1716inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
f67539c2
TL
1717 number<B, et_on> >::type
1718operator^(number<B, et_on>&& a, number<B, et_on>&& b)
1719{
1e59de90
TL
1720 using default_ops::eval_bitwise_xor;
1721 eval_bitwise_xor(a.backend(), b.backend());
1722 return std::move(a);
f67539c2 1723}
7c673cae 1724template <class B, class V>
1e59de90 1725inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
92f5a8d4
TL
1726 detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, V> >::type
1727operator^(const number<B, et_on>& a, const V& b)
7c673cae 1728{
92f5a8d4 1729 return detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, V>(a, b);
7c673cae 1730}
f67539c2 1731template <class B, class V>
1e59de90 1732inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
f67539c2
TL
1733 number<B, et_on> >::type
1734operator^(number<B, et_on>&& a, const V& b)
1735{
1e59de90
TL
1736 using default_ops::eval_bitwise_xor;
1737 eval_bitwise_xor(a.backend(), number<B, et_on>::canonical_value(b));
1738 return std::move(a);
f67539c2 1739}
7c673cae 1740template <class V, class B>
1e59de90 1741inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
92f5a8d4
TL
1742 detail::expression<detail::bitwise_xor_immediates, V, number<B, et_on> > >::type
1743operator^(const V& a, const number<B, et_on>& b)
7c673cae
FG
1744{
1745 return detail::expression<detail::bitwise_xor_immediates, V, number<B, et_on> >(a, b);
1746}
f67539c2 1747template <class V, class B>
1e59de90 1748inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
f67539c2
TL
1749 number<B, et_on> >::type
1750operator^(const V& a, number<B, et_on>&& b)
1751{
1e59de90
TL
1752 using default_ops::eval_bitwise_xor;
1753 eval_bitwise_xor(b.backend(), number<B, et_on>::canonical_value(a));
1754 return std::move(b);
f67539c2 1755}
7c673cae 1756template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90 1757inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
92f5a8d4
TL
1758 detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
1759operator^(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
1760{
1761 return detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
1762}
f67539c2 1763template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90
TL
1764inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
1765 std::is_same<typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
1766 && number_category<B>::value == number_kind_integer,
1767 typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
1768operator^(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
1769{
1770 a ^= b;
1771 return std::move(a);
1772}
1773template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1774inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
1775 !std::is_same<typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
1776 && number_category<B>::value == number_kind_integer,
f67539c2
TL
1777 typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
1778operator^(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
1779{
1780 return detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
1781}
7c673cae 1782template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
1e59de90 1783inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
92f5a8d4
TL
1784 detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
1785operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
7c673cae
FG
1786{
1787 return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
1788}
f67539c2 1789template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
1e59de90
TL
1790inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
1791 std::is_same<typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
1792 && number_category<B>::value == number_kind_integer,
1793 typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
1794operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
1795{
1796 b ^= a;
1797 return std::move(b);
1798}
1799template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
1800inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
1801 !std::is_same<typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
1802 && number_category<B>::value == number_kind_integer,
f67539c2
TL
1803 typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
1804operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
1805{
1806 return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
1807}
7c673cae 1808template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
1e59de90 1809inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
92f5a8d4
TL
1810 detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
1811operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
7c673cae
FG
1812{
1813 return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
1814}
1815template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
1e59de90 1816inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
92f5a8d4
TL
1817 detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
1818operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
7c673cae 1819{
92f5a8d4 1820 return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
7c673cae
FG
1821}
1822template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
1e59de90 1823inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer), detail::expression<detail::bitwise_xor, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
92f5a8d4 1824operator^(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
7c673cae
FG
1825{
1826 return detail::expression<detail::bitwise_xor, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
1827}
1828
92f5a8d4 1829}} // namespace boost::multiprecision
7c673cae
FG
1830
1831#endif