]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/multiprecision/detail/et_ops.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / multiprecision / detail / et_ops.hpp
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
9 namespace 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 //
23 template <class B, expression_template_option ExpressionTemplates>
24 inline BOOST_CONSTEXPR const number<B, ExpressionTemplates> operator + (const number<B, ExpressionTemplates>& v) { return v; }
25 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
26 inline BOOST_CONSTEXPR const detail::expression<tag, Arg1, Arg2, Arg3, Arg4> operator + (const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return v; }
27 template <class B>
28 inline 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 }
33 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
34 inline 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 }
39 template <class B>
40 inline 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); }
43 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
44 inline 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 //
50 template <class B>
51 inline 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 }
56 template <class B, class V>
57 inline 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 }
62 template <class V, class B>
63 inline 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 }
68 template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
69 inline 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 }
74 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
75 inline 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 }
80 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
81 inline 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 }
86 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
87 inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
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 }
92 template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
93 inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::plus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
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 //
101 template <class V, class Arg1, class Arg2, class Arg3, class Arg4>
102 inline 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 }
108 template <class Arg1, class Arg2, class Arg3, class Arg4, class V>
109 inline 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 }
115 template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
116 inline 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 }
121 template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
122 inline 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 //
130 template <class V, class Arg1, class Arg2, class Arg3, class Arg4>
131 inline 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 }
138 template <class Arg1, class Arg2, class Arg3, class Arg4, class V>
139 inline 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 }
145 template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
146 inline 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 }
152 template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
153 inline 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 //
161 template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
162 inline 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 }
167 template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
168 inline 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 }
173 template <class B>
174 inline 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 }
179 template <class B>
180 inline 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 }
185 template <class B, class V>
186 inline 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 }
191 template <class B, class B2, expression_template_option ET>
192 inline 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 }
197 template <class B2, expression_template_option ET, class B>
198 inline 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 }
203 template <class B>
204 inline 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 //
212 template <class B>
213 inline 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 }
218 template <class B, class V>
219 inline 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 }
224 template <class V, class B>
225 inline 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 }
230 template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
231 inline 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 }
236 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
237 inline 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 }
242 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
243 inline 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 }
248 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
249 inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
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 }
254 template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
255 inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::minus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
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 //
263 template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
264 inline 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 }
269 template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
270 inline 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 }
276 template <class B>
277 inline 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 }
282 template <class B>
283 inline 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 }
289 template <class B, class V>
290 inline 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 }
295 template <class B, class B2, expression_template_option ET>
296 inline 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 }
301 template <class V, class B>
302 inline 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 }
307 template <class B2, expression_template_option ET, class B>
308 inline 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 //
316 template <class B>
317 inline 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 }
322 template <class B, class V>
323 inline 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 }
328 template <class V, class B>
329 inline 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 }
334 template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
335 inline 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 }
340 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
341 inline 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 }
346 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
347 inline 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 }
352 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
353 inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
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 }
358 template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
359 inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::multiplies, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
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 //
367 template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
368 inline 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 }
374 template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
375 inline 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 }
381 template <class B>
382 inline 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 }
388 template <class B>
389 inline 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 }
395 template <class B, class V>
396 inline 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 }
402 template <class B, class B2, expression_template_option ET>
403 inline 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 }
409 template <class V, class B>
410 inline 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 }
416 template <class B2, expression_template_option ET, class B>
417 inline 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 //
426 template <class B>
427 inline 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 }
432 template <class B, class V>
433 inline 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 }
438 template <class V, class B>
439 inline 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 }
444 template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
445 inline 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 }
450 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
451 inline 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 }
456 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
457 inline 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 }
462 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
463 inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V > >::type
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 }
468 template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
469 inline typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>, detail::expression<detail::divides, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
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 //
477 template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
478 inline 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 }
484 template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
485 inline 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 }
491 template <class B>
492 inline 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 }
498 template <class B>
499 inline 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 }
505 template <class B, class V>
506 inline 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 }
512 template <class B, class B2, expression_template_option ET>
513 inline 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 }
519 template <class V, class B>
520 inline 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 }
526 template <class B2, expression_template_option ET, class B>
527 inline 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 //
536 template <class B>
537 inline 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 }
543 template <class B, class V>
544 inline 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 }
550 template <class V, class B>
551 inline 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 }
557 template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
558 inline 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 }
564 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
565 inline 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 }
571 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
572 inline 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 }
578 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
579 inline 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 }
586 template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
587 inline 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 //
597 template <class B, class I>
598 inline 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 }
603 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
604 inline 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 //
613 template <class B, class I>
614 inline 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 }
620 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
621 inline 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 //
631 template <class B>
632 inline 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 }
638 template <class B, class V>
639 inline 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 }
646 template <class V, class B>
647 inline 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 }
654 template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
655 inline 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 }
661 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
662 inline 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 }
668 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
669 inline 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 }
675 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
676 inline 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 }
683 template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
684 inline 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 //
694 template <class B>
695 inline 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 }
701 template <class B, class V>
702 inline 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 }
709 template <class V, class B>
710 inline 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 }
717 template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
718 inline 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 }
724 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
725 inline 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 }
731 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
732 inline 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 }
738 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
739 inline 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 }
746 template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
747 inline 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 //
757 template <class B>
758 inline 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 }
764 template <class B, class V>
765 inline 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 }
772 template <class V, class B>
773 inline 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 }
780 template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
781 inline 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 }
787 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
788 inline 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 }
794 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
795 inline 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 }
801 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
802 inline 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 }
809 template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
810 inline 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