1 ///////////////////////////////////////////////////////////////////////////////
2 //  Copyright 2012 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_NO_ET_OPS_HPP
7 #define BOOST_MP_NO_ET_OPS_HPP
8 
9 #ifdef BOOST_MSVC
10 #pragma warning(push)
11 #pragma warning(disable: 4714)
12 #endif
13 
14 namespace boost{
15 namespace multiprecision{
16 
17 //
18 // Operators for non-expression template enabled number.
19 // NOTE: this is not a complete header - really just a suffix to default_ops.hpp.
20 // NOTE: these operators have to be defined after the methods in default_ops.hpp.
21 //
22 template <class B>
operator -(const number<B,et_off> & v)23 BOOST_MP_FORCEINLINE number<B, et_off> operator - (const number<B, et_off>& v)
24 {
25    BOOST_STATIC_ASSERT_MSG(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
26    number<B, et_off> result(v);
27    result.backend().negate();
28    return BOOST_MP_MOVE(result);
29 }
30 template <class B>
operator ~(const number<B,et_off> & v)31 BOOST_MP_FORCEINLINE number<B, et_off> operator ~ (const number<B, et_off>& v)
32 {
33    number<B, et_off> result;
34    eval_complement(result.backend(), v.backend());
35    return BOOST_MP_MOVE(result);
36 }
37 //
38 // Addition:
39 //
40 template <class B>
operator +(const number<B,et_off> & a,const number<B,et_off> & b)41 BOOST_MP_FORCEINLINE number<B, et_off> operator + (const number<B, et_off>& a, const number<B, et_off>& b)
42 {
43    number<B, et_off> result;
44    using default_ops::eval_add;
45    eval_add(result.backend(), a.backend(), b.backend());
46    return BOOST_MP_MOVE(result);
47 }
48 template <class B, class V>
49 BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
operator +(const number<B,et_off> & a,const V & b)50    operator + (const number<B, et_off>& a, const V& b)
51 {
52    number<B, et_off> result;
53    using default_ops::eval_add;
54    eval_add(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
55    return BOOST_MP_MOVE(result);
56 }
57 template <class V, class B>
58 BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
operator +(const V & a,const number<B,et_off> & b)59    operator + (const V& a, const number<B, et_off>& b)
60 {
61    number<B, et_off> result;
62    using default_ops::eval_add;
63    eval_add(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
64    return BOOST_MP_MOVE(result);
65 }
66 //
67 // Subtraction:
68 //
69 template <class B>
operator -(const number<B,et_off> & a,const number<B,et_off> & b)70 BOOST_MP_FORCEINLINE number<B, et_off> operator - (const number<B, et_off>& a, const number<B, et_off>& b)
71 {
72    number<B, et_off> result;
73    using default_ops::eval_subtract;
74    eval_subtract(result.backend(), a.backend(), b.backend());
75    return BOOST_MP_MOVE(result);
76 }
77 template <class B, class V>
78 BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
operator -(const number<B,et_off> & a,const V & b)79    operator - (const number<B, et_off>& a, const V& b)
80 {
81    number<B, et_off> result;
82    using default_ops::eval_subtract;
83    eval_subtract(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
84    return BOOST_MP_MOVE(result);
85 }
86 template <class V, class B>
87 BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
operator -(const V & a,const number<B,et_off> & b)88    operator - (const V& a, const number<B, et_off>& b)
89 {
90    number<B, et_off> result;
91    using default_ops::eval_subtract;
92    eval_subtract(result.backend(), number<B, et_off>::canonical_value(a), b.backend());
93    return BOOST_MP_MOVE(result);
94 }
95 //
96 // Multiply:
97 //
98 template <class B>
operator *(const number<B,et_off> & a,const number<B,et_off> & b)99 BOOST_MP_FORCEINLINE number<B, et_off> operator * (const number<B, et_off>& a, const number<B, et_off>& b)
100 {
101    number<B, et_off> result;
102    using default_ops::eval_multiply;
103    eval_multiply(result.backend(), a.backend(), b.backend());
104    return BOOST_MP_MOVE(result);
105 }
106 template <class B, class V>
107 BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
operator *(const number<B,et_off> & a,const V & b)108    operator * (const number<B, et_off>& a, const V& b)
109 {
110    number<B, et_off> result;
111    using default_ops::eval_multiply;
112    eval_multiply(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
113    return BOOST_MP_MOVE(result);
114 }
115 template <class V, class B>
116 BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
operator *(const V & a,const number<B,et_off> & b)117    operator * (const V& a, const number<B, et_off>& b)
118 {
119    number<B, et_off> result;
120    using default_ops::eval_multiply;
121    eval_multiply(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
122    return BOOST_MP_MOVE(result);
123 }
124 //
125 // divide:
126 //
127 template <class B>
operator /(const number<B,et_off> & a,const number<B,et_off> & b)128 BOOST_MP_FORCEINLINE number<B, et_off> operator / (const number<B, et_off>& a, const number<B, et_off>& b)
129 {
130    number<B, et_off> result;
131    using default_ops::eval_divide;
132    eval_divide(result.backend(), a.backend(), b.backend());
133    return BOOST_MP_MOVE(result);
134 }
135 template <class B, class V>
136 BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
operator /(const number<B,et_off> & a,const V & b)137    operator / (const number<B, et_off>& a, const V& b)
138 {
139    number<B, et_off> result;
140    using default_ops::eval_divide;
141    eval_divide(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
142    return BOOST_MP_MOVE(result);
143 }
144 template <class V, class B>
145 BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
operator /(const V & a,const number<B,et_off> & b)146    operator / (const V& a, const number<B, et_off>& b)
147 {
148    number<B, et_off> result;
149    using default_ops::eval_divide;
150    eval_divide(result.backend(), number<B, et_off>::canonical_value(a), b.backend());
151    return BOOST_MP_MOVE(result);
152 }
153 //
154 // modulus:
155 //
156 template <class B>
operator %(const number<B,et_off> & a,const number<B,et_off> & b)157 BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator % (const number<B, et_off>& a, const number<B, et_off>& b)
158 {
159    number<B, et_off> result;
160    using default_ops::eval_modulus;
161    eval_modulus(result.backend(), a.backend(), b.backend());
162    return BOOST_MP_MOVE(result);
163 }
164 template <class B, class V>
165 BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator %(const number<B,et_off> & a,const V & b)166    operator % (const number<B, et_off>& a, const V& b)
167 {
168    number<B, et_off> result;
169    using default_ops::eval_modulus;
170    eval_modulus(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
171    return BOOST_MP_MOVE(result);
172 }
173 template <class V, class B>
174 BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator %(const V & a,const number<B,et_off> & b)175    operator % (const V& a, const number<B, et_off>& b)
176 {
177    number<B, et_off> result;
178    using default_ops::eval_modulus;
179    eval_modulus(result.backend(), number<B, et_off>::canonical_value(a), b.backend());
180    return BOOST_MP_MOVE(result);
181 }
182 //
183 // Bitwise or:
184 //
185 template <class B>
operator |(const number<B,et_off> & a,const number<B,et_off> & b)186 BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator | (const number<B, et_off>& a, const number<B, et_off>& b)
187 {
188    number<B, et_off> result;
189    using default_ops::eval_bitwise_or;
190    eval_bitwise_or(result.backend(), a.backend(), b.backend());
191    return BOOST_MP_MOVE(result);
192 }
193 template <class B, class V>
194 BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator |(const number<B,et_off> & a,const V & b)195    operator | (const number<B, et_off>& a, const V& b)
196 {
197    number<B, et_off> result;
198    using default_ops::eval_bitwise_or;
199    eval_bitwise_or(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
200    return BOOST_MP_MOVE(result);
201 }
202 template <class V, class B>
203 BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator |(const V & a,const number<B,et_off> & b)204    operator | (const V& a, const number<B, et_off>& b)
205 {
206    number<B, et_off> result;
207    using default_ops::eval_bitwise_or;
208    eval_bitwise_or(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
209    return BOOST_MP_MOVE(result);
210 }
211 //
212 // Bitwise xor:
213 //
214 template <class B>
operator ^(const number<B,et_off> & a,const number<B,et_off> & b)215 BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator ^ (const number<B, et_off>& a, const number<B, et_off>& b)
216 {
217    number<B, et_off> result;
218    using default_ops::eval_bitwise_xor;
219    eval_bitwise_xor(result.backend(), a.backend(), b.backend());
220    return BOOST_MP_MOVE(result);
221 }
222 template <class B, class V>
223 BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator ^(const number<B,et_off> & a,const V & b)224    operator ^ (const number<B, et_off>& a, const V& b)
225 {
226    number<B, et_off> result;
227    using default_ops::eval_bitwise_xor;
228    eval_bitwise_xor(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
229    return BOOST_MP_MOVE(result);
230 }
231 template <class V, class B>
232 BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator ^(const V & a,const number<B,et_off> & b)233    operator ^ (const V& a, const number<B, et_off>& b)
234 {
235    number<B, et_off> result;
236    using default_ops::eval_bitwise_xor;
237    eval_bitwise_xor(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
238    return BOOST_MP_MOVE(result);
239 }
240 //
241 // Bitwise and:
242 //
243 template <class B>
operator &(const number<B,et_off> & a,const number<B,et_off> & b)244 BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator & (const number<B, et_off>& a, const number<B, et_off>& b)
245 {
246    number<B, et_off> result;
247    using default_ops::eval_bitwise_and;
248    eval_bitwise_and(result.backend(), a.backend(), b.backend());
249    return BOOST_MP_MOVE(result);
250 }
251 template <class B, class V>
252 BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator &(const number<B,et_off> & a,const V & b)253    operator & (const number<B, et_off>& a, const V& b)
254 {
255    number<B, et_off> result;
256    using default_ops::eval_bitwise_and;
257    eval_bitwise_and(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
258    return BOOST_MP_MOVE(result);
259 }
260 template <class V, class B>
261 BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator &(const V & a,const number<B,et_off> & b)262    operator & (const V& a, const number<B, et_off>& b)
263 {
264    number<B, et_off> result;
265    using default_ops::eval_bitwise_and;
266    eval_bitwise_and(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
267    return BOOST_MP_MOVE(result);
268 }
269 //
270 // shifts:
271 //
272 template <class B, class I>
273 BOOST_MP_FORCEINLINE typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator <<(const number<B,et_off> & a,const I & b)274    operator << (const number<B, et_off>& a, const I& b)
275 {
276    number<B, et_off> result(a);
277    using default_ops::eval_left_shift;
278    detail::check_shift_range(b, mpl::bool_<(sizeof(I) > sizeof(std::size_t))>(), is_signed<I>());
279    eval_left_shift(result.backend(), b);
280    return BOOST_MP_MOVE(result);
281 }
282 template <class B, class I>
283 BOOST_MP_FORCEINLINE typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator >>(const number<B,et_off> & a,const I & b)284    operator >> (const number<B, et_off>& a, const I& b)
285 {
286    number<B, et_off> result(a);
287    using default_ops::eval_right_shift;
288    detail::check_shift_range(b, mpl::bool_<(sizeof(I) > sizeof(std::size_t))>(), is_signed<I>());
289    eval_right_shift(result.backend(), b);
290    return BOOST_MP_MOVE(result);
291 }
292 
293 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !(defined(__GNUC__) && ((__GNUC__ == 4) && (__GNUC_MINOR__ < 5)))
294 //
295 // If we have rvalue references go all over again with rvalue ref overloads and move semantics.
296 // Note that while it would be tempting to implement these so they return an rvalue reference
297 // (and indeed this would be optimally efficient), this is unsafe due to users propensity to
298 // write:
299 //
300 // const T& t = a * b;
301 //
302 // which would lead to a dangling reference if we didn't return by value.  Of course move
303 // semantics help a great deal in return by value, so performance is still pretty good...
304 //
305 template <class B>
operator -(number<B,et_off> && v)306 BOOST_MP_FORCEINLINE number<B, et_off> operator - (number<B, et_off>&& v)
307 {
308    BOOST_STATIC_ASSERT_MSG(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
309    v.backend().negate();
310    return static_cast<number<B, et_off>&&>(v);
311 }
312 template <class B>
operator ~(number<B,et_off> && v)313 BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator ~ (number<B, et_off>&& v)
314 {
315    eval_complement(v.backend(), v.backend());
316    return static_cast<number<B, et_off>&&>(v);
317 }
318 //
319 // Addition:
320 //
321 template <class B>
operator +(number<B,et_off> && a,const number<B,et_off> & b)322 BOOST_MP_FORCEINLINE number<B, et_off> operator + (number<B, et_off>&& a, const number<B, et_off>& b)
323 {
324    using default_ops::eval_add;
325    eval_add(a.backend(), b.backend());
326    return static_cast<number<B, et_off>&&>(a);
327 }
328 template <class B>
operator +(const number<B,et_off> & a,number<B,et_off> && b)329 BOOST_MP_FORCEINLINE number<B, et_off> operator + (const number<B, et_off>& a, number<B, et_off>&& b)
330 {
331    using default_ops::eval_add;
332    eval_add(b.backend(), a.backend());
333    return static_cast<number<B, et_off>&&>(b);
334 }
335 template <class B>
operator +(number<B,et_off> && a,number<B,et_off> && b)336 BOOST_MP_FORCEINLINE number<B, et_off> operator + (number<B, et_off>&& a, number<B, et_off>&& b)
337 {
338    using default_ops::eval_add;
339    eval_add(a.backend(), b.backend());
340    return static_cast<number<B, et_off>&&>(a);
341 }
342 template <class B, class V>
343 BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
operator +(number<B,et_off> && a,const V & b)344    operator + (number<B, et_off>&& a, const V& b)
345 {
346    using default_ops::eval_add;
347    eval_add(a.backend(), number<B, et_off>::canonical_value(b));
348    return static_cast<number<B, et_off>&&>(a);
349 }
350 template <class V, class B>
351 BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
operator +(const V & a,number<B,et_off> && b)352    operator + (const V& a, number<B, et_off>&& b)
353 {
354    using default_ops::eval_add;
355    eval_add(b.backend(), number<B, et_off>::canonical_value(a));
356    return static_cast<number<B, et_off>&&>(b);
357 }
358 //
359 // Subtraction:
360 //
361 template <class B>
operator -(number<B,et_off> && a,const number<B,et_off> & b)362 BOOST_MP_FORCEINLINE number<B, et_off> operator - (number<B, et_off>&& a, const number<B, et_off>& b)
363 {
364    using default_ops::eval_subtract;
365    eval_subtract(a.backend(), b.backend());
366    return static_cast<number<B, et_off>&&>(a);
367 }
368 template <class B>
operator -(const number<B,et_off> & a,number<B,et_off> && b)369 BOOST_MP_FORCEINLINE typename enable_if<is_signed_number<B>, number<B, et_off> >::type operator - (const number<B, et_off>& a, number<B, et_off>&& b)
370 {
371    using default_ops::eval_subtract;
372    eval_subtract(b.backend(), a.backend());
373    b.backend().negate();
374    return static_cast<number<B, et_off>&&>(b);
375 }
376 template <class B>
operator -(number<B,et_off> && a,number<B,et_off> && b)377 BOOST_MP_FORCEINLINE number<B, et_off> operator - (number<B, et_off>&& a, number<B, et_off>&& b)
378 {
379    using default_ops::eval_subtract;
380    eval_subtract(a.backend(), b.backend());
381    return static_cast<number<B, et_off>&&>(a);
382 }
383 template <class B, class V>
384 BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
operator -(number<B,et_off> && a,const V & b)385    operator - (number<B, et_off>&& a, const V& b)
386 {
387    using default_ops::eval_subtract;
388    eval_subtract(a.backend(), number<B, et_off>::canonical_value(b));
389    return static_cast<number<B, et_off>&&>(a);
390 }
391 template <class V, class B>
392 BOOST_MP_FORCEINLINE typename enable_if_c<(is_compatible_arithmetic_type<V, number<B, et_off> >::value && is_signed_number<B>::value), number<B, et_off> >::type
operator -(const V & a,number<B,et_off> && b)393    operator - (const V& a, number<B, et_off>&& b)
394 {
395    using default_ops::eval_subtract;
396    eval_subtract(b.backend(), number<B, et_off>::canonical_value(a));
397    b.backend().negate();
398    return static_cast<number<B, et_off>&&>(b);
399 }
400 //
401 // Multiply:
402 //
403 template <class B>
operator *(number<B,et_off> && a,const number<B,et_off> & b)404 BOOST_MP_FORCEINLINE number<B, et_off> operator * (number<B, et_off>&& a, const number<B, et_off>& b)
405 {
406    using default_ops::eval_multiply;
407    eval_multiply(a.backend(), b.backend());
408    return static_cast<number<B, et_off>&&>(a);
409 }
410 template <class B>
operator *(const number<B,et_off> & a,number<B,et_off> && b)411 BOOST_MP_FORCEINLINE number<B, et_off> operator * (const number<B, et_off>& a, number<B, et_off>&& b)
412 {
413    using default_ops::eval_multiply;
414    eval_multiply(b.backend(), a.backend());
415    return static_cast<number<B, et_off>&&>(b);
416 }
417 template <class B>
operator *(number<B,et_off> && a,number<B,et_off> && b)418 BOOST_MP_FORCEINLINE number<B, et_off> operator * (number<B, et_off>&& a, number<B, et_off>&& b)
419 {
420    using default_ops::eval_multiply;
421    eval_multiply(a.backend(), b.backend());
422    return static_cast<number<B, et_off>&&>(a);
423 }
424 template <class B, class V>
425 BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
operator *(number<B,et_off> && a,const V & b)426    operator * (number<B, et_off>&& a, const V& b)
427 {
428    using default_ops::eval_multiply;
429    eval_multiply(a.backend(), number<B, et_off>::canonical_value(b));
430    return static_cast<number<B, et_off>&&>(a);
431 }
432 template <class V, class B>
433 BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
operator *(const V & a,number<B,et_off> && b)434    operator * (const V& a, number<B, et_off>&& b)
435 {
436    using default_ops::eval_multiply;
437    eval_multiply(b.backend(), number<B, et_off>::canonical_value(a));
438    return static_cast<number<B, et_off>&&>(b);
439 }
440 //
441 // divide:
442 //
443 template <class B>
operator /(number<B,et_off> && a,const number<B,et_off> & b)444 BOOST_MP_FORCEINLINE number<B, et_off> operator / (number<B, et_off>&& a, const number<B, et_off>& b)
445 {
446    using default_ops::eval_divide;
447    eval_divide(a.backend(), b.backend());
448    return static_cast<number<B, et_off>&&>(a);
449 }
450 template <class B, class V>
451 BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
operator /(number<B,et_off> && a,const V & b)452    operator / (number<B, et_off>&& a, const V& b)
453 {
454    using default_ops::eval_divide;
455    eval_divide(a.backend(), number<B, et_off>::canonical_value(b));
456    return static_cast<number<B, et_off>&&>(a);
457 }
458 //
459 // modulus:
460 //
461 template <class B>
operator %(number<B,et_off> && a,const number<B,et_off> & b)462 BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator % (number<B, et_off>&& a, const number<B, et_off>& b)
463 {
464    using default_ops::eval_modulus;
465    eval_modulus(a.backend(), b.backend());
466    return static_cast<number<B, et_off>&&>(a);
467 }
468 template <class B, class V>
469 BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator %(number<B,et_off> && a,const V & b)470    operator % (number<B, et_off>&& a, const V& b)
471 {
472    using default_ops::eval_modulus;
473    eval_modulus(a.backend(), number<B, et_off>::canonical_value(b));
474    return static_cast<number<B, et_off>&&>(a);
475 }
476 //
477 // Bitwise or:
478 //
479 template <class B>
operator |(number<B,et_off> && a,const number<B,et_off> & b)480 BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator | (number<B, et_off>&& a, const number<B, et_off>& b)
481 {
482    using default_ops::eval_bitwise_or;
483    eval_bitwise_or(a.backend(), b.backend());
484    return static_cast<number<B, et_off>&&>(a);
485 }
486 template <class B>
operator |(const number<B,et_off> & a,number<B,et_off> && b)487 BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator | (const number<B, et_off>& a, number<B, et_off>&& b)
488 {
489    using default_ops::eval_bitwise_or;
490    eval_bitwise_or(b.backend(), a.backend());
491    return static_cast<number<B, et_off>&&>(b);
492 }
493 template <class B>
operator |(number<B,et_off> && a,number<B,et_off> && b)494 BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator | (number<B, et_off>&& a, number<B, et_off>&& b)
495 {
496    using default_ops::eval_bitwise_or;
497    eval_bitwise_or(a.backend(), b.backend());
498    return static_cast<number<B, et_off>&&>(a);
499 }
500 template <class B, class V>
501 BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator |(number<B,et_off> && a,const V & b)502    operator | (number<B, et_off>&& a, const V& b)
503 {
504    using default_ops::eval_bitwise_or;
505    eval_bitwise_or(a.backend(), number<B, et_off>::canonical_value(b));
506    return static_cast<number<B, et_off>&&>(a);
507 }
508 template <class V, class B>
509 BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator |(const V & a,number<B,et_off> && b)510    operator | (const V& a, number<B, et_off>&& b)
511 {
512    using default_ops::eval_bitwise_or;
513    eval_bitwise_or(b.backend(), number<B, et_off>::canonical_value(a));
514    return static_cast<number<B, et_off>&&>(b);
515 }
516 //
517 // Bitwise xor:
518 //
519 template <class B>
operator ^(number<B,et_off> && a,const number<B,et_off> & b)520 BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator ^ (number<B, et_off>&& a, const number<B, et_off>& b)
521 {
522    using default_ops::eval_bitwise_xor;
523    eval_bitwise_xor(a.backend(), b.backend());
524    return static_cast<number<B, et_off>&&>(a);
525 }
526 template <class B>
operator ^(const number<B,et_off> & a,number<B,et_off> && b)527 BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator ^ (const number<B, et_off>& a, number<B, et_off>&& b)
528 {
529    using default_ops::eval_bitwise_xor;
530    eval_bitwise_xor(b.backend(), a.backend());
531    return static_cast<number<B, et_off>&&>(b);
532 }
533 template <class B>
operator ^(number<B,et_off> && a,number<B,et_off> && b)534 BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator ^ (number<B, et_off>&& a, number<B, et_off>&& b)
535 {
536    using default_ops::eval_bitwise_xor;
537    eval_bitwise_xor(a.backend(), b.backend());
538    return static_cast<number<B, et_off>&&>(a);
539 }
540 template <class B, class V>
541 BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator ^(number<B,et_off> && a,const V & b)542    operator ^ (number<B, et_off>&& a, const V& b)
543 {
544    using default_ops::eval_bitwise_xor;
545    eval_bitwise_xor(a.backend(), number<B, et_off>::canonical_value(b));
546    return static_cast<number<B, et_off>&&>(a);
547 }
548 template <class V, class B>
549 BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator ^(const V & a,number<B,et_off> && b)550    operator ^ (const V& a, number<B, et_off>&& b)
551 {
552    using default_ops::eval_bitwise_xor;
553    eval_bitwise_xor(b.backend(), number<B, et_off>::canonical_value(a));
554    return static_cast<number<B, et_off>&&>(b);
555 }
556 //
557 // Bitwise and:
558 //
559 template <class B>
operator &(number<B,et_off> && a,const number<B,et_off> & b)560 BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator & (number<B, et_off>&& a, const number<B, et_off>& b)
561 {
562    using default_ops::eval_bitwise_and;
563    eval_bitwise_and(a.backend(), b.backend());
564    return static_cast<number<B, et_off>&&>(a);
565 }
566 template <class B>
operator &(const number<B,et_off> & a,number<B,et_off> && b)567 BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator & (const number<B, et_off>& a, number<B, et_off>&& b)
568 {
569    using default_ops::eval_bitwise_and;
570    eval_bitwise_and(b.backend(), a.backend());
571    return static_cast<number<B, et_off>&&>(b);
572 }
573 template <class B>
operator &(number<B,et_off> && a,number<B,et_off> && b)574 BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator & (number<B, et_off>&& a, number<B, et_off>&& b)
575 {
576    using default_ops::eval_bitwise_and;
577    eval_bitwise_and(a.backend(), b.backend());
578    return static_cast<number<B, et_off>&&>(a);
579 }
580 template <class B, class V>
581 BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator &(number<B,et_off> && a,const V & b)582    operator & (number<B, et_off>&& a, const V& b)
583 {
584    using default_ops::eval_bitwise_and;
585    eval_bitwise_and(a.backend(), number<B, et_off>::canonical_value(b));
586    return static_cast<number<B, et_off>&&>(a);
587 }
588 template <class V, class B>
589 BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator &(const V & a,number<B,et_off> && b)590    operator & (const V& a, number<B, et_off>&& b)
591 {
592    using default_ops::eval_bitwise_and;
593    eval_bitwise_and(b.backend(), number<B, et_off>::canonical_value(a));
594    return static_cast<number<B, et_off>&&>(b);
595 }
596 //
597 // shifts:
598 //
599 template <class B, class I>
600 BOOST_MP_FORCEINLINE typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator <<(number<B,et_off> && a,const I & b)601    operator << (number<B, et_off>&& a, const I& b)
602 {
603    using default_ops::eval_left_shift;
604    eval_left_shift(a.backend(), b);
605    return static_cast<number<B, et_off>&&>(a);
606 }
607 template <class B, class I>
608 BOOST_MP_FORCEINLINE typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
operator >>(number<B,et_off> && a,const I & b)609    operator >> (number<B, et_off>&& a, const I& b)
610 {
611    using default_ops::eval_right_shift;
612    eval_right_shift(a.backend(), b);
613    return static_cast<number<B, et_off>&&>(a);
614 }
615 
616 #endif
617 
618 }} // namespaces
619 
620 #ifdef BOOST_MSVC
621 #pragma warning(pop)
622 #endif
623 
624 #endif // BOOST_MP_NO_ET_OPS_HPP
625