]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/multiprecision/include/boost/multiprecision/detail/et_ops.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / multiprecision / include / 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
9namespace boost{ namespace multiprecision{
10
11//
12// Non-member operators for number:
13//
14// Unary operators first.
15// Note that these *must* return by value, even though that's somewhat against
16// existing practice. The issue is that in C++11 land one could easily and legitimately
17// write:
18// auto x = +1234_my_user_defined_suffix;
19// which would result in a dangling-reference-to-temporary if unary + returned a reference
20// to it's argument. While return-by-value is obviously inefficient in other situations
21// the reality is that no one ever uses unary operator+ anyway...!
22//
23template <class B, expression_template_option ExpressionTemplates>
24inline BOOST_CONSTEXPR const number<B, ExpressionTemplates> operator + (const number<B, ExpressionTemplates>& v) { return v; }
25template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
26inline BOOST_CONSTEXPR const detail::expression<tag, Arg1, Arg2, Arg3, Arg4> operator + (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return v; }
27template <class B>
28inline detail::expression<detail::negate, number<B, et_on> > operator - (const number<B, et_on>& v)
29{
30 BOOST_STATIC_ASSERT_MSG(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
31 return detail::expression<detail::negate, number<B, et_on> >(v);
32}
33template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
34inline detail::expression<detail::negate, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > operator - (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v)
35{
36 BOOST_STATIC_ASSERT_MSG((is_signed_number<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value), "Negating an unsigned type results in ill-defined behavior.");
37 return detail::expression<detail::negate, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(v);
38}
39template <class B>
40inline typename enable_if_c<number_category<B>::value == number_kind_integer,
41 detail::expression<detail::complement_immediates, number<B, et_on> > >::type
42 operator ~ (const number<B, et_on>& v) { return detail::expression<detail::complement_immediates, number<B, et_on> >(v); }
43template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
44inline typename enable_if_c<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
45 detail::expression<detail::bitwise_complement, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
46 operator ~ (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return detail::expression<detail::bitwise_complement, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(v); }
47//
48// Then addition:
49//
50template <class B>
51inline detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >
52 operator + (const number<B, et_on>& a, const number<B, et_on>& b)
53{
54 return detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(a, b);
55}
56template <class B, class V>
57inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::add_immediates, number<B, et_on>, V > >::type
58 operator + (const number<B, et_on>& a, const V& b)
59{
60 return detail::expression<detail::add_immediates, number<B, et_on>, V >(a, b);
61}
62template <class V, class B>
63inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::add_immediates, V, number<B, et_on> > >::type
64 operator + (const V& a, const number<B, et_on>& b)
65{
66 return detail::expression<detail::add_immediates, V, number<B, et_on> >(a, b);
67}
68template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
69inline detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
70 operator + (const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
71{
72 return detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
73}
74template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
75inline detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
76 operator + (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
77{
78 return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
79}
80template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
81inline detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
82 operator + (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
83{
84 return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
85}
86template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
87inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
88 operator + (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
89{
90 return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
91}
92template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
93inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::plus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
94 operator + (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
95{
96 return detail::expression<detail::plus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
97}
98//
99// Fused multiply add:
100//
101template <class V, class Arg1, class Arg2, class Arg3, class Arg4>
102inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>,
103 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
104 operator + (const V& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
105{
106 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);
107}
108template <class Arg1, class Arg2, class Arg3, class Arg4, class V>
109inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>,
110 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
111 operator + (const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
112{
113 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);
114}
115template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
116inline 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> >
117 operator + (const number<B, ET>& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
118{
119 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);
120}
121template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
122inline 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> >
123 operator + (const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
124{
125 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);
126}
127//
128// Fused multiply subtract:
129//
130template <class V, class Arg1, class Arg2, class Arg3, class Arg4>
131inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>,
132 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
133 operator - (const V& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
134{
135 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> >
136 (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));
137}
138template <class Arg1, class Arg2, class Arg3, class Arg4, class V>
139inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>,
140 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
141 operator - (const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
142{
143 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);
144}
145template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
146inline 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> > >
147 operator - (const number<B, ET>& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
148{
149 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> > >
150 (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));
151}
152template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
153inline 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> >
154 operator - (const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
155{
156 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);
157}
158//
159// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
160//
161template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
162inline detail::expression<detail::minus, number<B, ET>, Arg1>
163 operator + (const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
164{
165 return detail::expression<detail::minus, number<B, ET>, Arg1>(a, b.left_ref());
166}
167template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
168inline detail::expression<detail::minus, number<B, ET>, Arg1>
169 operator + (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
170{
171 return detail::expression<detail::minus, number<B, ET>, Arg1>(b, a.left_ref());
172}
173template <class B>
174inline detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
175 operator + (const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
176{
177 return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref());
178}
179template <class B>
180inline detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
181 operator + (const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
182{
183 return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref());
184}
185template <class B, class V>
186inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::subtract_immediates, V, number<B, et_on> > >::type
187 operator + (const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
188{
189 return detail::expression<detail::subtract_immediates, V, number<B, et_on> >(b, a.left_ref());
190}
191template <class B, class B2, expression_template_option ET>
192inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >, detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> > >::type
193 operator + (const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
194{
195 return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(b, a.left_ref());
196}
197template <class B2, expression_template_option ET, class B>
198inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >, detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> > >::type
199 operator + (const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
200{
201 return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
202}
203template <class B>
204inline detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >
205 operator + (const detail::expression<detail::negate, number<B, et_on> >& a, const detail::expression<detail::negate, number<B, et_on> >& b)
206{
207 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()));
208}
209//
210// Subtraction:
211//
212template <class B>
213inline detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
214 operator - (const number<B, et_on>& a, const number<B, et_on>& b)
215{
216 return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(a, b);
217}
218template <class B, class V>
219inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::subtract_immediates, number<B, et_on>, V > >::type
220 operator - (const number<B, et_on>& a, const V& b)
221{
222 return detail::expression<detail::subtract_immediates, number<B, et_on>, V >(a, b);
223}
224template <class V, class B>
225inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::subtract_immediates, V, number<B, et_on> > >::type
226 operator - (const V& a, const number<B, et_on>& b)
227{
228 return detail::expression<detail::subtract_immediates, V, number<B, et_on> >(a, b);
229}
230template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
231inline detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
232 operator - (const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
233{
234 return detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
235}
236template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
237inline detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
238 operator - (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
239{
240 return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
241}
242template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
243inline detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
244 operator - (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
245{
246 return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
247}
248template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
249inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
250 operator - (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
251{
252 return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
253}
254template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
255inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::minus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
256 operator - (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
257{
258 return detail::expression<detail::minus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
259}
260//
261// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
262//
263template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
264inline detail::expression<detail::plus, number<B, ET>, Arg1>
265 operator - (const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
266{
267 return detail::expression<detail::plus, number<B, ET>, Arg1>(a, b.left_ref());
268}
269template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
270inline detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >
271 operator - (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
272{
273 return detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >(
274 detail::expression<detail::plus, number<B, ET>, Arg1>(b, a.left_ref()));
275}
276template <class B>
277inline detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >
278 operator - (const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
279{
280 return detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref());
281}
282template <class B>
283inline detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >
284 operator - (const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
285{
286 return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >(
287 detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
288}
289template <class B, class V>
290inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, V > > >::type
291 operator - (const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
292{
293 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));
294}
295template <class B, class B2, expression_template_option ET>
296inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B2, ET> > > >::type
297 operator - (const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
298{
299 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));
300}
301template <class V, class B>
302inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::add_immediates, V, number<B, et_on> > >::type
303 operator - (const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
304{
305 return detail::expression<detail::add_immediates, V, number<B, et_on> >(a, b.left_ref());
306}
307template <class B2, expression_template_option ET, class B>
308inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >, detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> > >::type
309 operator - (const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
310{
311 return detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
312}
313//
314// Multiplication:
315//
316template <class B>
317inline detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >
318 operator * (const number<B, et_on>& a, const number<B, et_on>& b)
319{
320 return detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b);
321}
322template <class B, class V>
323inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::multiply_immediates, number<B, et_on>, V > >::type
324 operator * (const number<B, et_on>& a, const V& b)
325{
326 return detail::expression<detail::multiply_immediates, number<B, et_on>, V >(a, b);
327}
328template <class V, class B>
329inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::multiply_immediates, V, number<B, et_on> > >::type
330 operator * (const V& a, const number<B, et_on>& b)
331{
332 return detail::expression<detail::multiply_immediates, V, number<B, et_on> >(a, b);
333}
334template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
335inline detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
336 operator * (const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
337{
338 return detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
339}
340template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
341inline detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
342 operator * (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
343{
344 return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
345}
346template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
347inline detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
348 operator * (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
349{
350 return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
351}
352template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
353inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
354 operator * (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
355{
356 return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
357}
358template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
359inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::multiplies, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
360 operator * (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
361{
362 return detail::expression<detail::multiplies, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
363}
364//
365// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
366//
367template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
368inline detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >
369 operator * (const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
370{
371 return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
372 detail::expression<detail::multiplies, number<B, ET>, Arg1> (a, b.left_ref()));
373}
374template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
375inline detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >
376 operator * (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
377{
378 return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
379 detail::expression<detail::multiplies, number<B, ET>, Arg1>(b, a.left_ref()));
380}
381template <class B>
382inline detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >
383 operator * (const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
384{
385 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
386 detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
387}
388template <class B>
389inline detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >
390 operator * (const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
391{
392 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
393 detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
394}
395template <class B, class V>
396inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V > > >::type
397 operator * (const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
398{
399 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V > > (
400 detail::expression<detail::multiply_immediates, number<B, et_on>, V >(a.left_ref(), b));
401}
402template <class B, class B2, expression_template_option ET>
403inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > > >::type
404 operator * (const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
405{
406 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > > (
407 detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
408}
409template <class V, class B>
410inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V > > >::type
411 operator * (const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
412{
413 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V > >(
414 detail::expression<detail::multiply_immediates, number<B, et_on>, V >(b.left_ref(), a));
415}
416template <class B2, expression_template_option ET, class B>
417inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > > >::type
418 operator * (const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
419{
420 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
421 detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(b.left_ref(), a));
422}
423//
424// Division:
425//
426template <class B>
427inline detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >
428 operator / (const number<B, et_on>& a, const number<B, et_on>& b)
429{
430 return detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b);
431}
432template <class B, class V>
433inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::divide_immediates, number<B, et_on>, V > >::type
434 operator / (const number<B, et_on>& a, const V& b)
435{
436 return detail::expression<detail::divide_immediates, number<B, et_on>, V >(a, b);
437}
438template <class V, class B>
439inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::divide_immediates, V, number<B, et_on> > >::type
440 operator / (const V& a, const number<B, et_on>& b)
441{
442 return detail::expression<detail::divide_immediates, V, number<B, et_on> >(a, b);
443}
444template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
445inline detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
446 operator / (const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
447{
448 return detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
449}
450template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
451inline detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
452 operator / (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
453{
454 return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
455}
456template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
457inline detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
458 operator / (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
459{
460 return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
461}
462template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
463inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
464 operator / (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
465{
466 return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
467}
468template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
469inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::divides, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
470 operator / (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
471{
472 return detail::expression<detail::divides, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
473}
474//
475// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
476//
477template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
478inline detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >
479 operator / (const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
480{
481 return detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >(
482 detail::expression<detail::divides, number<B, ET>, Arg1>(a, b.left_ref()));
483}
484template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
485inline detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >
486 operator / (const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
487{
488 return detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >(
489 detail::expression<detail::divides, Arg1, number<B, ET> >(a.left_ref(), b));
490}
491template <class B>
492inline detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >
493 operator / (const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
494{
495 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >(
496 detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
497}
498template <class B>
499inline detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >
500 operator / (const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
501{
502 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >(
503 detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a.left_ref(), b));
504}
505template <class B, class V>
506inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, V > > >::type
507 operator / (const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
508{
509 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, V > >(
510 detail::expression<detail::divide_immediates, number<B, et_on>, V>(a.left_ref(), b));
511}
512template <class B, class B2, expression_template_option ET>
513inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > > >::type
514 operator / (const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
515{
516 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > >(
517 detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
518}
519template <class V, class B>
520inline typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::divide_immediates, V, number<B, et_on> > > >::type
521 operator / (const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
522{
523 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, V, number<B, et_on> > >(
524 detail::expression<detail::divide_immediates, V, number<B, et_on> >(a, b.left_ref()));
525}
526template <class B2, expression_template_option ET, class B>
527inline typename enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > > >::type
528 operator / (const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
529{
530 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > >(
531 detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref()));
532}
533//
534// Modulus:
535//
536template <class B>
537inline typename enable_if_c<number_category<B>::value == number_kind_integer,
538 detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> > >::type
539 operator % (const number<B, et_on>& a, const number<B, et_on>& b)
540{
541 return detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> >(a, b);
542}
543template <class B, class V>
544inline typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
545 detail::expression<detail::modulus_immediates, number<B, et_on>, V > >::type
546 operator % (const number<B, et_on>& a, const V& b)
547{
548 return detail::expression<detail::modulus_immediates, number<B, et_on>, V >(a, b);
549}
550template <class V, class B>
551inline typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
552 detail::expression<detail::modulus_immediates, V, number<B, et_on> > >::type
553 operator % (const V& a, const number<B, et_on>& b)
554{
555 return detail::expression<detail::modulus_immediates, V, number<B, et_on> >(a, b);
556}
557template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
558inline typename enable_if_c<number_category<B>::value == number_kind_integer,
559 detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
560 operator % (const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
561{
562 return detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
563}
564template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
565inline typename enable_if_c<number_category<B>::value == number_kind_integer,
566 detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
567 operator % (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
568{
569 return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
570}
571template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
572inline typename enable_if_c<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
573 detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
574 operator % (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
575{
576 return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
577}
578template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
579inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value
580 && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
581 detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
582 operator % (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
583{
584 return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
585}
586template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
587inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value
588 && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
589 detail::expression<detail::modulus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
590 operator % (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
591{
592 return detail::expression<detail::modulus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
593}
594//
595// Left shift:
596//
597template <class B, class I>
598inline typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer), detail::expression<detail::shift_left, number<B, et_on>, I > >::type
599 operator << (const number<B, et_on>& a, const I& b)
600{
601 return detail::expression<detail::shift_left, number<B, et_on>, I>(a, b);
602}
603template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
604inline typename enable_if_c<is_integral<I>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
605 detail::expression<detail::shift_left, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
606 operator << (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
607{
608 return detail::expression<detail::shift_left, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I>(a, b);
609}
610//
611// Right shift:
612//
613template <class B, class I>
614inline typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer),
615 detail::expression<detail::shift_right, number<B, et_on>, I > >::type
616 operator >> (const number<B, et_on>& a, const I& b)
617{
618 return detail::expression<detail::shift_right, number<B, et_on>, I>(a, b);
619}
620template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
621inline typename enable_if_c<is_integral<I>::value
622 && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
623 detail::expression<detail::shift_right, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
624 operator >> (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
625{
626 return detail::expression<detail::shift_right, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I>(a, b);
627}
628//
629// Bitwise AND:
630//
631template <class B>
632inline typename enable_if_c<number_category<B>::value == number_kind_integer,
633 detail::expression<detail::bitwise_and_immediates, number<B, et_on>, number<B, et_on> > >::type
634 operator & (const number<B, et_on>& a, const number<B, et_on>& b)
635{
636 return detail::expression<detail::bitwise_and_immediates, number<B, et_on>, number<B, et_on> >(a, b);
637}
638template <class B, class V>
639inline typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value
640 && (number_category<B>::value == number_kind_integer),
641 detail::expression<detail::bitwise_and_immediates, number<B, et_on>, V > >::type
642 operator & (const number<B, et_on>& a, const V& b)
643{
644 return detail::expression<detail::bitwise_and_immediates, number<B, et_on>, V >(a, b);
645}
646template <class V, class B>
647inline typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value
648 && (number_category<B>::value == number_kind_integer),
649 detail::expression<detail::bitwise_and_immediates, V, number<B, et_on> > >::type
650 operator & (const V& a, const number<B, et_on>& b)
651{
652 return detail::expression<detail::bitwise_and_immediates, V, number<B, et_on> >(a, b);
653}
654template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
655inline typename enable_if_c<number_category<B>::value == number_kind_integer,
656 detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
657 operator & (const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
658{
659 return detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
660}
661template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
662inline typename enable_if_c<number_category<B>::value == number_kind_integer,
663 detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
664 operator & (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
665{
666 return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
667}
668template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
669inline typename enable_if_c<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
670 detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
671 operator & (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
672{
673 return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
674}
675template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
676inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value
677 && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
678 detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
679 operator & (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
680{
681 return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
682}
683template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
684inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value
685 && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
686 detail::expression<detail::bitwise_and, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
687 operator & (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
688{
689 return detail::expression<detail::bitwise_and, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
690}
691//
692// Bitwise OR:
693//
694template <class B>
695inline typename enable_if_c<number_category<B>::value == number_kind_integer,
696 detail::expression<detail::bitwise_or_immediates, number<B, et_on>, number<B, et_on> > >::type
697 operator| (const number<B, et_on>& a, const number<B, et_on>& b)
698{
699 return detail::expression<detail::bitwise_or_immediates, number<B, et_on>, number<B, et_on> >(a, b);
700}
701template <class B, class V>
702inline typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value
703 && (number_category<B>::value == number_kind_integer),
704 detail::expression<detail::bitwise_or_immediates, number<B, et_on>, V > >::type
705 operator| (const number<B, et_on>& a, const V& b)
706{
707 return detail::expression<detail::bitwise_or_immediates, number<B, et_on>, V >(a, b);
708}
709template <class V, class B>
710inline typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value
711 && (number_category<B>::value == number_kind_integer),
712 detail::expression<detail::bitwise_or_immediates, V, number<B, et_on> > >::type
713 operator| (const V& a, const number<B, et_on>& b)
714{
715 return detail::expression<detail::bitwise_or_immediates, V, number<B, et_on> >(a, b);
716}
717template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
718inline typename enable_if_c<number_category<B>::value == number_kind_integer,
719 detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
720 operator| (const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
721{
722 return detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
723}
724template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
725inline typename enable_if_c<number_category<B>::value == number_kind_integer,
726 detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
727 operator| (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
728{
729 return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
730}
731template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
732inline typename enable_if_c<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
733 detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
734 operator| (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
735{
736 return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
737}
738template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
739inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value
740 && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
741 detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
742 operator| (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
743{
744 return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
745}
746template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
747inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value
748 && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
749 detail::expression<detail::bitwise_or, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
750 operator| (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
751{
752 return detail::expression<detail::bitwise_or, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
753}
754//
755// Bitwise XOR:
756//
757template <class B>
758inline typename enable_if_c<number_category<B>::value == number_kind_integer,
759 detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, number<B, et_on> > >::type
760 operator^ (const number<B, et_on>& a, const number<B, et_on>& b)
761{
762 return detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, number<B, et_on> >(a, b);
763}
764template <class B, class V>
765inline typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value
766 && (number_category<B>::value == number_kind_integer),
767 detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, V > >::type
768 operator^ (const number<B, et_on>& a, const V& b)
769{
770 return detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, V >(a, b);
771}
772template <class V, class B>
773inline typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value
774 && (number_category<B>::value == number_kind_integer),
775 detail::expression<detail::bitwise_xor_immediates, V, number<B, et_on> > >::type
776 operator^ (const V& a, const number<B, et_on>& b)
777{
778 return detail::expression<detail::bitwise_xor_immediates, V, number<B, et_on> >(a, b);
779}
780template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
781inline typename enable_if_c<number_category<B>::value == number_kind_integer,
782 detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
783 operator^ (const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
784{
785 return detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
786}
787template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
788inline typename enable_if_c<number_category<B>::value == number_kind_integer,
789 detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
790 operator^ (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
791{
792 return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
793}
794template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
795inline typename enable_if_c<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
796 detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
797 operator^ (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
798{
799 return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
800}
801template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
802inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value
803 && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
804 detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
805 operator^ (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
806{
807 return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V >(a, b);
808}
809template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
810inline typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value
811 && (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
812 operator^ (const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
813{
814 return detail::expression<detail::bitwise_xor, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
815}
816
817}} // namespaces
818
819#endif