et_ops.hpp 119 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832
  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