]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/multiprecision/detail/et_ops.hpp
import new upstream nautilus stable release 14.2.8
[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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v)
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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >
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 BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >
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 BOOST_MP_CXX14_CONSTEXPR 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> >(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));
136 }
137 template <class Arg1, class Arg2, class Arg3, class Arg4, class V>
138 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>,
139 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
140 operator-(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
141 {
142 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);
143 }
144 template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
145 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >
146 operator-(const number<B, ET>& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
147 {
148 return detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >(detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(b.left(), b.right(), a));
149 }
150 template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
151 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >
152 operator-(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
153 {
154 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);
155 }
156 //
157 // Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
158 //
159 template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
160 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, number<B, ET>, Arg1>
161 operator+(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
162 {
163 return detail::expression<detail::minus, number<B, ET>, Arg1>(a, b.left_ref());
164 }
165 template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
166 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, number<B, ET>, Arg1>
167 operator+(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
168 {
169 return detail::expression<detail::minus, number<B, ET>, Arg1>(b, a.left_ref());
170 }
171 template <class B>
172 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
173 operator+(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
174 {
175 return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref());
176 }
177 template <class B>
178 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
179 operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
180 {
181 return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref());
182 }
183 template <class B, class V>
184 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::subtract_immediates, V, number<B, et_on> > >::type
185 operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
186 {
187 return detail::expression<detail::subtract_immediates, V, number<B, et_on> >(b, a.left_ref());
188 }
189 template <class B, class B2, expression_template_option ET>
190 inline BOOST_MP_CXX14_CONSTEXPR 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
191 operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
192 {
193 return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(b, a.left_ref());
194 }
195 template <class B2, expression_template_option ET, class B>
196 inline BOOST_MP_CXX14_CONSTEXPR 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
197 operator+(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
198 {
199 return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
200 }
201 template <class B>
202 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >
203 operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const detail::expression<detail::negate, number<B, et_on> >& b)
204 {
205 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()));
206 }
207 //
208 // Subtraction:
209 //
210 template <class B>
211 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
212 operator-(const number<B, et_on>& a, const number<B, et_on>& b)
213 {
214 return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(a, b);
215 }
216 template <class B, class V>
217 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::subtract_immediates, number<B, et_on>, V> >::type
218 operator-(const number<B, et_on>& a, const V& b)
219 {
220 return detail::expression<detail::subtract_immediates, number<B, et_on>, V>(a, b);
221 }
222 template <class V, class B>
223 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::subtract_immediates, V, number<B, et_on> > >::type
224 operator-(const V& a, const number<B, et_on>& b)
225 {
226 return detail::expression<detail::subtract_immediates, V, number<B, et_on> >(a, b);
227 }
228 template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
229 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
230 operator-(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
231 {
232 return detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
233 }
234 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
235 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
236 operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
237 {
238 return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
239 }
240 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
241 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
242 operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
243 {
244 return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
245 }
246 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
247 inline BOOST_MP_CXX14_CONSTEXPR 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
248 operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
249 {
250 return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
251 }
252 template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
253 inline BOOST_MP_CXX14_CONSTEXPR 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
254 operator-(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
255 {
256 return detail::expression<detail::minus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
257 }
258 //
259 // Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
260 //
261 template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
262 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::plus, number<B, ET>, Arg1>
263 operator-(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
264 {
265 return detail::expression<detail::plus, number<B, ET>, Arg1>(a, b.left_ref());
266 }
267 template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
268 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >
269 operator-(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
270 {
271 return detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >(
272 detail::expression<detail::plus, number<B, ET>, Arg1>(b, a.left_ref()));
273 }
274 template <class B>
275 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >
276 operator-(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
277 {
278 return detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref());
279 }
280 template <class B>
281 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >
282 operator-(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
283 {
284 return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >(
285 detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
286 }
287 template <class B, class V>
288 inline BOOST_MP_CXX14_CONSTEXPR 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
289 operator-(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
290 {
291 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));
292 }
293 template <class B, class B2, expression_template_option ET>
294 inline BOOST_MP_CXX14_CONSTEXPR 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
295 operator-(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
296 {
297 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));
298 }
299 template <class V, class B>
300 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::add_immediates, V, number<B, et_on> > >::type
301 operator-(const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
302 {
303 return detail::expression<detail::add_immediates, V, number<B, et_on> >(a, b.left_ref());
304 }
305 template <class B2, expression_template_option ET, class B>
306 inline BOOST_MP_CXX14_CONSTEXPR 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
307 operator-(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
308 {
309 return detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
310 }
311 //
312 // Multiplication:
313 //
314 template <class B>
315 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >
316 operator*(const number<B, et_on>& a, const number<B, et_on>& b)
317 {
318 return detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b);
319 }
320 template <class B, class V>
321 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::multiply_immediates, number<B, et_on>, V> >::type
322 operator*(const number<B, et_on>& a, const V& b)
323 {
324 return detail::expression<detail::multiply_immediates, number<B, et_on>, V>(a, b);
325 }
326 template <class V, class B>
327 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::multiply_immediates, V, number<B, et_on> > >::type
328 operator*(const V& a, const number<B, et_on>& b)
329 {
330 return detail::expression<detail::multiply_immediates, V, number<B, et_on> >(a, b);
331 }
332 template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
333 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
334 operator*(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
335 {
336 return detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
337 }
338 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
339 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
340 operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
341 {
342 return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
343 }
344 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
345 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
346 operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
347 {
348 return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
349 }
350 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
351 inline BOOST_MP_CXX14_CONSTEXPR 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
352 operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
353 {
354 return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
355 }
356 template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
357 inline BOOST_MP_CXX14_CONSTEXPR 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
358 operator*(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
359 {
360 return detail::expression<detail::multiplies, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
361 }
362 //
363 // Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
364 //
365 template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
366 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >
367 operator*(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
368 {
369 return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
370 detail::expression<detail::multiplies, number<B, ET>, Arg1>(a, b.left_ref()));
371 }
372 template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
373 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >
374 operator*(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
375 {
376 return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
377 detail::expression<detail::multiplies, number<B, ET>, Arg1>(b, a.left_ref()));
378 }
379 template <class B>
380 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >
381 operator*(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
382 {
383 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
384 detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
385 }
386 template <class B>
387 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >
388 operator*(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
389 {
390 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
391 detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
392 }
393 template <class B, class V>
394 inline BOOST_MP_CXX14_CONSTEXPR 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
395 operator*(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
396 {
397 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V> >(
398 detail::expression<detail::multiply_immediates, number<B, et_on>, V>(a.left_ref(), b));
399 }
400 template <class B, class B2, expression_template_option ET>
401 inline BOOST_MP_CXX14_CONSTEXPR 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
402 operator*(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
403 {
404 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
405 detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
406 }
407 template <class V, class B>
408 inline BOOST_MP_CXX14_CONSTEXPR 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
409 operator*(const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
410 {
411 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V> >(
412 detail::expression<detail::multiply_immediates, number<B, et_on>, V>(b.left_ref(), a));
413 }
414 template <class B2, expression_template_option ET, class B>
415 inline BOOST_MP_CXX14_CONSTEXPR 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
416 operator*(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
417 {
418 return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
419 detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(b.left_ref(), a));
420 }
421 //
422 // Division:
423 //
424 template <class B>
425 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >
426 operator/(const number<B, et_on>& a, const number<B, et_on>& b)
427 {
428 return detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b);
429 }
430 template <class B, class V>
431 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::divide_immediates, number<B, et_on>, V> >::type
432 operator/(const number<B, et_on>& a, const V& b)
433 {
434 return detail::expression<detail::divide_immediates, number<B, et_on>, V>(a, b);
435 }
436 template <class V, class B>
437 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >, detail::expression<detail::divide_immediates, V, number<B, et_on> > >::type
438 operator/(const V& a, const number<B, et_on>& b)
439 {
440 return detail::expression<detail::divide_immediates, V, number<B, et_on> >(a, b);
441 }
442 template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
443 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
444 operator/(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
445 {
446 return detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
447 }
448 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
449 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
450 operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
451 {
452 return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
453 }
454 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
455 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
456 operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
457 {
458 return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
459 }
460 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
461 inline BOOST_MP_CXX14_CONSTEXPR 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
462 operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
463 {
464 return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
465 }
466 template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
467 inline BOOST_MP_CXX14_CONSTEXPR 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
468 operator/(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
469 {
470 return detail::expression<detail::divides, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
471 }
472 //
473 // Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
474 //
475 template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
476 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >
477 operator/(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
478 {
479 return detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >(
480 detail::expression<detail::divides, number<B, ET>, Arg1>(a, b.left_ref()));
481 }
482 template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
483 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >
484 operator/(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
485 {
486 return detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >(
487 detail::expression<detail::divides, Arg1, number<B, ET> >(a.left_ref(), b));
488 }
489 template <class B>
490 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >
491 operator/(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
492 {
493 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >(
494 detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
495 }
496 template <class B>
497 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >
498 operator/(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
499 {
500 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >(
501 detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a.left_ref(), b));
502 }
503 template <class B, class V>
504 inline BOOST_MP_CXX14_CONSTEXPR 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
505 operator/(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
506 {
507 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, V> >(
508 detail::expression<detail::divide_immediates, number<B, et_on>, V>(a.left_ref(), b));
509 }
510 template <class B, class B2, expression_template_option ET>
511 inline BOOST_MP_CXX14_CONSTEXPR 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
512 operator/(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
513 {
514 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > >(
515 detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
516 }
517 template <class V, class B>
518 inline BOOST_MP_CXX14_CONSTEXPR 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
519 operator/(const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
520 {
521 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, V, number<B, et_on> > >(
522 detail::expression<detail::divide_immediates, V, number<B, et_on> >(a, b.left_ref()));
523 }
524 template <class B2, expression_template_option ET, class B>
525 inline BOOST_MP_CXX14_CONSTEXPR 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
526 operator/(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
527 {
528 return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > >(
529 detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref()));
530 }
531 //
532 // Modulus:
533 //
534 template <class B>
535 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer,
536 detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> > >::type
537 operator%(const number<B, et_on>& a, const number<B, et_on>& b)
538 {
539 return detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> >(a, b);
540 }
541 template <class B, class V>
542 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
543 detail::expression<detail::modulus_immediates, number<B, et_on>, V> >::type
544 operator%(const number<B, et_on>& a, const V& b)
545 {
546 return detail::expression<detail::modulus_immediates, number<B, et_on>, V>(a, b);
547 }
548 template <class V, class B>
549 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
550 detail::expression<detail::modulus_immediates, V, number<B, et_on> > >::type
551 operator%(const V& a, const number<B, et_on>& b)
552 {
553 return detail::expression<detail::modulus_immediates, V, number<B, et_on> >(a, b);
554 }
555 template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
556 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer,
557 detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
558 operator%(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
559 {
560 return detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
561 }
562 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
563 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer,
564 detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
565 operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
566 {
567 return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
568 }
569 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
570 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
571 detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
572 operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
573 {
574 return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
575 }
576 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
577 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
578 detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
579 operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
580 {
581 return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
582 }
583 template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
584 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
585 detail::expression<detail::modulus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
586 operator%(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
587 {
588 return detail::expression<detail::modulus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
589 }
590 //
591 // Left shift:
592 //
593 template <class B, class I>
594 inline BOOST_MP_CXX14_CONSTEXPR 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
595 operator<<(const number<B, et_on>& a, const I& b)
596 {
597 return detail::expression<detail::shift_left, number<B, et_on>, I>(a, b);
598 }
599 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
600 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_integral<I>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
601 detail::expression<detail::shift_left, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
602 operator<<(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
603 {
604 return detail::expression<detail::shift_left, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I>(a, b);
605 }
606 //
607 // Right shift:
608 //
609 template <class B, class I>
610 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer),
611 detail::expression<detail::shift_right, number<B, et_on>, I> >::type
612 operator>>(const number<B, et_on>& a, const I& b)
613 {
614 return detail::expression<detail::shift_right, number<B, et_on>, I>(a, b);
615 }
616 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
617 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_integral<I>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
618 detail::expression<detail::shift_right, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
619 operator>>(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
620 {
621 return detail::expression<detail::shift_right, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I>(a, b);
622 }
623 //
624 // Bitwise AND:
625 //
626 template <class B>
627 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer,
628 detail::expression<detail::bitwise_and_immediates, number<B, et_on>, number<B, et_on> > >::type
629 operator&(const number<B, et_on>& a, const number<B, et_on>& b)
630 {
631 return detail::expression<detail::bitwise_and_immediates, number<B, et_on>, number<B, et_on> >(a, b);
632 }
633 template <class B, class V>
634 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
635 detail::expression<detail::bitwise_and_immediates, number<B, et_on>, V> >::type
636 operator&(const number<B, et_on>& a, const V& b)
637 {
638 return detail::expression<detail::bitwise_and_immediates, number<B, et_on>, V>(a, b);
639 }
640 template <class V, class B>
641 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
642 detail::expression<detail::bitwise_and_immediates, V, number<B, et_on> > >::type
643 operator&(const V& a, const number<B, et_on>& b)
644 {
645 return detail::expression<detail::bitwise_and_immediates, V, number<B, et_on> >(a, b);
646 }
647 template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
648 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer,
649 detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
650 operator&(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
651 {
652 return detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
653 }
654 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
655 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer,
656 detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
657 operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
658 {
659 return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
660 }
661 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
662 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
663 detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
664 operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
665 {
666 return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
667 }
668 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
669 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
670 detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
671 operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
672 {
673 return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
674 }
675 template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
676 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
677 detail::expression<detail::bitwise_and, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
678 operator&(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
679 {
680 return detail::expression<detail::bitwise_and, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
681 }
682 //
683 // Bitwise OR:
684 //
685 template <class B>
686 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer,
687 detail::expression<detail::bitwise_or_immediates, number<B, et_on>, number<B, et_on> > >::type
688 operator|(const number<B, et_on>& a, const number<B, et_on>& b)
689 {
690 return detail::expression<detail::bitwise_or_immediates, number<B, et_on>, number<B, et_on> >(a, b);
691 }
692 template <class B, class V>
693 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
694 detail::expression<detail::bitwise_or_immediates, number<B, et_on>, V> >::type
695 operator|(const number<B, et_on>& a, const V& b)
696 {
697 return detail::expression<detail::bitwise_or_immediates, number<B, et_on>, V>(a, b);
698 }
699 template <class V, class B>
700 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
701 detail::expression<detail::bitwise_or_immediates, V, number<B, et_on> > >::type
702 operator|(const V& a, const number<B, et_on>& b)
703 {
704 return detail::expression<detail::bitwise_or_immediates, V, number<B, et_on> >(a, b);
705 }
706 template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
707 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer,
708 detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
709 operator|(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
710 {
711 return detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
712 }
713 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
714 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer,
715 detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
716 operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
717 {
718 return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
719 }
720 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
721 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
722 detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
723 operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
724 {
725 return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
726 }
727 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
728 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
729 detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
730 operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
731 {
732 return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
733 }
734 template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
735 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
736 detail::expression<detail::bitwise_or, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
737 operator|(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
738 {
739 return detail::expression<detail::bitwise_or, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
740 }
741 //
742 // Bitwise XOR:
743 //
744 template <class B>
745 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer,
746 detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, number<B, et_on> > >::type
747 operator^(const number<B, et_on>& a, const number<B, et_on>& b)
748 {
749 return detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, number<B, et_on> >(a, b);
750 }
751 template <class B, class V>
752 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
753 detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, V> >::type
754 operator^(const number<B, et_on>& a, const V& b)
755 {
756 return detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, V>(a, b);
757 }
758 template <class V, class B>
759 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
760 detail::expression<detail::bitwise_xor_immediates, V, number<B, et_on> > >::type
761 operator^(const V& a, const number<B, et_on>& b)
762 {
763 return detail::expression<detail::bitwise_xor_immediates, V, number<B, et_on> >(a, b);
764 }
765 template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
766 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer,
767 detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
768 operator^(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
769 {
770 return detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
771 }
772 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
773 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer,
774 detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
775 operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
776 {
777 return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
778 }
779 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
780 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
781 detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
782 operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
783 {
784 return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
785 }
786 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
787 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
788 detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
789 operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
790 {
791 return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
792 }
793 template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
794 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer), detail::expression<detail::bitwise_xor, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
795 operator^(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
796 {
797 return detail::expression<detail::bitwise_xor, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
798 }
799
800 }} // namespace boost::multiprecision
801
802 #endif