et_ops.hpp 119 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831
  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 which return expression templates.
  10. //
  11. // Note that operators taking rvalue-references DO NOT return expression templates
  12. // as this can lead to dangling references, see https://github.com/boostorg/multiprecision/issues/175.
  13. //
  14. // Unary operators first.
  15. // Note that these *must* return by value, even though that's somewhat against
  16. // existing practice. The issue is that in C++11 land one could easily and legitimately
  17. // write:
  18. // auto x = +1234_my_user_defined_suffix;
  19. // which would result in a dangling-reference-to-temporary if unary + returned a reference
  20. // to it's argument. While return-by-value is obviously inefficient in other situations
  21. // the reality is that no one ever uses unary operator+ anyway...!
  22. //
  23. template <class B, expression_template_option ExpressionTemplates>
  24. inline constexpr const number<B, ExpressionTemplates> operator+(const number<B, ExpressionTemplates>& v) { return v; }
  25. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  26. inline constexpr const detail::expression<tag, Arg1, Arg2, Arg3, Arg4> operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return v; }
  27. template <class B>
  28. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, number<B, et_on> > operator-(const number<B, et_on>& v)
  29. {
  30. static_assert(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
  31. return detail::expression<detail::negate, number<B, et_on> >(v);
  32. }
  33. // rvalue ops:
  34. template <class B>
  35. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on> operator-(number<B, et_on>&& v)
  36. {
  37. static_assert(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
  38. v.backend().negate();
  39. return std::move(v);
  40. }
  41. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  42. 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)
  43. {
  44. 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.");
  45. return detail::expression<detail::negate, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(v);
  46. }
  47. template <class B>
  48. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  49. detail::expression<detail::complement_immediates, number<B, et_on> > >::type
  50. operator~(const number<B, et_on>& v) { return detail::expression<detail::complement_immediates, number<B, et_on> >(v); }
  51. template <class B>
  52. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  53. number<B, et_on> >::type
  54. operator~(number<B, et_on>&& v)
  55. {
  56. using default_ops::eval_complement;
  57. eval_complement(v.backend(), v.backend());
  58. return std::move(v);
  59. }
  60. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  61. 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,
  62. detail::expression<detail::bitwise_complement, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  63. operator~(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& v) { return detail::expression<detail::bitwise_complement, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(v); }
  64. //
  65. // Then addition:
  66. //
  67. template <class B>
  68. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >
  69. operator+(const number<B, et_on>& a, const number<B, et_on>& b)
  70. {
  71. return detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  72. }
  73. template <class B>
  74. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  75. operator+(number<B, et_on>&& a, const number<B, et_on>& b)
  76. {
  77. using default_ops::eval_add;
  78. eval_add(a.backend(), b.backend());
  79. return std::move(a);
  80. }
  81. template <class B>
  82. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  83. operator+(const number<B, et_on>& a, number<B, et_on>&& b)
  84. {
  85. using default_ops::eval_add;
  86. eval_add(b.backend(), a.backend());
  87. return std::move(b);
  88. }
  89. template <class B>
  90. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  91. operator+(number<B, et_on>&& a, number<B, et_on>&& b)
  92. {
  93. using default_ops::eval_add;
  94. eval_add(a.backend(), b.backend());
  95. return std::move(a);
  96. }
  97. template <class B, class V>
  98. 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
  99. operator+(const number<B, et_on>& a, const V& b)
  100. {
  101. return detail::expression<detail::add_immediates, number<B, et_on>, V>(a, b);
  102. }
  103. template <class B, class V>
  104. 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
  105. operator+(number<B, et_on>&& a, const V& b)
  106. {
  107. using default_ops::eval_add;
  108. eval_add(a.backend(), number<B, et_on>::canonical_value(b));
  109. return std::move(a);
  110. }
  111. template <class V, class B>
  112. 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
  113. operator+(const V& a, const number<B, et_on>& b)
  114. {
  115. return detail::expression<detail::add_immediates, V, number<B, et_on> >(a, b);
  116. }
  117. template <class V, class B>
  118. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, number<B, et_on> >::type
  119. operator+(const V& a, number<B, et_on>&& b)
  120. {
  121. using default_ops::eval_add;
  122. eval_add(b.backend(), number<B, et_on>::canonical_value(a));
  123. return std::move(b);
  124. }
  125. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  126. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
  127. operator+(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  128. {
  129. return detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  130. }
  131. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  132. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  133. std::is_same<typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET> >::value,
  134. typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
  135. operator+(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  136. {
  137. a += b;
  138. return std::move(a);
  139. }
  140. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  141. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  142. !std::is_same<typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET> >::value,
  143. typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
  144. operator+(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  145. {
  146. return detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  147. }
  148. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  149. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
  150. operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  151. {
  152. return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
  153. }
  154. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  155. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  156. std::is_same<typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
  157. typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
  158. operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  159. {
  160. b += a;
  161. return std::move(b);
  162. }
  163. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  164. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  165. !std::is_same<typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
  166. typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
  167. operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  168. {
  169. return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
  170. }
  171. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
  172. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
  173. operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
  174. {
  175. return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
  176. }
  177. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
  178. 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
  179. operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  180. {
  181. return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
  182. }
  183. template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  184. 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
  185. operator+(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  186. {
  187. return detail::expression<detail::plus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  188. }
  189. //
  190. // Fused multiply add:
  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::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
  195. operator+(const V& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
  196. {
  197. 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);
  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_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
  202. operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  203. {
  204. 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);
  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::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> >
  208. operator+(const number<B, ET>& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
  209. {
  210. 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);
  211. }
  212. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  213. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  214. std::is_same<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, number<B, ET>>::value,
  215. 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>::type
  216. operator+(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
  217. {
  218. a += b;
  219. return std::move(a);
  220. }
  221. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  222. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  223. !std::is_same<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, number<B, ET>>::value,
  224. 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>::type
  225. operator+(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
  226. {
  227. 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);
  228. }
  229. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  230. 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> >
  231. operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  232. {
  233. 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);
  234. }
  235. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  236. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  237. std::is_same<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, number<B, ET>>::value,
  238. 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>::type
  239. operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  240. {
  241. b += a;
  242. return std::move(b);
  243. }
  244. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  245. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  246. !std::is_same<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, number<B, ET>>::value,
  247. 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>::type
  248. operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  249. {
  250. 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);
  251. }
  252. //
  253. // Fused multiply subtract:
  254. //
  255. template <class V, class Arg1, class Arg2, class Arg3, class Arg4>
  256. 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,
  257. 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
  258. operator-(const V& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
  259. {
  260. 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));
  261. }
  262. template <class Arg1, class Arg2, class Arg3, class Arg4, class V>
  263. 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,
  264. 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
  265. operator-(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  266. {
  267. 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);
  268. }
  269. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  270. 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> > >
  271. operator-(const number<B, ET>& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
  272. {
  273. 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));
  274. }
  275. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  276. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  277. std::is_same<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, number<B, ET>>::value,
  278. 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>::type
  279. operator-(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
  280. {
  281. a -= b;
  282. return std::move(a);
  283. }
  284. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  285. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  286. !std::is_same<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, number<B, ET>>::value,
  287. 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>::type
  288. operator-(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
  289. {
  290. 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));
  291. }
  292. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  293. 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> >
  294. operator-(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  295. {
  296. 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);
  297. }
  298. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  299. 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
  300. operator-(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  301. {
  302. 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);
  303. }
  304. //
  305. // Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
  306. //
  307. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  308. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, number<B, ET>, Arg1>
  309. operator+(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  310. {
  311. return detail::expression<detail::minus, number<B, ET>, Arg1>(a, b.left_ref());
  312. }
  313. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  314. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  315. std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
  316. typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type>::type
  317. operator+(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  318. {
  319. a -= b.left_ref();
  320. return std::move(a);
  321. }
  322. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  323. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  324. !std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
  325. typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type>::type
  326. operator+(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  327. {
  328. return detail::expression<detail::minus, number<B, ET>, Arg1>(a, b.left_ref());
  329. }
  330. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  331. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, number<B, ET>, Arg1>
  332. operator+(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  333. {
  334. return detail::expression<detail::minus, number<B, ET>, Arg1>(b, a.left_ref());
  335. }
  336. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  337. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  338. std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
  339. typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type>::type
  340. operator+(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  341. {
  342. b -= a.left_ref();
  343. return std::move(b);
  344. }
  345. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  346. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  347. !std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
  348. typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type>::type
  349. operator+(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  350. {
  351. return detail::expression<detail::minus, number<B, ET>, Arg1>(b, a.left_ref());
  352. }
  353. template <class B>
  354. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
  355. operator+(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  356. {
  357. return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref());
  358. }
  359. template <class B>
  360. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >::result_type
  361. operator+(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  362. {
  363. using default_ops::eval_subtract;
  364. eval_subtract(a.backend(), b.left_ref().backend());
  365. return std::move(a);
  366. }
  367. template <class B>
  368. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
  369. operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
  370. {
  371. return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref());
  372. }
  373. template <class B>
  374. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >::result_type
  375. operator+(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
  376. {
  377. using default_ops::eval_subtract;
  378. eval_subtract(b.backend(), a.left_ref().backend());
  379. return std::move(b);
  380. }
  381. template <class B, class V>
  382. 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
  383. operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
  384. {
  385. return detail::expression<detail::subtract_immediates, V, number<B, et_on> >(b, a.left_ref());
  386. }
  387. template <class B, class B2, expression_template_option ET>
  388. 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
  389. operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
  390. {
  391. return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(b, a.left_ref());
  392. }
  393. template <class B, class B2, expression_template_option ET>
  394. 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
  395. operator+(const detail::expression<detail::negate, number<B, et_on> >& a, number<B2, ET>&& b)
  396. {
  397. return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(b, a.left_ref());
  398. }
  399. template <class B2, expression_template_option ET, class B>
  400. 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
  401. operator+(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  402. {
  403. return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
  404. }
  405. template <class B2, expression_template_option ET, class B>
  406. 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
  407. operator+(number<B2, ET>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  408. {
  409. return detail::expression<detail::subtract_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
  410. }
  411. template <class B>
  412. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >
  413. operator+(const detail::expression<detail::negate, number<B, et_on> >& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  414. {
  415. 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()));
  416. }
  417. //
  418. // Subtraction:
  419. //
  420. template <class B>
  421. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >
  422. operator-(const number<B, et_on>& a, const number<B, et_on>& b)
  423. {
  424. return detail::expression<detail::subtract_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  425. }
  426. template <class B>
  427. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  428. operator-(number<B, et_on>&& a, const number<B, et_on>& b)
  429. {
  430. using default_ops::eval_subtract;
  431. eval_subtract(a.backend(), b.backend());
  432. return std::move(a);
  433. }
  434. template <class B>
  435. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  436. operator-(const number<B, et_on>& a, number<B, et_on>&& b)
  437. {
  438. using default_ops::eval_subtract;
  439. eval_subtract(b.backend(), a.backend());
  440. b.backend().negate();
  441. return std::move(b);
  442. }
  443. template <class B>
  444. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  445. operator-(number<B, et_on>&& a, number<B, et_on>&& b)
  446. {
  447. using default_ops::eval_subtract;
  448. eval_subtract(a.backend(), b.backend());
  449. return std::move(a);
  450. }
  451. template <class B, class V>
  452. 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
  453. operator-(const number<B, et_on>& a, const V& b)
  454. {
  455. return detail::expression<detail::subtract_immediates, number<B, et_on>, V>(a, b);
  456. }
  457. template <class B, class V>
  458. 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
  459. operator-(number<B, et_on>&& a, const V& b)
  460. {
  461. using default_ops::eval_subtract;
  462. eval_subtract(a.backend(), number<B, et_on>::canonical_value(b));
  463. return std::move(a);
  464. }
  465. template <class V, class B>
  466. 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
  467. operator-(const V& a, const number<B, et_on>& b)
  468. {
  469. return detail::expression<detail::subtract_immediates, V, number<B, et_on> >(a, b);
  470. }
  471. template <class V, class B>
  472. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, number<B, et_on> >::type
  473. operator-(const V& a, number<B, et_on>&& b)
  474. {
  475. using default_ops::eval_subtract;
  476. eval_subtract(b.backend(), number<B, et_on>::canonical_value(a));
  477. b.backend().negate();
  478. return std::move(b);
  479. }
  480. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  481. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
  482. operator-(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  483. {
  484. return detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  485. }
  486. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  487. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  488. std::is_same<typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
  489. typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
  490. operator-(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  491. {
  492. a -= b;
  493. return std::move(a);
  494. }
  495. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  496. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  497. !std::is_same<typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
  498. typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
  499. operator-(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  500. {
  501. return detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  502. }
  503. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  504. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
  505. operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  506. {
  507. return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
  508. }
  509. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  510. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  511. std::is_same<typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
  512. typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
  513. operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  514. {
  515. b -= a;
  516. b.backend().negate();
  517. return std::move(b);
  518. }
  519. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  520. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  521. !std::is_same<typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
  522. typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
  523. operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  524. {
  525. return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
  526. }
  527. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
  528. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
  529. operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
  530. {
  531. return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
  532. }
  533. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
  534. 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
  535. operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  536. {
  537. return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
  538. }
  539. template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  540. 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
  541. operator-(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  542. {
  543. return detail::expression<detail::minus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  544. }
  545. //
  546. // Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
  547. //
  548. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  549. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::plus, number<B, ET>, Arg1>
  550. operator-(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  551. {
  552. return detail::expression<detail::plus, number<B, ET>, Arg1>(a, b.left_ref());
  553. }
  554. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  555. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  556. std::is_same<typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
  557. typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type>::type
  558. operator-(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  559. {
  560. a += b.left_ref();
  561. return std::move(a);
  562. }
  563. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  564. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  565. !std::is_same<typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
  566. typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type>::type
  567. operator-(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  568. {
  569. return detail::expression<detail::plus, number<B, ET>, Arg1>(a, b.left_ref());
  570. }
  571. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  572. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >
  573. operator-(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  574. {
  575. return detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >(
  576. detail::expression<detail::plus, number<B, ET>, Arg1>(b, a.left_ref()));
  577. }
  578. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  579. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  580. std::is_same<typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value,
  581. typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type>::type
  582. operator-(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  583. {
  584. b += a.left_ref();
  585. b.backend().negate();
  586. return std::move(b);
  587. }
  588. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  589. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  590. !std::is_same<typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value,
  591. typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type>::type
  592. operator-(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  593. {
  594. return detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >(detail::expression<detail::plus, number<B, ET>, Arg1>(b, a.left_ref()));
  595. }
  596. template <class B>
  597. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >
  598. operator-(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  599. {
  600. return detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref());
  601. }
  602. template <class B>
  603. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >::result_type
  604. operator-(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  605. {
  606. using default_ops::eval_add;
  607. eval_add(a.backend(), b.left_ref().backend());
  608. return std::move(a);
  609. }
  610. template <class B>
  611. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >
  612. operator-(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
  613. {
  614. return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >(
  615. detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
  616. }
  617. template <class B>
  618. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  619. std::is_same<typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
  620. typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
  621. operator-(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
  622. {
  623. using default_ops::eval_add;
  624. eval_add(b.backend(), a.left_ref().backend());
  625. b.backend().negate();
  626. return std::move(b);
  627. }
  628. template <class B>
  629. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  630. !std::is_same<typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
  631. typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
  632. operator-(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
  633. {
  634. return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >(
  635. detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
  636. }
  637. template <class B, class V>
  638. 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
  639. operator-(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
  640. {
  641. 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));
  642. }
  643. template <class B, class B2, expression_template_option ET>
  644. 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
  645. operator-(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
  646. {
  647. 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));
  648. }
  649. template <class B, class B2, expression_template_option ET>
  650. 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
  651. operator-(const detail::expression<detail::negate, number<B, et_on> >& a, number<B2, ET>&& b)
  652. {
  653. 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));
  654. }
  655. template <class V, class B>
  656. 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
  657. operator-(const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  658. {
  659. return detail::expression<detail::add_immediates, V, number<B, et_on> >(a, b.left_ref());
  660. }
  661. template <class B2, expression_template_option ET, class B>
  662. 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
  663. operator-(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  664. {
  665. return detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
  666. }
  667. template <class B2, expression_template_option ET, class B>
  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::add_immediates, number<B2, ET>, number<B, et_on> >::result_type>::type
  669. operator-(number<B2, ET>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  670. {
  671. return detail::expression<detail::add_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref());
  672. }
  673. //
  674. // Multiplication:
  675. //
  676. template <class B>
  677. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >
  678. operator*(const number<B, et_on>& a, const number<B, et_on>& b)
  679. {
  680. return detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  681. }
  682. template <class B>
  683. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  684. operator*(number<B, et_on>&& a, const number<B, et_on>& b)
  685. {
  686. using default_ops::eval_multiply;
  687. eval_multiply(a.backend(), b.backend());
  688. return std::move(a);
  689. }
  690. template <class B>
  691. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  692. operator*(const number<B, et_on>& a, number<B, et_on>&& b)
  693. {
  694. using default_ops::eval_multiply;
  695. eval_multiply(b.backend(), a.backend());
  696. return std::move(b);
  697. }
  698. template <class B>
  699. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  700. operator*(number<B, et_on>&& a, number<B, et_on>&& b)
  701. {
  702. using default_ops::eval_multiply;
  703. eval_multiply(a.backend(), b.backend());
  704. return std::move(a);
  705. }
  706. template <class B, class V>
  707. 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
  708. operator*(const number<B, et_on>& a, const V& b)
  709. {
  710. return detail::expression<detail::multiply_immediates, number<B, et_on>, V>(a, b);
  711. }
  712. template <class B, class V>
  713. 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
  714. operator*(number<B, et_on>&& a, const V& b)
  715. {
  716. using default_ops::eval_multiply;
  717. eval_multiply(a.backend(), number<B, et_on>::canonical_value(b));
  718. return std::move(a);
  719. }
  720. template <class V, class B>
  721. 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
  722. operator*(const V& a, const number<B, et_on>& b)
  723. {
  724. return detail::expression<detail::multiply_immediates, V, number<B, et_on> >(a, b);
  725. }
  726. template <class V, class B>
  727. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, number<B, et_on> >::type
  728. operator*(const V& a, number<B, et_on>&& b)
  729. {
  730. using default_ops::eval_multiply;
  731. eval_multiply(b.backend(), number<B, et_on>::canonical_value(a));
  732. return std::move(b);
  733. }
  734. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  735. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
  736. operator*(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  737. {
  738. return detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  739. }
  740. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  741. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  742. std::is_same<typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
  743. typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
  744. operator*(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  745. {
  746. a *= b;
  747. return std::move(a);
  748. }
  749. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  750. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  751. !std::is_same<typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
  752. typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
  753. operator*(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  754. {
  755. return detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  756. }
  757. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  758. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
  759. operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  760. {
  761. return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
  762. }
  763. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  764. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  765. std::is_same<typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
  766. typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
  767. operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  768. {
  769. b *= a;
  770. return std::move(b);
  771. }
  772. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  773. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  774. !std::is_same<typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
  775. typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
  776. operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  777. {
  778. return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
  779. }
  780. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
  781. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
  782. operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
  783. {
  784. return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
  785. }
  786. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
  787. inline BOOST_MP_CXX14_CONSTEXPR typename 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
  788. operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  789. {
  790. return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
  791. }
  792. template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  793. 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
  794. operator*(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  795. {
  796. return detail::expression<detail::multiplies, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  797. }
  798. //
  799. // Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
  800. //
  801. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  802. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >
  803. operator*(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  804. {
  805. return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
  806. detail::expression<detail::multiplies, number<B, ET>, Arg1>(a, b.left_ref()));
  807. }
  808. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  809. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >::result_type
  810. operator*(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  811. {
  812. return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
  813. detail::expression<detail::multiplies, number<B, ET>, Arg1>(a, b.left_ref()));
  814. }
  815. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  816. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >
  817. operator*(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  818. {
  819. return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
  820. detail::expression<detail::multiplies, number<B, ET>, Arg1>(b, a.left_ref()));
  821. }
  822. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  823. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >::result_type
  824. operator*(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  825. {
  826. return detail::expression<detail::negate, detail::expression<detail::multiplies, number<B, ET>, Arg1> >(
  827. detail::expression<detail::multiplies, number<B, ET>, Arg1>(b, a.left_ref()));
  828. }
  829. template <class B>
  830. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >
  831. operator*(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  832. {
  833. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
  834. detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
  835. }
  836. template <class B>
  837. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  838. std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
  839. typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
  840. operator*(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  841. {
  842. a *= b.left_ref();
  843. a.backend().negate();
  844. return std::move(a);
  845. }
  846. template <class B>
  847. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  848. !std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
  849. typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
  850. operator*(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  851. {
  852. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
  853. detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
  854. }
  855. template <class B>
  856. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >
  857. operator*(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
  858. {
  859. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
  860. detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
  861. }
  862. template <class B>
  863. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  864. std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
  865. typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
  866. operator*(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
  867. {
  868. b *= a.left_ref();
  869. b.backend().negate();
  870. return std::move(b);
  871. }
  872. template <class B>
  873. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  874. !std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
  875. typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
  876. operator*(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
  877. {
  878. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
  879. detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
  880. }
  881. template <class B, class V>
  882. 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
  883. operator*(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
  884. {
  885. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V> >(
  886. detail::expression<detail::multiply_immediates, number<B, et_on>, V>(a.left_ref(), b));
  887. }
  888. template <class B, class B2, expression_template_option ET>
  889. 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
  890. operator*(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
  891. {
  892. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
  893. detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
  894. }
  895. template <class B, class B2, expression_template_option ET>
  896. 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
  897. operator*(const detail::expression<detail::negate, number<B, et_on> >& a, number<B2, ET>&& b)
  898. {
  899. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
  900. detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
  901. }
  902. template <class V, class B>
  903. 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
  904. operator*(const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  905. {
  906. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, V> >(
  907. detail::expression<detail::multiply_immediates, number<B, et_on>, V>(b.left_ref(), a));
  908. }
  909. template <class B2, expression_template_option ET, class B>
  910. 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
  911. operator*(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  912. {
  913. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
  914. detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(b.left_ref(), a));
  915. }
  916. template <class B2, expression_template_option ET, class B>
  917. 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
  918. operator*(number<B2, ET>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  919. {
  920. return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> > >(
  921. detail::expression<detail::multiply_immediates, number<B, et_on>, number<B2, ET> >(b.left_ref(), a));
  922. }
  923. //
  924. // Division:
  925. //
  926. template <class B>
  927. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >
  928. operator/(const number<B, et_on>& a, const number<B, et_on>& b)
  929. {
  930. return detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  931. }
  932. template <class B>
  933. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  934. operator/(number<B, et_on>&& a, const number<B, et_on>& b)
  935. {
  936. using default_ops::eval_divide;
  937. eval_divide(a.backend(), b.backend());
  938. return std::move(a);
  939. }
  940. template <class B>
  941. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  942. operator/(const number<B, et_on>& a, number<B, et_on>&& b)
  943. {
  944. return detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  945. }
  946. template <class B>
  947. inline BOOST_MP_CXX14_CONSTEXPR number<B, et_on>
  948. operator/(number<B, et_on>&& a, number<B, et_on>&& b)
  949. {
  950. using default_ops::eval_divide;
  951. eval_divide(a.backend(), b.backend());
  952. return std::move(a);
  953. }
  954. template <class B, class V>
  955. 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
  956. operator/(const number<B, et_on>& a, const V& b)
  957. {
  958. return detail::expression<detail::divide_immediates, number<B, et_on>, V>(a, b);
  959. }
  960. template <class B, class V>
  961. 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
  962. operator/(number<B, et_on>&& a, const V& b)
  963. {
  964. using default_ops::eval_divide;
  965. eval_divide(a.backend(), number<B, et_on>::canonical_value(b));
  966. return std::move(a);
  967. }
  968. template <class V, class B>
  969. 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
  970. operator/(const V& a, const number<B, et_on>& b)
  971. {
  972. return detail::expression<detail::divide_immediates, V, number<B, et_on> >(a, b);
  973. }
  974. template <class V, class B>
  975. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_on> >::value, number<B, et_on> >::type
  976. operator/(const V& a, number<B, et_on>&& b)
  977. {
  978. return detail::expression<detail::divide_immediates, V, number<B, et_on> >(a, b);
  979. }
  980. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  981. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
  982. operator/(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  983. {
  984. return detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  985. }
  986. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  987. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  988. std::is_same<typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
  989. typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
  990. operator/(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  991. {
  992. a /= b;
  993. return std::move(a);
  994. }
  995. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  996. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  997. !std::is_same<typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
  998. typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
  999. operator/(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1000. {
  1001. return detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1002. }
  1003. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  1004. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
  1005. operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  1006. {
  1007. return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
  1008. }
  1009. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  1010. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type
  1011. operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  1012. {
  1013. return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
  1014. }
  1015. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
  1016. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >
  1017. operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
  1018. {
  1019. return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
  1020. }
  1021. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
  1022. 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
  1023. operator/(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  1024. {
  1025. return detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
  1026. }
  1027. template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1028. 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
  1029. operator/(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1030. {
  1031. return detail::expression<detail::divides, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1032. }
  1033. //
  1034. // Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries:
  1035. //
  1036. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  1037. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >
  1038. operator/(const number<B, ET>& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  1039. {
  1040. return detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >(
  1041. detail::expression<detail::divides, number<B, ET>, Arg1>(a, b.left_ref()));
  1042. }
  1043. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  1044. inline typename std::enable_if<
  1045. std::is_same<typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value,
  1046. typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type>::type
  1047. operator/(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  1048. {
  1049. a /= b.left_ref();
  1050. a.backend().negate();
  1051. return std::move(a);
  1052. }
  1053. template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
  1054. inline typename std::enable_if<
  1055. !std::is_same<typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value,
  1056. typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type>::type
  1057. operator/(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
  1058. {
  1059. return detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >(
  1060. detail::expression<detail::divides, number<B, ET>, Arg1>(a, b.left_ref()));
  1061. }
  1062. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  1063. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >
  1064. operator/(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, const number<B, ET>& b)
  1065. {
  1066. return detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >(
  1067. detail::expression<detail::divides, Arg1, number<B, ET> >(a.left_ref(), b));
  1068. }
  1069. template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  1070. inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >::result_type
  1071. operator/(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
  1072. {
  1073. return detail::expression<detail::negate, detail::expression<detail::divides, Arg1, number<B, ET> > >(
  1074. detail::expression<detail::divides, Arg1, number<B, ET> >(a.left_ref(), b));
  1075. }
  1076. template <class B>
  1077. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >
  1078. operator/(const number<B, et_on>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  1079. {
  1080. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >(
  1081. detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
  1082. }
  1083. template <class B>
  1084. 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
  1085. operator/(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  1086. {
  1087. a /= b.left_ref();
  1088. a.backend().negate();
  1089. return std::move(a);
  1090. }
  1091. template <class B>
  1092. inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >
  1093. operator/(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B, et_on>& b)
  1094. {
  1095. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >(
  1096. detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a.left_ref(), b));
  1097. }
  1098. template <class B>
  1099. 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
  1100. operator/(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
  1101. {
  1102. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> > >(
  1103. detail::expression<detail::divide_immediates, number<B, et_on>, number<B, et_on> >(a.left_ref(), b));
  1104. }
  1105. template <class B, class V>
  1106. 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
  1107. operator/(const detail::expression<detail::negate, number<B, et_on> >& a, const V& b)
  1108. {
  1109. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, V> >(
  1110. detail::expression<detail::divide_immediates, number<B, et_on>, V>(a.left_ref(), b));
  1111. }
  1112. template <class B, class B2, expression_template_option ET>
  1113. 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
  1114. operator/(const detail::expression<detail::negate, number<B, et_on> >& a, const number<B2, ET>& b)
  1115. {
  1116. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > >(
  1117. detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
  1118. }
  1119. template <class B, class B2, expression_template_option ET>
  1120. 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
  1121. operator/(const detail::expression<detail::negate, number<B, et_on> >& a, number<B2, ET>&& b)
  1122. {
  1123. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> > >(
  1124. detail::expression<detail::divide_immediates, number<B, et_on>, number<B2, ET> >(a.left_ref(), b));
  1125. }
  1126. template <class V, class B>
  1127. 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
  1128. operator/(const V& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  1129. {
  1130. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, V, number<B, et_on> > >(
  1131. detail::expression<detail::divide_immediates, V, number<B, et_on> >(a, b.left_ref()));
  1132. }
  1133. template <class B2, expression_template_option ET, class B>
  1134. 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
  1135. operator/(const number<B2, ET>& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  1136. {
  1137. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > >(
  1138. detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref()));
  1139. }
  1140. template <class B2, expression_template_option ET, class B>
  1141. 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
  1142. operator/(number<B2, ET>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
  1143. {
  1144. return detail::expression<detail::negate, detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> > >(
  1145. detail::expression<detail::divide_immediates, number<B2, ET>, number<B, et_on> >(a, b.left_ref()));
  1146. }
  1147. //
  1148. // Modulus:
  1149. //
  1150. template <class B>
  1151. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1152. detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> > >::type
  1153. operator%(const number<B, et_on>& a, const number<B, et_on>& b)
  1154. {
  1155. return detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  1156. }
  1157. template <class B>
  1158. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1159. number<B, et_on> >::type
  1160. operator%(number<B, et_on>&& a, const number<B, et_on>& b)
  1161. {
  1162. using default_ops::eval_modulus;
  1163. eval_modulus(a.backend(), b.backend());
  1164. return std::move(a);
  1165. }
  1166. template <class B>
  1167. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1168. number<B, et_on> >::type
  1169. operator%(const number<B, et_on>& a, number<B, et_on>&& b)
  1170. {
  1171. return detail::expression<detail::modulus_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  1172. }
  1173. template <class B>
  1174. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1175. number<B, et_on> >::type
  1176. operator%(number<B, et_on>&& a, number<B, et_on>&& b)
  1177. {
  1178. using default_ops::eval_modulus;
  1179. eval_modulus(a.backend(), b.backend());
  1180. return std::move(a);
  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) && !is_equivalent_number_type<V, number<B, et_on> >::value,
  1184. detail::expression<detail::modulus_immediates, number<B, et_on>, V> >::type
  1185. operator%(const number<B, et_on>& a, const V& b)
  1186. {
  1187. return detail::expression<detail::modulus_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) && !is_equivalent_number_type<V, number<B, et_on> >::value,
  1191. number<B, et_on> >::type
  1192. operator%(number<B, et_on>&& a, const V& b)
  1193. {
  1194. using default_ops::eval_modulus;
  1195. eval_modulus(a.backend(), number<B, et_on>::canonical_value(b));
  1196. return std::move(a);
  1197. }
  1198. template <class V, class B>
  1199. 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),
  1200. detail::expression<detail::modulus_immediates, V, number<B, et_on> > >::type
  1201. operator%(const V& a, const number<B, et_on>& b)
  1202. {
  1203. return detail::expression<detail::modulus_immediates, V, number<B, et_on> >(a, b);
  1204. }
  1205. template <class V, class B>
  1206. 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),
  1207. number<B, et_on> >::type
  1208. operator%(const V& a, number<B, et_on>&& b)
  1209. {
  1210. return detail::expression<detail::modulus_immediates, V, number<B, et_on> >(a, b);
  1211. }
  1212. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1213. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1214. detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  1215. operator%(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1216. {
  1217. return detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1218. }
  1219. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1220. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1221. std::is_same<typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
  1222. && number_category<B>::value == number_kind_integer,
  1223. typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
  1224. operator%(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1225. {
  1226. a %= b;
  1227. return std::move(a);
  1228. }
  1229. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1230. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1231. !std::is_same<typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
  1232. && number_category<B>::value == number_kind_integer,
  1233. typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
  1234. operator%(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1235. {
  1236. return detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1237. }
  1238. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  1239. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1240. detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
  1241. operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
  1242. {
  1243. return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
  1244. }
  1245. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  1246. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1247. typename detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type >::type
  1248. operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
  1249. {
  1250. return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
  1251. }
  1252. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
  1253. 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,
  1254. detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
  1255. operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
  1256. {
  1257. return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
  1258. }
  1259. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
  1260. 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),
  1261. detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
  1262. operator%(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  1263. {
  1264. return detail::expression<detail::modulus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
  1265. }
  1266. template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1267. 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),
  1268. detail::expression<detail::modulus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  1269. operator%(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1270. {
  1271. return detail::expression<detail::modulus, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1272. }
  1273. //
  1274. // Left shift:
  1275. //
  1276. template <class B, class I>
  1277. 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
  1278. operator<<(const number<B, et_on>& a, const I& b)
  1279. {
  1280. return detail::expression<detail::shift_left, number<B, et_on>, I>(a, b);
  1281. }
  1282. template <class B, class I>
  1283. 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
  1284. operator<<(number<B, et_on>&& a, const I& b)
  1285. {
  1286. using default_ops::eval_left_shift;
  1287. eval_left_shift(a.backend(), b);
  1288. return std::move(a);
  1289. }
  1290. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
  1291. 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),
  1292. detail::expression<detail::shift_left, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
  1293. operator<<(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
  1294. {
  1295. return detail::expression<detail::shift_left, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I>(a, b);
  1296. }
  1297. //
  1298. // Right shift:
  1299. //
  1300. template <class B, class I>
  1301. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer),
  1302. detail::expression<detail::shift_right, number<B, et_on>, I> >::type
  1303. operator>>(const number<B, et_on>& a, const I& b)
  1304. {
  1305. return detail::expression<detail::shift_right, number<B, et_on>, I>(a, b);
  1306. }
  1307. template <class B, class I>
  1308. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer),
  1309. number<B, et_on> >::type
  1310. operator>>(number<B, et_on>&& a, const I& b)
  1311. {
  1312. using default_ops::eval_right_shift;
  1313. eval_right_shift(a.backend(), b);
  1314. return std::move(a);
  1315. }
  1316. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class I>
  1317. 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),
  1318. detail::expression<detail::shift_right, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I> >::type
  1319. operator>>(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const I& b)
  1320. {
  1321. return detail::expression<detail::shift_right, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, I>(a, b);
  1322. }
  1323. //
  1324. // Bitwise AND:
  1325. //
  1326. template <class B>
  1327. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1328. detail::expression<detail::bitwise_and_immediates, number<B, et_on>, number<B, et_on> > >::type
  1329. operator&(const number<B, et_on>& a, const number<B, et_on>& b)
  1330. {
  1331. return detail::expression<detail::bitwise_and_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  1332. }
  1333. template <class B>
  1334. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1335. number<B, et_on> >::type
  1336. operator&(number<B, et_on>&& a, const number<B, et_on>& b)
  1337. {
  1338. using default_ops::eval_bitwise_and;
  1339. eval_bitwise_and(a.backend(), b.backend());
  1340. return std::move(a);
  1341. }
  1342. template <class B>
  1343. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1344. number<B, et_on> >::type
  1345. operator&(const number<B, et_on>& a, number<B, et_on>&& b)
  1346. {
  1347. using default_ops::eval_bitwise_and;
  1348. eval_bitwise_and(b.backend(), a.backend());
  1349. return std::move(b);
  1350. }
  1351. template <class B>
  1352. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1353. number<B, et_on> >::type
  1354. operator&(number<B, et_on>&& a, number<B, et_on>&& b)
  1355. {
  1356. using default_ops::eval_bitwise_and;
  1357. eval_bitwise_and(a.backend(), b.backend());
  1358. return std::move(a);
  1359. }
  1360. template <class B, class V>
  1361. 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),
  1362. detail::expression<detail::bitwise_and_immediates, number<B, et_on>, V> >::type
  1363. operator&(const number<B, et_on>& a, const V& b)
  1364. {
  1365. return detail::expression<detail::bitwise_and_immediates, number<B, et_on>, V>(a, b);
  1366. }
  1367. template <class B, class V>
  1368. 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),
  1369. number<B, et_on> >::type
  1370. operator&(number<B, et_on>&& a, const V& b)
  1371. {
  1372. using default_ops::eval_bitwise_and;
  1373. eval_bitwise_and(a.backend(), number<B, et_on>::canonical_value(b));
  1374. return std::move(a);
  1375. }
  1376. template <class V, class B>
  1377. 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),
  1378. detail::expression<detail::bitwise_and_immediates, V, number<B, et_on> > >::type
  1379. operator&(const V& a, const number<B, et_on>& b)
  1380. {
  1381. return detail::expression<detail::bitwise_and_immediates, V, number<B, et_on> >(a, b);
  1382. }
  1383. template <class V, class B>
  1384. 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),
  1385. number<B, et_on> >::type
  1386. operator&(const V& a, number<B, et_on>&& b)
  1387. {
  1388. using default_ops::eval_bitwise_and;
  1389. eval_bitwise_and(b.backend(), number<B, et_on>::canonical_value(a));
  1390. return std::move(b);
  1391. }
  1392. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1393. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1394. detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  1395. operator&(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1396. {
  1397. return detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1398. }
  1399. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1400. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1401. std::is_same<typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
  1402. && number_category<B>::value == number_kind_integer,
  1403. typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
  1404. operator&(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1405. {
  1406. a &= b;
  1407. return std::move(a);
  1408. }
  1409. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1410. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1411. !std::is_same<typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
  1412. && number_category<B>::value == number_kind_integer,
  1413. typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
  1414. operator&(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1415. {
  1416. return detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1417. }
  1418. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  1419. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1420. detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
  1421. operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
  1422. {
  1423. return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
  1424. }
  1425. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  1426. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1427. std::is_same<typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
  1428. && number_category<B>::value == number_kind_integer,
  1429. typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type >::type
  1430. operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
  1431. {
  1432. b &= a;
  1433. return std::move(b);
  1434. }
  1435. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  1436. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1437. !std::is_same<typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
  1438. && number_category<B>::value == number_kind_integer,
  1439. typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type >::type
  1440. operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
  1441. {
  1442. return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
  1443. }
  1444. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
  1445. 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,
  1446. detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
  1447. operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
  1448. {
  1449. return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
  1450. }
  1451. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
  1452. 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),
  1453. detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
  1454. operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  1455. {
  1456. return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
  1457. }
  1458. template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1459. 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),
  1460. detail::expression<detail::bitwise_and, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  1461. operator&(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1462. {
  1463. return detail::expression<detail::bitwise_and, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1464. }
  1465. //
  1466. // Bitwise OR:
  1467. //
  1468. template <class B>
  1469. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1470. detail::expression<detail::bitwise_or_immediates, number<B, et_on>, number<B, et_on> > >::type
  1471. operator|(const number<B, et_on>& a, const number<B, et_on>& b)
  1472. {
  1473. return detail::expression<detail::bitwise_or_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  1474. }
  1475. template <class B>
  1476. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1477. number<B, et_on> >::type
  1478. operator|(number<B, et_on>&& a, const number<B, et_on>& b)
  1479. {
  1480. using default_ops::eval_bitwise_or;
  1481. eval_bitwise_or(a.backend(), b.backend());
  1482. return std::move(a);
  1483. }
  1484. template <class B>
  1485. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1486. number<B, et_on> >::type
  1487. operator|(const number<B, et_on>& a, number<B, et_on>&& b)
  1488. {
  1489. using default_ops::eval_bitwise_or;
  1490. eval_bitwise_or(b.backend(), a.backend());
  1491. return std::move(b);
  1492. }
  1493. template <class B>
  1494. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1495. number<B, et_on> >::type
  1496. operator|(number<B, et_on>&& a, number<B, et_on>&& b)
  1497. {
  1498. using default_ops::eval_bitwise_or;
  1499. eval_bitwise_or(a.backend(), b.backend());
  1500. return std::move(a);
  1501. }
  1502. template <class B, class V>
  1503. 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),
  1504. detail::expression<detail::bitwise_or_immediates, number<B, et_on>, V> >::type
  1505. operator|(const number<B, et_on>& a, const V& b)
  1506. {
  1507. return detail::expression<detail::bitwise_or_immediates, number<B, et_on>, V>(a, b);
  1508. }
  1509. template <class B, class V>
  1510. 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),
  1511. number<B, et_on> >::type
  1512. operator|(number<B, et_on>&& a, const V& b)
  1513. {
  1514. using default_ops::eval_bitwise_or;
  1515. eval_bitwise_or(a.backend(), number<B, et_on>::canonical_value(b));
  1516. return std::move(a);
  1517. }
  1518. template <class V, class B>
  1519. 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),
  1520. detail::expression<detail::bitwise_or_immediates, V, number<B, et_on> > >::type
  1521. operator|(const V& a, const number<B, et_on>& b)
  1522. {
  1523. return detail::expression<detail::bitwise_or_immediates, V, number<B, et_on> >(a, b);
  1524. }
  1525. template <class V, class B>
  1526. 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),
  1527. number<B, et_on> >::type
  1528. operator|(const V& a, number<B, et_on>&& b)
  1529. {
  1530. using default_ops::eval_bitwise_or;
  1531. eval_bitwise_or(b.backend(), number<B, et_on>::canonical_value(a));
  1532. return std::move(b);
  1533. }
  1534. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1535. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1536. detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  1537. operator|(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1538. {
  1539. return detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1540. }
  1541. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1542. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1543. std::is_same<typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
  1544. && number_category<B>::value == number_kind_integer,
  1545. typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
  1546. operator|(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1547. {
  1548. a |= b;
  1549. return std::move(a);
  1550. }
  1551. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1552. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1553. !std::is_same<typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
  1554. && number_category<B>::value == number_kind_integer,
  1555. typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
  1556. operator|(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1557. {
  1558. return detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1559. }
  1560. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  1561. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1562. detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
  1563. operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
  1564. {
  1565. return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
  1566. }
  1567. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  1568. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1569. std::is_same<typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
  1570. && number_category<B>::value == number_kind_integer,
  1571. typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
  1572. operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
  1573. {
  1574. b |= a;
  1575. return std::move(b);
  1576. }
  1577. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  1578. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1579. !std::is_same<typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
  1580. && number_category<B>::value == number_kind_integer,
  1581. typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
  1582. operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
  1583. {
  1584. return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
  1585. }
  1586. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
  1587. 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,
  1588. detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
  1589. operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
  1590. {
  1591. return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
  1592. }
  1593. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
  1594. 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),
  1595. detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
  1596. operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  1597. {
  1598. return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
  1599. }
  1600. template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1601. 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),
  1602. detail::expression<detail::bitwise_or, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  1603. operator|(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1604. {
  1605. return detail::expression<detail::bitwise_or, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1606. }
  1607. //
  1608. // Bitwise XOR:
  1609. //
  1610. template <class B>
  1611. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1612. detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, number<B, et_on> > >::type
  1613. operator^(const number<B, et_on>& a, const number<B, et_on>& b)
  1614. {
  1615. return detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, number<B, et_on> >(a, b);
  1616. }
  1617. template <class B>
  1618. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1619. number<B, et_on> >::type
  1620. operator^(number<B, et_on>&& a, const number<B, et_on>& b)
  1621. {
  1622. using default_ops::eval_bitwise_xor;
  1623. eval_bitwise_xor(a.backend(), b.backend());
  1624. return std::move(a);
  1625. }
  1626. template <class B>
  1627. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1628. number<B, et_on> >::type
  1629. operator^(const number<B, et_on>& a, number<B, et_on>&& b)
  1630. {
  1631. using default_ops::eval_bitwise_xor;
  1632. eval_bitwise_xor(b.backend(), a.backend());
  1633. return std::move(b);
  1634. }
  1635. template <class B>
  1636. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1637. number<B, et_on> >::type
  1638. operator^(number<B, et_on>&& a, number<B, et_on>&& b)
  1639. {
  1640. using default_ops::eval_bitwise_xor;
  1641. eval_bitwise_xor(a.backend(), b.backend());
  1642. return std::move(a);
  1643. }
  1644. template <class B, class V>
  1645. 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),
  1646. detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, V> >::type
  1647. operator^(const number<B, et_on>& a, const V& b)
  1648. {
  1649. return detail::expression<detail::bitwise_xor_immediates, number<B, et_on>, V>(a, b);
  1650. }
  1651. template <class B, class V>
  1652. 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),
  1653. number<B, et_on> >::type
  1654. operator^(number<B, et_on>&& a, const V& b)
  1655. {
  1656. using default_ops::eval_bitwise_xor;
  1657. eval_bitwise_xor(a.backend(), number<B, et_on>::canonical_value(b));
  1658. return std::move(a);
  1659. }
  1660. template <class V, class B>
  1661. 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),
  1662. detail::expression<detail::bitwise_xor_immediates, V, number<B, et_on> > >::type
  1663. operator^(const V& a, const number<B, et_on>& b)
  1664. {
  1665. return detail::expression<detail::bitwise_xor_immediates, V, number<B, et_on> >(a, b);
  1666. }
  1667. template <class V, class B>
  1668. 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),
  1669. number<B, et_on> >::type
  1670. operator^(const V& a, number<B, et_on>&& b)
  1671. {
  1672. using default_ops::eval_bitwise_xor;
  1673. eval_bitwise_xor(b.backend(), number<B, et_on>::canonical_value(a));
  1674. return std::move(b);
  1675. }
  1676. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1677. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1678. detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
  1679. operator^(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1680. {
  1681. return detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1682. }
  1683. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1684. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1685. std::is_same<typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
  1686. && number_category<B>::value == number_kind_integer,
  1687. typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
  1688. operator^(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1689. {
  1690. a ^= b;
  1691. return std::move(a);
  1692. }
  1693. template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1694. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1695. !std::is_same<typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
  1696. && number_category<B>::value == number_kind_integer,
  1697. typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
  1698. operator^(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1699. {
  1700. return detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1701. }
  1702. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  1703. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
  1704. detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> > >::type
  1705. operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number<B, et_on>& b)
  1706. {
  1707. return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
  1708. }
  1709. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  1710. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1711. std::is_same<typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
  1712. && number_category<B>::value == number_kind_integer,
  1713. typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
  1714. operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
  1715. {
  1716. b ^= a;
  1717. return std::move(b);
  1718. }
  1719. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
  1720. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
  1721. !std::is_same<typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
  1722. && number_category<B>::value == number_kind_integer,
  1723. typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
  1724. operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
  1725. {
  1726. return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
  1727. }
  1728. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
  1729. 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,
  1730. detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> > >::type
  1731. operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b>& b)
  1732. {
  1733. return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, detail::expression<tag2, Arg1b, Arg2b, Arg3b, Arg4b> >(a, b);
  1734. }
  1735. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
  1736. 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),
  1737. detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
  1738. operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const V& b)
  1739. {
  1740. return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(a, b);
  1741. }
  1742. template <class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1743. 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
  1744. operator^(const V& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
  1745. {
  1746. return detail::expression<detail::bitwise_xor, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
  1747. }
  1748. }} // namespace boost::multiprecision
  1749. #endif