et_ops.hpp 98 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449
  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 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 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. static_assert(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. // rvalue ops:
  31. template <class B>
  32. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on> operator-(number<B, et_on>&& v)
  33. {
  34. static_assert(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
  35. return detail::expression<detail::negate, number<B, et_on> >(v);
  36. }
  37. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  38. 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)
  39. {
  40. static_assert((is_signed_number<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value), "Negating an unsigned type results in ill-defined behavior.");
  41. return detail::expression<detail::negate, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(v);
  42. }
  43. template <class B>
  44. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  45. detail::expression<detail::complement_immediates, number<B, et_on> > >::type
  46. operator~(const number<B, et_on>& v) { return detail::expression<detail::complement_immediates, number<B, et_on> >(v); }
  47. template <class B>
  48. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  49. number<B, et_on> >::type
  50. operator~(number<B, et_on>&& v) { return detail::expression<detail::complement_immediates, number<B, et_on> >(v); }
  51. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  52. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
  53. detail::expression<detail::bitwise_complement, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  54. operator~(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return detail::expression<detail::bitwise_complement, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(v); }
  55. //
  56. // Then addition:
  57. //
  58. template <class B>
  59. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >
  60. operator+(const number<B, et_on>& a, const number<B, et_on>& b)
  61. {
  62. return detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  63. }
  64. template <class B>
  65. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  66. operator+(number<B, et_on>&& a, const number<B, et_on>& b)
  67. {
  68. return detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  69. }
  70. template <class B>
  71. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  72. operator+(const number<B, et_on>& a, number<B, et_on>&& b)
  73. {
  74. return detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  75. }
  76. template <class B>
  77. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  78. operator+(number<B, et_on>&& a, number<B, et_on>&& b)
  79. {
  80. return detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  81. }
  82. template <class B, class V>
  83. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, detail::expression<detail::add_immediates, number<B, et_on>, V> >::type
  84. operator+(const number<B, et_on>& a, const V& b)
  85. {
  86. return detail::expression<detail::add_immediates, number<B, et_on>, V>(a, b);
  87. }
  88. template <class B, class V>
  89. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, number<B, et_on> >::type
  90. operator+(number<B, et_on>&& a, const V& b)
  91. {
  92. return detail::expression<detail::add_immediates, number<B, et_on>, V>(a, b);
  93. }
  94. template <class V, class B>
  95. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::add_immediates, V, number<B, et_on> > >::type
  96. operator+(const V& a, const number<B, et_on>& b)
  97. {
  98. return detail::expression<detail::add_immediates, V, number<B, et_on> >(a, b);
  99. }
  100. template <class V, class B>
  101. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, number<B, et_on> >::type
  102. operator+(const V& a, number<B, et_on>&& b)
  103. {
  104. return detail::expression<detail::add_immediates, V, number<B, et_on> >(a, b);
  105. }
  106. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  107. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
  108. operator+(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  109. {
  110. return detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  111. }
  112. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  113. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type
  114. operator+(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  115. {
  116. return detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  117. }
  118. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  119. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
  120. operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  121. {
  122. return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
  123. }
  124. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  125. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type
  126. operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  127. {
  128. return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
  129. }
  130. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
  131. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
  132. operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
  133. {
  134. return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
  135. }
  136. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
  137. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
  138. operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  139. {
  140. return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
  141. }
  142. template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  143. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::plus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  144. operator+(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  145. {
  146. return detail::expression<detail::plus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  147. }
  148. //
  149. // Fused multiply add:
  150. //
  151. template <class V, class Arg1, class Arg2, class Arg3, class Arg4>
  152. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value,
  153. 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
  154. operator+(const V& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
  155. {
  156. 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);
  157. }
  158. template <class Arg1, class Arg2, class Arg3, class Arg4, class V>
  159. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value,
  160. 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
  161. operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  162. {
  163. 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);
  164. }
  165. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  166. 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> >
  167. operator+(const number<B, ET>& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
  168. {
  169. 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);
  170. }
  171. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  172. inline BOOST_MP_CXX14_CONSTEXPR typename 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> >::result_type
  173. operator+(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
  174. {
  175. 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);
  176. }
  177. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  178. 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> >
  179. operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  180. {
  181. 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);
  182. }
  183. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  184. inline BOOST_MP_CXX14_CONSTEXPR typename 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> >::result_type
  185. operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  186. {
  187. 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);
  188. }
  189. //
  190. // Fused multiply subtract:
  191. //
  192. template <class V, class Arg1, class Arg2, class Arg3, class Arg4>
  193. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value,
  194. 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
  195. operator-(const V& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
  196. {
  197. 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));
  198. }
  199. template <class Arg1, class Arg2, class Arg3, class Arg4, class V>
  200. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::result_type>::value,
  201. 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
  202. operator-(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  203. {
  204. 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);
  205. }
  206. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  207. 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> > >
  208. operator-(const number<B, ET>& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
  209. {
  210. 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));
  211. }
  212. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  213. inline BOOST_MP_CXX14_CONSTEXPR typename 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> > >::result_type
  214. operator-(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
  215. {
  216. 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));
  217. }
  218. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  219. 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> >
  220. operator-(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  221. {
  222. 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);
  223. }
  224. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  225. inline BOOST_MP_CXX14_CONSTEXPR typename 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> >::result_type
  226. operator-(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  227. {
  228. 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);
  229. }
  230. //
  231. // Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
  232. //
  233. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  234. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, number<B, ET>, Arg1>
  235. operator+(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  236. {
  237. return detail::expression<detail::minus, number<B, ET>, Arg1>(a, b.left_ref());
  238. }
  239. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  240. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type
  241. operator+(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  242. {
  243. return detail::expression<detail::minus, number<B, ET>, Arg1>(a, b.left_ref());
  244. }
  245. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  246. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, number<B, ET>, Arg1>
  247. operator+(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  248. {
  249. return detail::expression<detail::minus, number<B, ET>, Arg1>(b, a.left_ref());
  250. }
  251. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  252. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type
  253. operator+(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  254. {
  255. return detail::expression<detail::minus, number<B, ET>, Arg1>(b, a.left_ref());
  256. }
  257. template <class B>
  258. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
  259. operator+(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  260. {
  261. return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref());
  262. }
  263. template <class B>
  264. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >::result_type
  265. operator+(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  266. {
  267. return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref());
  268. }
  269. template <class B>
  270. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
  271. operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
  272. {
  273. return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref());
  274. }
  275. template <class B>
  276. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >::result_type
  277. operator+(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
  278. {
  279. return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref());
  280. }
  281. template <class B, class V>
  282. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::subtract_immediates, V, number<B, et_on> > >::type
  283. operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
  284. {
  285. return detail::expression<detail::subtract_immediates, V, number<B, et_on> >(b, a.left_ref());
  286. }
  287. template <class B, class B2, expression_template_option ET>
  288. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> > >::type
  289. operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
  290. {
  291. return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(b, a.left_ref());
  292. }
  293. template <class B, class B2, expression_template_option ET>
  294. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >::result_type>::type
  295. operator+(const detail::expression<detail::negate, number<B, et_on> >& a, number<B2, ET>&& b)
  296. {
  297. return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(b, a.left_ref());
  298. }
  299. template <class B2, expression_template_option ET, class B>
  300. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> > >::type
  301. operator+(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  302. {
  303. return detail::expression<detail::subtract_immediates, number<B2, ET>, 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 std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >::result_type>::type
  307. operator+(number<B2, ET>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  308. {
  309. return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
  310. }
  311. template <class B>
  312. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >
  313. operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  314. {
  315. 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()));
  316. }
  317. //
  318. // Subtraction:
  319. //
  320. template <class B>
  321. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
  322. operator-(const number<B, et_on>& a, const number<B, et_on>& b)
  323. {
  324. return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  325. }
  326. template <class B>
  327. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  328. operator-(number<B, et_on>&& a, const number<B, et_on>& b)
  329. {
  330. return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  331. }
  332. template <class B>
  333. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  334. operator-(const number<B, et_on>& a, number<B, et_on>&& b)
  335. {
  336. return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  337. }
  338. template <class B>
  339. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  340. operator-(number<B, et_on>&& a, number<B, et_on>&& b)
  341. {
  342. return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  343. }
  344. template <class B, class V>
  345. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, detail::expression<detail::subtract_immediates, number<B, et_on>, V> >::type
  346. operator-(const number<B, et_on>& a, const V& b)
  347. {
  348. return detail::expression<detail::subtract_immediates, number<B, et_on>, V>(a, b);
  349. }
  350. template <class B, class V>
  351. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, number<B, et_on> >::type
  352. operator-(number<B, et_on>&& a, const V& b)
  353. {
  354. return detail::expression<detail::subtract_immediates, number<B, et_on>, V>(a, b);
  355. }
  356. template <class V, class B>
  357. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::subtract_immediates, V, number<B, et_on> > >::type
  358. operator-(const V& a, const number<B, et_on>& b)
  359. {
  360. return detail::expression<detail::subtract_immediates, V, number<B, et_on> >(a, b);
  361. }
  362. template <class V, class B>
  363. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, number<B, et_on> >::type
  364. operator-(const V& a, number<B, et_on>&& b)
  365. {
  366. return detail::expression<detail::subtract_immediates, V, number<B, et_on> >(a, b);
  367. }
  368. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  369. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
  370. operator-(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  371. {
  372. return detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  373. }
  374. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  375. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type
  376. operator-(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  377. {
  378. return detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  379. }
  380. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  381. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
  382. operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  383. {
  384. return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
  385. }
  386. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  387. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type
  388. operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  389. {
  390. return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
  391. }
  392. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
  393. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
  394. operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
  395. {
  396. return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
  397. }
  398. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
  399. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
  400. operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  401. {
  402. return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
  403. }
  404. template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  405. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::minus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  406. operator-(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  407. {
  408. return detail::expression<detail::minus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  409. }
  410. //
  411. // Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
  412. //
  413. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  414. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::plus, number<B, ET>, Arg1>
  415. operator-(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  416. {
  417. return detail::expression<detail::plus, number<B, ET>, Arg1>(a, b.left_ref());
  418. }
  419. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  420. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type
  421. operator-(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  422. {
  423. return detail::expression<detail::plus, number<B, ET>, Arg1>(a, b.left_ref());
  424. }
  425. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  426. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >
  427. operator-(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  428. {
  429. return detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >(
  430. detail::expression<detail::plus, number<B, ET>, Arg1>(b, a.left_ref()));
  431. }
  432. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  433. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type
  434. operator-(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  435. {
  436. return detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >(
  437. detail::expression<detail::plus, number<B, ET>, Arg1>(b, a.left_ref()));
  438. }
  439. template <class B>
  440. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >
  441. operator-(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  442. {
  443. return detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref());
  444. }
  445. template <class B>
  446. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >::result_type
  447. operator-(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  448. {
  449. return detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref());
  450. }
  451. template <class B>
  452. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >
  453. operator-(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
  454. {
  455. return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >(
  456. detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
  457. }
  458. template <class B>
  459. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type
  460. operator-(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
  461. {
  462. return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >(
  463. detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
  464. }
  465. template <class B, class V>
  466. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, V> > >::type
  467. operator-(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
  468. {
  469. 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));
  470. }
  471. template <class B, class B2, expression_template_option ET>
  472. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B2, ET> > > >::type
  473. operator-(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
  474. {
  475. 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));
  476. }
  477. template <class B, class B2, expression_template_option ET>
  478. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B2, ET> > >::result_type>::type
  479. operator-(const detail::expression<detail::negate, number<B, et_on> >& a, number<B2, ET>&& b)
  480. {
  481. 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));
  482. }
  483. template <class V, class B>
  484. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::add_immediates, V, number<B, et_on> > >::type
  485. operator-(const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  486. {
  487. return detail::expression<detail::add_immediates, V, number<B, et_on> >(a, b.left_ref());
  488. }
  489. template <class B2, expression_template_option ET, class B>
  490. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> > >::type
  491. operator-(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  492. {
  493. return detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
  494. }
  495. template <class B2, expression_template_option ET, class B>
  496. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> >::result_type>::type
  497. operator-(number<B2, ET>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  498. {
  499. return detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
  500. }
  501. //
  502. // Multiplication:
  503. //
  504. template <class B>
  505. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >
  506. operator*(const number<B, et_on>& a, const number<B, et_on>& b)
  507. {
  508. return detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  509. }
  510. template <class B>
  511. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  512. operator*(number<B, et_on>&& a, const number<B, et_on>& b)
  513. {
  514. return detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  515. }
  516. template <class B>
  517. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  518. operator*(const number<B, et_on>& a, number<B, et_on>&& b)
  519. {
  520. return detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  521. }
  522. template <class B>
  523. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  524. operator*(number<B, et_on>&& a, number<B, et_on>&& b)
  525. {
  526. return detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  527. }
  528. template <class B, class V>
  529. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, detail::expression<detail::multiply_immediates, number<B, et_on>, V> >::type
  530. operator*(const number<B, et_on>& a, const V& b)
  531. {
  532. return detail::expression<detail::multiply_immediates, number<B, et_on>, V>(a, b);
  533. }
  534. template <class B, class V>
  535. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, number<B, et_on> >::type
  536. operator*(number<B, et_on>&& a, const V& b)
  537. {
  538. return detail::expression<detail::multiply_immediates, number<B, et_on>, V>(a, b);
  539. }
  540. template <class V, class B>
  541. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::multiply_immediates, V, number<B, et_on> > >::type
  542. operator*(const V& a, const number<B, et_on>& b)
  543. {
  544. return detail::expression<detail::multiply_immediates, V, number<B, et_on> >(a, b);
  545. }
  546. template <class V, class B>
  547. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, number<B, et_on> >::type
  548. operator*(const V& a, number<B, et_on>&& b)
  549. {
  550. return detail::expression<detail::multiply_immediates, V, number<B, et_on> >(a, b);
  551. }
  552. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  553. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
  554. operator*(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  555. {
  556. return detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  557. }
  558. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  559. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type
  560. operator*(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  561. {
  562. return detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  563. }
  564. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  565. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
  566. operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  567. {
  568. return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
  569. }
  570. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  571. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type
  572. operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  573. {
  574. return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
  575. }
  576. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
  577. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
  578. operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
  579. {
  580. return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
  581. }
  582. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
  583. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
  584. operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  585. {
  586. return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
  587. }
  588. template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  589. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::multiplies, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  590. operator*(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  591. {
  592. return detail::expression<detail::multiplies, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  593. }
  594. //
  595. // Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
  596. //
  597. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  598. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >
  599. operator*(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  600. {
  601. return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
  602. detail::expression<detail::multiplies, number<B, ET>, Arg1>(a, b.left_ref()));
  603. }
  604. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  605. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >::result_type
  606. operator*(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  607. {
  608. return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
  609. detail::expression<detail::multiplies, number<B, ET>, Arg1>(a, b.left_ref()));
  610. }
  611. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  612. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >
  613. operator*(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  614. {
  615. return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
  616. detail::expression<detail::multiplies, number<B, ET>, Arg1>(b, a.left_ref()));
  617. }
  618. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  619. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >::result_type
  620. operator*(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  621. {
  622. return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
  623. detail::expression<detail::multiplies, number<B, ET>, Arg1>(b, a.left_ref()));
  624. }
  625. template <class B>
  626. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >
  627. operator*(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  628. {
  629. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
  630. detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
  631. }
  632. template <class B>
  633. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type
  634. operator*(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  635. {
  636. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
  637. detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
  638. }
  639. template <class B>
  640. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >
  641. operator*(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
  642. {
  643. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
  644. detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
  645. }
  646. template <class B>
  647. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type
  648. operator*(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
  649. {
  650. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
  651. detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
  652. }
  653. template <class B, class V>
  654. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V> > >::type
  655. operator*(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
  656. {
  657. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V> >(
  658. detail::expression<detail::multiply_immediates, number<B, et_on>, V>(a.left_ref(), b));
  659. }
  660. template <class B, class B2, expression_template_option ET>
  661. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > > >::type
  662. operator*(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
  663. {
  664. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
  665. detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
  666. }
  667. template <class B, class B2, expression_template_option ET>
  668. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >::result_type>::type
  669. operator*(const detail::expression<detail::negate, number<B, et_on> >& a, number<B2, ET>&& b)
  670. {
  671. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
  672. detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
  673. }
  674. template <class V, class B>
  675. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V> > >::type
  676. operator*(const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  677. {
  678. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V> >(
  679. detail::expression<detail::multiply_immediates, number<B, et_on>, V>(b.left_ref(), a));
  680. }
  681. template <class B2, expression_template_option ET, class B>
  682. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > > >::type
  683. operator*(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  684. {
  685. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
  686. detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(b.left_ref(), a));
  687. }
  688. template <class B2, expression_template_option ET, class B>
  689. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >::result_type>::type
  690. operator*(number<B2, ET>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  691. {
  692. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
  693. detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(b.left_ref(), a));
  694. }
  695. //
  696. // Division:
  697. //
  698. template <class B>
  699. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >
  700. operator/(const number<B, et_on>& a, const number<B, et_on>& b)
  701. {
  702. return detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  703. }
  704. template <class B>
  705. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  706. operator/(number<B, et_on>&& a, const number<B, et_on>& b)
  707. {
  708. return detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  709. }
  710. template <class B>
  711. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  712. operator/(const number<B, et_on>& a, number<B, et_on>&& b)
  713. {
  714. return detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  715. }
  716. template <class B>
  717. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  718. operator/(number<B, et_on>&& a, number<B, et_on>&& b)
  719. {
  720. return detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  721. }
  722. template <class B, class V>
  723. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, detail::expression<detail::divide_immediates, number<B, et_on>, V> >::type
  724. operator/(const number<B, et_on>& a, const V& b)
  725. {
  726. return detail::expression<detail::divide_immediates, number<B, et_on>, V>(a, b);
  727. }
  728. template <class B, class V>
  729. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && !is_equivalent_number_type<V, number<B, et_on> >::value, number<B, et_on> >::type
  730. operator/(number<B, et_on>&& a, const V& b)
  731. {
  732. return detail::expression<detail::divide_immediates, number<B, et_on>, V>(a, b);
  733. }
  734. template <class V, class B>
  735. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::divide_immediates, V, number<B, et_on> > >::type
  736. operator/(const V& a, const number<B, et_on>& b)
  737. {
  738. return detail::expression<detail::divide_immediates, V, number<B, et_on> >(a, b);
  739. }
  740. template <class V, class B>
  741. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, number<B, et_on> >::type
  742. operator/(const V& a, number<B, et_on>&& b)
  743. {
  744. return detail::expression<detail::divide_immediates, V, number<B, et_on> >(a, b);
  745. }
  746. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  747. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
  748. operator/(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  749. {
  750. return detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  751. }
  752. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  753. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type
  754. operator/(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  755. {
  756. return detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  757. }
  758. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  759. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
  760. operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  761. {
  762. return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
  763. }
  764. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  765. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type
  766. operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  767. {
  768. return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
  769. }
  770. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
  771. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
  772. operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
  773. {
  774. return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
  775. }
  776. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
  777. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
  778. operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  779. {
  780. return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
  781. }
  782. template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  783. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value, detail::expression<detail::divides, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  784. operator/(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  785. {
  786. return detail::expression<detail::divides, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  787. }
  788. //
  789. // Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
  790. //
  791. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  792. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >
  793. operator/(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  794. {
  795. return detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >(
  796. detail::expression<detail::divides, number<B, ET>, Arg1>(a, b.left_ref()));
  797. }
  798. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  799. inline typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type
  800. operator/(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  801. {
  802. return detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >(
  803. detail::expression<detail::divides, number<B, ET>, Arg1>(a, b.left_ref()));
  804. }
  805. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  806. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >
  807. operator/(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  808. {
  809. return detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >(
  810. detail::expression<detail::divides, Arg1, number<B, ET> >(a.left_ref(), b));
  811. }
  812. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  813. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >::result_type
  814. operator/(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  815. {
  816. return detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >(
  817. detail::expression<detail::divides, Arg1, number<B, ET> >(a.left_ref(), b));
  818. }
  819. template <class B>
  820. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >
  821. operator/(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  822. {
  823. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >(
  824. detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
  825. }
  826. template <class B>
  827. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >::result_type
  828. operator/(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  829. {
  830. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >(
  831. detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
  832. }
  833. template <class B>
  834. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >
  835. operator/(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
  836. {
  837. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >(
  838. detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a.left_ref(), b));
  839. }
  840. template <class B>
  841. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >::result_type
  842. operator/(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
  843. {
  844. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >(
  845. detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a.left_ref(), b));
  846. }
  847. template <class B, class V>
  848. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, V> > >::type
  849. operator/(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
  850. {
  851. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, V> >(
  852. detail::expression<detail::divide_immediates, number<B, et_on>, V>(a.left_ref(), b));
  853. }
  854. template <class B, class B2, expression_template_option ET>
  855. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > > >::type
  856. operator/(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
  857. {
  858. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > >(
  859. detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
  860. }
  861. template <class B, class B2, expression_template_option ET>
  862. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, typename detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > >::result_type>::type
  863. operator/(const detail::expression<detail::negate, number<B, et_on> >& a, number<B2, ET>&& b)
  864. {
  865. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > >(
  866. detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
  867. }
  868. template <class V, class B>
  869. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::divide_immediates, V, number<B, et_on> > > >::type
  870. operator/(const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  871. {
  872. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, V, number<B, et_on> > >(
  873. detail::expression<detail::divide_immediates, V, number<B, et_on> >(a, b.left_ref()));
  874. }
  875. template <class B2, expression_template_option ET, class B>
  876. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, number<B, et_on> >::value, detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > > >::type
  877. operator/(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  878. {
  879. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > >(
  880. detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref()));
  881. }
  882. template <class B2, expression_template_option ET, class B>
  883. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<number<B2, ET>, typename detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > >::result_type>::value, number<B, et_on> >::type
  884. operator/(number<B2, ET>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  885. {
  886. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > >(
  887. detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref()));
  888. }
  889. //
  890. // Modulus:
  891. //
  892. template <class B>
  893. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  894. detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> > >::type
  895. operator%(const number<B, et_on>& a, const number<B, et_on>& b)
  896. {
  897. return detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  898. }
  899. template <class B>
  900. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  901. number<B, et_on> >::type
  902. operator%(number<B, et_on>&& a, const number<B, et_on>& b)
  903. {
  904. return detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  905. }
  906. template <class B>
  907. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  908. number<B, et_on> >::type
  909. operator%(const number<B, et_on>& a, number<B, et_on>&& b)
  910. {
  911. return detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  912. }
  913. template <class B>
  914. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  915. number<B, et_on> >::type
  916. operator%(number<B, et_on>&& a, number<B, et_on>&& b)
  917. {
  918. return detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  919. }
  920. template <class B, class V>
  921. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, number<B, et_on> >::value,
  922. detail::expression<detail::modulus_immediates, number<B, et_on>, V> >::type
  923. operator%(const number<B, et_on>& a, const V& b)
  924. {
  925. return detail::expression<detail::modulus_immediates, number<B, et_on>, V>(a, b);
  926. }
  927. template <class B, class V>
  928. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, number<B, et_on> >::value,
  929. number<B, et_on> >::type
  930. operator%(number<B, et_on>&& a, const V& b)
  931. {
  932. return detail::expression<detail::modulus_immediates, number<B, et_on>, V>(a, b);
  933. }
  934. template <class V, class B>
  935. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
  936. detail::expression<detail::modulus_immediates, V, number<B, et_on> > >::type
  937. operator%(const V& a, const number<B, et_on>& b)
  938. {
  939. return detail::expression<detail::modulus_immediates, V, number<B, et_on> >(a, b);
  940. }
  941. template <class V, class B>
  942. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
  943. number<B, et_on> >::type
  944. operator%(const V& a, number<B, et_on>&& b)
  945. {
  946. return detail::expression<detail::modulus_immediates, V, number<B, et_on> >(a, b);
  947. }
  948. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  949. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  950. detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  951. operator%(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  952. {
  953. return detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  954. }
  955. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  956. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  957. typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
  958. operator%(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  959. {
  960. return detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  961. }
  962. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  963. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  964. detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
  965. operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
  966. {
  967. return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
  968. }
  969. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  970. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  971. typename detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type >::type
  972. operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
  973. {
  974. return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
  975. }
  976. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
  977. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
  978. detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
  979. operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
  980. {
  981. return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
  982. }
  983. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
  984. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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),
  985. detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
  986. operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  987. {
  988. return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
  989. }
  990. template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  991. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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),
  992. detail::expression<detail::modulus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  993. operator%(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  994. {
  995. return detail::expression<detail::modulus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  996. }
  997. //
  998. // Left shift:
  999. //
  1000. template <class B, class I>
  1001. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer), detail::expression<detail::shift_left, number<B, et_on>, I> >::type
  1002. operator<<(const number<B, et_on>& a, const I& b)
  1003. {
  1004. return detail::expression<detail::shift_left, number<B, et_on>, I>(a, b);
  1005. }
  1006. template <class B, class I>
  1007. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_on> >::type
  1008. operator<<(number<B, et_on>&& a, const I& b)
  1009. {
  1010. return detail::expression<detail::shift_left, number<B, et_on>, I>(a, b);
  1011. }
  1012. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
  1013. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
  1014. detail::expression<detail::shift_left, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
  1015. operator<<(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
  1016. {
  1017. return detail::expression<detail::shift_left, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I>(a, b);
  1018. }
  1019. //
  1020. // Right shift:
  1021. //
  1022. template <class B, class I>
  1023. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer),
  1024. detail::expression<detail::shift_right, number<B, et_on>, I> >::type
  1025. operator>>(const number<B, et_on>& a, const I& b)
  1026. {
  1027. return detail::expression<detail::shift_right, number<B, et_on>, I>(a, b);
  1028. }
  1029. template <class B, class I>
  1030. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer),
  1031. number<B, et_on> >::type
  1032. operator>>(number<B, et_on>&& a, const I& b)
  1033. {
  1034. return detail::expression<detail::shift_right, number<B, et_on>, I>(a, b);
  1035. }
  1036. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
  1037. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer),
  1038. detail::expression<detail::shift_right, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
  1039. operator>>(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
  1040. {
  1041. return detail::expression<detail::shift_right, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I>(a, b);
  1042. }
  1043. //
  1044. // Bitwise AND:
  1045. //
  1046. template <class B>
  1047. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1048. detail::expression<detail::bitwise_and_immediates, number<B, et_on>, number<B, et_on> > >::type
  1049. operator&(const number<B, et_on>& a, const number<B, et_on>& b)
  1050. {
  1051. return detail::expression<detail::bitwise_and_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  1052. }
  1053. template <class B>
  1054. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1055. number<B, et_on> >::type
  1056. operator&(number<B, et_on>&& a, const number<B, et_on>& b)
  1057. {
  1058. return detail::expression<detail::bitwise_and_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  1059. }
  1060. template <class B>
  1061. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1062. number<B, et_on> >::type
  1063. operator&(const number<B, et_on>& a, number<B, et_on>&& b)
  1064. {
  1065. return detail::expression<detail::bitwise_and_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  1066. }
  1067. template <class B>
  1068. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1069. number<B, et_on> >::type
  1070. operator&(number<B, et_on>&& a, number<B, et_on>&& b)
  1071. {
  1072. return detail::expression<detail::bitwise_and_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  1073. }
  1074. template <class B, class V>
  1075. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
  1076. detail::expression<detail::bitwise_and_immediates, number<B, et_on>, V> >::type
  1077. operator&(const number<B, et_on>& a, const V& b)
  1078. {
  1079. return detail::expression<detail::bitwise_and_immediates, number<B, et_on>, V>(a, b);
  1080. }
  1081. template <class B, class V>
  1082. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
  1083. number<B, et_on> >::type
  1084. operator&(number<B, et_on>&& a, const V& b)
  1085. {
  1086. return detail::expression<detail::bitwise_and_immediates, number<B, et_on>, V>(a, b);
  1087. }
  1088. template <class V, class B>
  1089. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
  1090. detail::expression<detail::bitwise_and_immediates, V, number<B, et_on> > >::type
  1091. operator&(const V& a, const number<B, et_on>& b)
  1092. {
  1093. return detail::expression<detail::bitwise_and_immediates, V, number<B, et_on> >(a, b);
  1094. }
  1095. template <class V, class B>
  1096. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
  1097. number<B, et_on> >::type
  1098. operator&(const V& a, number<B, et_on>&& b)
  1099. {
  1100. return detail::expression<detail::bitwise_and_immediates, V, number<B, et_on> >(a, b);
  1101. }
  1102. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1103. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1104. detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  1105. operator&(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1106. {
  1107. return detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1108. }
  1109. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1110. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1111. typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
  1112. operator&(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1113. {
  1114. return detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1115. }
  1116. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  1117. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1118. detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
  1119. operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
  1120. {
  1121. return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
  1122. }
  1123. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  1124. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1125. typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type >::type
  1126. operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
  1127. {
  1128. return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
  1129. }
  1130. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
  1131. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
  1132. detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
  1133. operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
  1134. {
  1135. return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
  1136. }
  1137. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
  1138. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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),
  1139. detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
  1140. operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  1141. {
  1142. return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
  1143. }
  1144. template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1145. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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),
  1146. detail::expression<detail::bitwise_and, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  1147. operator&(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1148. {
  1149. return detail::expression<detail::bitwise_and, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1150. }
  1151. //
  1152. // Bitwise OR:
  1153. //
  1154. template <class B>
  1155. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1156. detail::expression<detail::bitwise_or_immediates, number<B, et_on>, number<B, et_on> > >::type
  1157. operator|(const number<B, et_on>& a, const number<B, et_on>& b)
  1158. {
  1159. return detail::expression<detail::bitwise_or_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  1160. }
  1161. template <class B>
  1162. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1163. number<B, et_on> >::type
  1164. operator|(number<B, et_on>&& a, const number<B, et_on>& b)
  1165. {
  1166. return detail::expression<detail::bitwise_or_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  1167. }
  1168. template <class B>
  1169. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1170. number<B, et_on> >::type
  1171. operator|(const number<B, et_on>& a, number<B, et_on>&& b)
  1172. {
  1173. return detail::expression<detail::bitwise_or_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  1174. }
  1175. template <class B>
  1176. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1177. number<B, et_on> >::type
  1178. operator|(number<B, et_on>&& a, number<B, et_on>&& b)
  1179. {
  1180. return detail::expression<detail::bitwise_or_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  1181. }
  1182. template <class B, class V>
  1183. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
  1184. detail::expression<detail::bitwise_or_immediates, number<B, et_on>, V> >::type
  1185. operator|(const number<B, et_on>& a, const V& b)
  1186. {
  1187. return detail::expression<detail::bitwise_or_immediates, number<B, et_on>, V>(a, b);
  1188. }
  1189. template <class B, class V>
  1190. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
  1191. number<B, et_on> >::type
  1192. operator|(number<B, et_on>&& a, const V& b)
  1193. {
  1194. return detail::expression<detail::bitwise_or_immediates, number<B, et_on>, V>(a, b);
  1195. }
  1196. template <class V, class B>
  1197. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
  1198. detail::expression<detail::bitwise_or_immediates, V, number<B, et_on> > >::type
  1199. operator|(const V& a, const number<B, et_on>& b)
  1200. {
  1201. return detail::expression<detail::bitwise_or_immediates, V, number<B, et_on> >(a, b);
  1202. }
  1203. template <class V, class B>
  1204. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
  1205. number<B, et_on> >::type
  1206. operator|(const V& a, number<B, et_on>&& b)
  1207. {
  1208. return detail::expression<detail::bitwise_or_immediates, V, number<B, et_on> >(a, b);
  1209. }
  1210. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1211. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1212. detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  1213. operator|(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1214. {
  1215. return detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1216. }
  1217. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1218. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1219. typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
  1220. operator|(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1221. {
  1222. return detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1223. }
  1224. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  1225. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1226. detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
  1227. operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
  1228. {
  1229. return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
  1230. }
  1231. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  1232. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1233. typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
  1234. operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
  1235. {
  1236. return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
  1237. }
  1238. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
  1239. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
  1240. detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
  1241. operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
  1242. {
  1243. return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
  1244. }
  1245. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
  1246. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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),
  1247. detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
  1248. operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  1249. {
  1250. return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
  1251. }
  1252. template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1253. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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),
  1254. detail::expression<detail::bitwise_or, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  1255. operator|(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1256. {
  1257. return detail::expression<detail::bitwise_or, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1258. }
  1259. //
  1260. // Bitwise XOR:
  1261. //
  1262. template <class B>
  1263. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1264. detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, number<B, et_on> > >::type
  1265. operator^(const number<B, et_on>& a, const number<B, et_on>& b)
  1266. {
  1267. return detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  1268. }
  1269. template <class B>
  1270. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1271. number<B, et_on> >::type
  1272. operator^(number<B, et_on>&& a, const number<B, et_on>& b)
  1273. {
  1274. return detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  1275. }
  1276. template <class B>
  1277. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1278. number<B, et_on> >::type
  1279. operator^(const number<B, et_on>& a, number<B, et_on>&& b)
  1280. {
  1281. return detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  1282. }
  1283. template <class B>
  1284. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1285. number<B, et_on> >::type
  1286. operator^(number<B, et_on>&& a, number<B, et_on>&& b)
  1287. {
  1288. return detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  1289. }
  1290. template <class B, class V>
  1291. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
  1292. detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, V> >::type
  1293. operator^(const number<B, et_on>& a, const V& b)
  1294. {
  1295. return detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, V>(a, b);
  1296. }
  1297. template <class B, class V>
  1298. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
  1299. number<B, et_on> >::type
  1300. operator^(number<B, et_on>&& a, const V& b)
  1301. {
  1302. return detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, V>(a, b);
  1303. }
  1304. template <class V, class B>
  1305. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
  1306. detail::expression<detail::bitwise_xor_immediates, V, number<B, et_on> > >::type
  1307. operator^(const V& a, const number<B, et_on>& b)
  1308. {
  1309. return detail::expression<detail::bitwise_xor_immediates, V, number<B, et_on> >(a, b);
  1310. }
  1311. template <class V, class B>
  1312. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value && (number_category<B>::value == number_kind_integer),
  1313. number<B, et_on> >::type
  1314. operator^(const V& a, number<B, et_on>&& b)
  1315. {
  1316. return detail::expression<detail::bitwise_xor_immediates, V, number<B, et_on> >(a, b);
  1317. }
  1318. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1319. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1320. detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  1321. operator^(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1322. {
  1323. return detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1324. }
  1325. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1326. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1327. typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
  1328. operator^(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1329. {
  1330. return detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1331. }
  1332. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  1333. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1334. detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
  1335. operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
  1336. {
  1337. return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
  1338. }
  1339. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  1340. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1341. typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
  1342. operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
  1343. {
  1344. return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
  1345. }
  1346. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
  1347. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
  1348. detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
  1349. operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
  1350. {
  1351. return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
  1352. }
  1353. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
  1354. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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),
  1355. detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
  1356. operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  1357. {
  1358. return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
  1359. }
  1360. template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1361. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
  1362. operator^(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1363. {
  1364. return detail::expression<detail::bitwise_xor, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1365. }
  1366. }} // namespace boost::multiprecision
  1367. #endif