et_ops.hpp 60 KB

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