number.hpp 102 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207
  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_MATH_EXTENDED_REAL_HPP
  6. #define BOOST_MATH_EXTENDED_REAL_HPP
  7. #include <boost/config.hpp>
  8. #include <cstdint>
  9. #include <boost/assert.hpp>
  10. #include <boost/throw_exception.hpp>
  11. #include <boost/multiprecision/detail/precision.hpp>
  12. #include <boost/multiprecision/detail/generic_interconvert.hpp>
  13. #include <boost/multiprecision/detail/number_compare.hpp>
  14. #include <boost/multiprecision/traits/is_restricted_conversion.hpp>
  15. #include <boost/multiprecision/traits/is_complex.hpp>
  16. #include <boost/container_hash/hash.hpp>
  17. #include <istream> // stream operators
  18. #include <cstdio> // EOF
  19. #include <cctype> // isspace
  20. #include <functional> // std::hash
  21. #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
  22. #include <string_view>
  23. #endif
  24. namespace boost {
  25. namespace multiprecision {
  26. #ifdef BOOST_MSVC
  27. // warning C4127: conditional expression is constant
  28. // warning C4714: function marked as __forceinline not inlined
  29. #pragma warning(push)
  30. #pragma warning(disable : 4127 4714 6326)
  31. #endif
  32. template <class Backend, expression_template_option ExpressionTemplates>
  33. class number
  34. {
  35. using self_type = number<Backend, ExpressionTemplates>;
  36. public:
  37. using backend_type = Backend ;
  38. using value_type = typename component_type<self_type>::type;
  39. BOOST_MP_FORCEINLINE constexpr number() noexcept(noexcept(Backend())) {}
  40. BOOST_MP_FORCEINLINE constexpr number(const number& e) noexcept(noexcept(Backend(std::declval<Backend const&>()))) : m_backend(e.m_backend) {}
  41. template <class V>
  42. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v, typename std::enable_if<
  43. (boost::multiprecision::detail::is_arithmetic<V>::value || std::is_same<std::string, V>::value || std::is_convertible<V, const char*>::value) && !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
  44. #ifdef BOOST_HAS_FLOAT128
  45. && !std::is_same<V, __float128>::value
  46. #endif
  47. >::type* = 0)
  48. {
  49. m_backend = canonical_value(v);
  50. }
  51. template <class V>
  52. BOOST_MP_FORCEINLINE constexpr number(const V& v, typename std::enable_if<
  53. std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = 0)
  54. #ifndef BOOST_INTEL
  55. noexcept(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))
  56. #endif
  57. : m_backend(canonical_value(v))
  58. {}
  59. template <class V>
  60. BOOST_MP_FORCEINLINE constexpr number(const V& v, unsigned digits10, typename std::enable_if<(boost::multiprecision::detail::is_arithmetic<V>::value || std::is_same<std::string, V>::value || std::is_convertible<V, const char*>::value) && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_complex) && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_rational)
  61. #ifdef BOOST_HAS_FLOAT128
  62. && !std::is_same<V, __float128>::value
  63. #endif
  64. >::type* = 0)
  65. : m_backend(canonical_value(v), digits10)
  66. {}
  67. BOOST_MP_FORCEINLINE constexpr number(const number& e, unsigned digits10)
  68. noexcept(noexcept(Backend(std::declval<Backend const&>(), std::declval<unsigned>())))
  69. : m_backend(e.m_backend, digits10) {}
  70. template <class V>
  71. explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v, typename std::enable_if<
  72. (boost::multiprecision::detail::is_arithmetic<V>::value || std::is_same<std::string, V>::value || std::is_convertible<V, const char*>::value) && !detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = 0)
  73. noexcept(noexcept(std::declval<Backend&>() = std::declval<typename detail::canonical<V, Backend>::type const&>()))
  74. {
  75. m_backend = canonical_value(v);
  76. }
  77. template <class V>
  78. explicit BOOST_MP_FORCEINLINE constexpr number(const V& v, typename std::enable_if<
  79. detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && (detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value || !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value)>::type* = 0)
  80. noexcept(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))
  81. : m_backend(canonical_value(v)) {}
  82. template <class V>
  83. explicit BOOST_MP_FORCEINLINE constexpr number(const V& v, unsigned digits10, typename std::enable_if<(boost::multiprecision::detail::is_arithmetic<V>::value || std::is_same<std::string, V>::value || std::is_convertible<V, const char*>::value) && detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_complex) && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_rational)>::type* = 0)
  84. : m_backend(canonical_value(v), digits10) {}
  85. template <expression_template_option ET>
  86. BOOST_MP_FORCEINLINE constexpr number(const number<Backend, ET>& val)
  87. noexcept(noexcept(Backend(std::declval<Backend const&>()))) : m_backend(val.backend()) {}
  88. template <class Other, expression_template_option ET>
  89. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val,
  90. typename std::enable_if<(std::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value)>::type* = 0)
  91. noexcept(noexcept(Backend(std::declval<Other const&>())))
  92. : m_backend(val.backend()) {}
  93. template <class Other, expression_template_option ET>
  94. explicit BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val, typename std::enable_if<
  95. (!detail::is_explicitly_convertible<Other, Backend>::value)>::type* = 0)
  96. {
  97. //
  98. // Attempt a generic interconvertion:
  99. //
  100. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard_1(val);
  101. detail::scoped_default_precision<number<Other, ET> > precision_guard_2(val);
  102. using detail::generic_interconvert;
  103. generic_interconvert(backend(), val.backend(), number_category<Backend>(), number_category<Other>());
  104. }
  105. template <class Other, expression_template_option ET>
  106. explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val, typename std::enable_if<
  107. (detail::is_explicitly_convertible<Other, Backend>::value && (detail::is_restricted_conversion<Other, Backend>::value || !std::is_convertible<Other, Backend>::value))>::type* = 0) noexcept(noexcept(Backend(std::declval<Other const&>())))
  108. : m_backend(val.backend()) {}
  109. template <class V, class U>
  110. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,
  111. typename std::enable_if<(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value && !std::is_same<typename component_type<self_type>::type, self_type>::value)>::type* = 0)
  112. {
  113. using default_ops::assign_components;
  114. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(v1, v2);
  115. assign_components(m_backend, canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)));
  116. }
  117. template <class V, class U>
  118. BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,
  119. typename std::enable_if<
  120. (std::is_constructible<value_type, V>::value || std::is_convertible<V, std::string>::value) && (std::is_constructible<value_type, U>::value || std::is_convertible<U, std::string>::value) && !std::is_same<typename component_type<self_type>::type, self_type>::value && !std::is_same<V, self_type>::value && !(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value)>::type* = 0)
  121. {
  122. using default_ops::assign_components;
  123. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(v1, v2);
  124. assign_components(m_backend, canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)));
  125. }
  126. #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
  127. //
  128. // Support for new types in C++17
  129. //
  130. template <class Traits>
  131. explicit inline BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view<char, Traits>& view)
  132. {
  133. using default_ops::assign_from_string_view;
  134. assign_from_string_view(this->backend(), view);
  135. }
  136. template <class Traits>
  137. explicit inline BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view<char, Traits>& view_x, const std::basic_string_view<char, Traits>& view_y)
  138. {
  139. using default_ops::assign_from_string_view;
  140. assign_from_string_view(this->backend(), view_x, view_y);
  141. }
  142. template <class Traits>
  143. explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const std::basic_string_view<char, Traits>& v, unsigned digits10)
  144. : m_backend(canonical_value(v), digits10) {}
  145. template <class Traits>
  146. BOOST_MP_CXX14_CONSTEXPR number& assign(const std::basic_string_view<char, Traits>& view)
  147. {
  148. using default_ops::assign_from_string_view;
  149. assign_from_string_view(this->backend(), view);
  150. return *this;
  151. }
  152. #endif
  153. template <class V, class U>
  154. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, unsigned digits10,
  155. typename std::enable_if<(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value && !std::is_same<typename component_type<self_type>::type, self_type>::value)>::type* = 0)
  156. : m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)), digits10)
  157. {}
  158. template <class V, class U>
  159. BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, unsigned digits10,
  160. typename std::enable_if<((std::is_constructible<value_type, V>::value || std::is_convertible<V, std::string>::value) && (std::is_constructible<value_type, U>::value || std::is_convertible<U, std::string>::value) && !std::is_same<typename component_type<self_type>::type, self_type>::value) && !(is_convertible<V, value_type>::value && is_convertible<U, value_type>::value)>::type* = 0)
  161. : m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)), digits10) {}
  162. template <class Other, expression_template_option ET>
  163. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& v1, const number<Other, ET>& v2, typename std::enable_if<std::is_convertible<Other, Backend>::value>::type* = 0)
  164. {
  165. using default_ops::assign_components;
  166. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(v1, v2);
  167. assign_components(m_backend, v1.backend(), v2.backend());
  168. }
  169. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  170. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
  171. {
  172. using tag_type = std::integral_constant<bool, is_equivalent_number_type<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value>;
  173. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(e);
  174. //
  175. // If the current precision of *this differs from that of expression e, then we
  176. // create a temporary (which will have the correct precision thanks to precision_guard)
  177. // and then move the result into *this. In C++17 we add a leading "if constexpr"
  178. // which causes this code to be eliminated in the common case that this type is
  179. // not actually variable precision. Pre C++17 this code should still be mostly
  180. // optimised away, but we can't prevent instantiation of the dead code leading
  181. // to longer build and possibly link times.
  182. //
  183. BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
  184. if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
  185. {
  186. number t(e);
  187. return *this = std::move(t);
  188. }
  189. do_assign(e, tag_type());
  190. return *this;
  191. }
  192. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  193. BOOST_MP_CXX14_CONSTEXPR number& assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
  194. {
  195. using tag_type = std::integral_constant<bool, is_equivalent_number_type<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value>;
  196. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(e);
  197. //
  198. // If the current precision of *this differs from that of expression e, then we
  199. // create a temporary (which will have the correct precision thanks to precision_guard)
  200. // and then move the result into *this. In C++17 we add a leading "if constexpr"
  201. // which causes this code to be eliminated in the common case that this type is
  202. // not actually variable precision. Pre C++17 this code should still be mostly
  203. // optimised away, but we can't prevent instantiation of the dead code leading
  204. // to longer build and possibly link times.
  205. //
  206. BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
  207. if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
  208. {
  209. number t;
  210. t.assign(e);
  211. return *this = std::move(t);
  212. }
  213. do_assign(e, tag_type());
  214. return *this;
  215. }
  216. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator=(const number& e)
  217. noexcept(noexcept(std::declval<Backend&>() = std::declval<Backend const&>()))
  218. {
  219. m_backend = e.m_backend;
  220. return *this;
  221. }
  222. template <class V>
  223. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
  224. operator=(const V& v)
  225. noexcept(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))
  226. {
  227. m_backend = canonical_value(v);
  228. return *this;
  229. }
  230. template <class V>
  231. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<Backend, ExpressionTemplates>& assign(const V& v)
  232. noexcept(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))
  233. {
  234. m_backend = canonical_value(v);
  235. return *this;
  236. }
  237. template <class V>
  238. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<Backend, ExpressionTemplates>& assign(const V& v, unsigned digits10)
  239. noexcept(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))
  240. {
  241. number t(v, digits10);
  242. return *this = t;
  243. }
  244. template <class Other, expression_template_option ET>
  245. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!boost::multiprecision::detail::is_explicitly_convertible<Other, Backend>::value, number<Backend, ExpressionTemplates>&>::type
  246. assign(const number<Other, ET>& v)
  247. {
  248. //
  249. // Attempt a generic interconvertion:
  250. //
  251. using detail::generic_interconvert;
  252. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(v);
  253. detail::scoped_default_precision<number<Other, ET> > precision_guard2(v);
  254. //
  255. // If the current precision of *this differs from that of value v, then we
  256. // create a temporary (which will have the correct precision thanks to precision_guard)
  257. // and then move the result into *this. In C++17 we add a leading "if constexpr"
  258. // which causes this code to be eliminated in the common case that this type is
  259. // not actually variable precision. Pre C++17 this code should still be mostly
  260. // optimised away, but we can't prevent instantiation of the dead code leading
  261. // to longer build and possibly link times.
  262. //
  263. BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
  264. if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
  265. {
  266. number t(v);
  267. return *this = std::move(t);
  268. }
  269. generic_interconvert(backend(), v.backend(), number_category<Backend>(), number_category<Other>());
  270. return *this;
  271. }
  272. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  273. BOOST_MP_CXX14_CONSTEXPR number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = 0)
  274. {
  275. //
  276. // No preicsion guard here, we already have one in operator=
  277. //
  278. *this = e;
  279. }
  280. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  281. explicit BOOST_MP_CXX14_CONSTEXPR number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e,
  282. typename std::enable_if<!std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value && boost::multiprecision::detail::is_explicitly_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = 0)
  283. {
  284. //
  285. // No precision guard as assign has one already:
  286. //
  287. assign(e);
  288. }
  289. // rvalues:
  290. BOOST_MP_FORCEINLINE constexpr number(number&& r)
  291. noexcept(noexcept(Backend(std::declval<Backend>())))
  292. : m_backend(static_cast<Backend&&>(r.m_backend))
  293. {}
  294. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator=(number&& r) noexcept(noexcept(std::declval<Backend&>() = std::declval<Backend>()))
  295. {
  296. m_backend = static_cast<Backend&&>(r.m_backend);
  297. return *this;
  298. }
  299. template <class Other, expression_template_option ET>
  300. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(number<Other, ET>&& val,
  301. typename std::enable_if<(std::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value)>::type* = 0)
  302. noexcept(noexcept(Backend(std::declval<Other const&>())))
  303. : m_backend(static_cast<number<Other, ET>&&>(val).backend()) {}
  304. template <class Other, expression_template_option ET>
  305. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(std::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value), number&>::type
  306. operator=(number<Other, ET>&& val)
  307. noexcept(noexcept(Backend(std::declval<Other const&>())))
  308. {
  309. m_backend = std::move(val).backend();
  310. return *this;
  311. }
  312. BOOST_MP_CXX14_CONSTEXPR number& operator+=(const self_type& val)
  313. {
  314. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, val);
  315. //
  316. // If the current precision of *this differs from that of expression e, then we
  317. // create a temporary (which will have the correct precision thanks to precision_guard)
  318. // and then move the result into *this. In C++17 we add a leading "if constexpr"
  319. // which causes this code to be eliminated in the common case that this type is
  320. // not actually variable precision. Pre C++17 this code should still be mostly
  321. // optimised away, but we can't prevent instantiation of the dead code leading
  322. // to longer build and possibly link times.
  323. //
  324. BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
  325. if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
  326. {
  327. number t(*this + val);
  328. return *this = std::move(t);
  329. }
  330. do_add(detail::expression<detail::terminal, self_type>(val), detail::terminal());
  331. return *this;
  332. }
  333. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  334. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator+=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
  335. {
  336. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
  337. // Create a copy if e contains this, but not if we're just doing a
  338. // x += x
  339. if ((contains_self(e) && !is_self(e)))
  340. {
  341. self_type temp(e);
  342. do_add(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
  343. }
  344. else
  345. {
  346. do_add(e, tag());
  347. }
  348. return *this;
  349. }
  350. template <class Arg1, class Arg2, class Arg3, class Arg4>
  351. BOOST_MP_CXX14_CONSTEXPR number& operator+=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)
  352. {
  353. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
  354. //
  355. // If the current precision of *this differs from that of expression e, then we
  356. // create a temporary (which will have the correct precision thanks to precision_guard)
  357. // and then move the result into *this. In C++17 we add a leading "if constexpr"
  358. // which causes this code to be eliminated in the common case that this type is
  359. // not actually variable precision. Pre C++17 this code should still be mostly
  360. // optimised away, but we can't prevent instantiation of the dead code leading
  361. // to longer build and possibly link times.
  362. //
  363. BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
  364. if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
  365. {
  366. number t(*this + e);
  367. return *this = std::move(t);
  368. }
  369. //
  370. // Fused multiply-add:
  371. //
  372. using default_ops::eval_multiply_add;
  373. eval_multiply_add(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref()));
  374. return *this;
  375. }
  376. template <class V>
  377. typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
  378. BOOST_MP_CXX14_CONSTEXPR operator+=(const V& v)
  379. {
  380. using default_ops::eval_add;
  381. eval_add(m_backend, canonical_value(v));
  382. return *this;
  383. }
  384. BOOST_MP_CXX14_CONSTEXPR number& operator-=(const self_type& val)
  385. {
  386. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, val);
  387. //
  388. // If the current precision of *this differs from that of expression e, then we
  389. // create a temporary (which will have the correct precision thanks to precision_guard)
  390. // and then move the result into *this. In C++17 we add a leading "if constexpr"
  391. // which causes this code to be eliminated in the common case that this type is
  392. // not actually variable precision. Pre C++17 this code should still be mostly
  393. // optimised away, but we can't prevent instantiation of the dead code leading
  394. // to longer build and possibly link times.
  395. //
  396. BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
  397. if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
  398. {
  399. number t(*this - val);
  400. return *this = std::move(t);
  401. }
  402. do_subtract(detail::expression<detail::terminal, self_type>(val), detail::terminal());
  403. return *this;
  404. }
  405. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  406. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator-=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
  407. {
  408. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
  409. // Create a copy if e contains this:
  410. if (contains_self(e))
  411. {
  412. self_type temp(e);
  413. do_subtract(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
  414. }
  415. else
  416. {
  417. do_subtract(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
  418. }
  419. return *this;
  420. }
  421. template <class V>
  422. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
  423. operator-=(const V& v)
  424. {
  425. using default_ops::eval_subtract;
  426. eval_subtract(m_backend, canonical_value(v));
  427. return *this;
  428. }
  429. template <class Arg1, class Arg2, class Arg3, class Arg4>
  430. BOOST_MP_CXX14_CONSTEXPR number& operator-=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)
  431. {
  432. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
  433. //
  434. // If the current precision of *this differs from that of expression e, then we
  435. // create a temporary (which will have the correct precision thanks to precision_guard)
  436. // and then move the result into *this. In C++17 we add a leading "if constexpr"
  437. // which causes this code to be eliminated in the common case that this type is
  438. // not actually variable precision. Pre C++17 this code should still be mostly
  439. // optimised away, but we can't prevent instantiation of the dead code leading
  440. // to longer build and possibly link times.
  441. //
  442. BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
  443. if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
  444. {
  445. number t(*this - e);
  446. return *this = std::move(t);
  447. }
  448. //
  449. // Fused multiply-subtract:
  450. //
  451. using default_ops::eval_multiply_subtract;
  452. eval_multiply_subtract(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref()));
  453. return *this;
  454. }
  455. BOOST_MP_CXX14_CONSTEXPR number& operator*=(const self_type& e)
  456. {
  457. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
  458. //
  459. // If the current precision of *this differs from that of expression e, then we
  460. // create a temporary (which will have the correct precision thanks to precision_guard)
  461. // and then move the result into *this. In C++17 we add a leading "if constexpr"
  462. // which causes this code to be eliminated in the common case that this type is
  463. // not actually variable precision. Pre C++17 this code should still be mostly
  464. // optimised away, but we can't prevent instantiation of the dead code leading
  465. // to longer build and possibly link times.
  466. //
  467. BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
  468. if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
  469. {
  470. number t(*this * e);
  471. return *this = std::move(t);
  472. }
  473. do_multiplies(detail::expression<detail::terminal, self_type>(e), detail::terminal());
  474. return *this;
  475. }
  476. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  477. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator*=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
  478. {
  479. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
  480. // Create a temporary if the RHS references *this, but not
  481. // if we're just doing an x *= x;
  482. if ((contains_self(e) && !is_self(e)))
  483. {
  484. self_type temp(e);
  485. do_multiplies(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
  486. }
  487. else
  488. {
  489. do_multiplies(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
  490. }
  491. return *this;
  492. }
  493. template <class V>
  494. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
  495. operator*=(const V& v)
  496. {
  497. using default_ops::eval_multiply;
  498. eval_multiply(m_backend, canonical_value(v));
  499. return *this;
  500. }
  501. BOOST_MP_CXX14_CONSTEXPR number& operator%=(const self_type& e)
  502. {
  503. static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
  504. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
  505. //
  506. // If the current precision of *this differs from that of expression e, then we
  507. // create a temporary (which will have the correct precision thanks to precision_guard)
  508. // and then move the result into *this. In C++17 we add a leading "if constexpr"
  509. // which causes this code to be eliminated in the common case that this type is
  510. // not actually variable precision. Pre C++17 this code should still be mostly
  511. // optimised away, but we can't prevent instantiation of the dead code leading
  512. // to longer build and possibly link times.
  513. //
  514. BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
  515. if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
  516. {
  517. number t(*this % e);
  518. return *this = std::move(t);
  519. }
  520. do_modulus(detail::expression<detail::terminal, self_type>(e), detail::terminal());
  521. return *this;
  522. }
  523. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  524. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator%=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
  525. {
  526. static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
  527. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
  528. // Create a temporary if the RHS references *this:
  529. if (contains_self(e))
  530. {
  531. self_type temp(e);
  532. do_modulus(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
  533. }
  534. else
  535. {
  536. do_modulus(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
  537. }
  538. return *this;
  539. }
  540. template <class V>
  541. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
  542. operator%=(const V& v)
  543. {
  544. static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
  545. using default_ops::eval_modulus;
  546. eval_modulus(m_backend, canonical_value(v));
  547. return *this;
  548. }
  549. //
  550. // These operators are *not* proto-ized.
  551. // The issue is that the increment/decrement must happen
  552. // even if the result of the operator *is never used*.
  553. // Possibly we could modify our expression wrapper to
  554. // execute the increment/decrement on destruction, but
  555. // correct implementation will be tricky, so defered for now...
  556. //
  557. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator++()
  558. {
  559. using default_ops::eval_increment;
  560. eval_increment(m_backend);
  561. return *this;
  562. }
  563. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator--()
  564. {
  565. using default_ops::eval_decrement;
  566. eval_decrement(m_backend);
  567. return *this;
  568. }
  569. inline BOOST_MP_CXX14_CONSTEXPR number operator++(int)
  570. {
  571. using default_ops::eval_increment;
  572. self_type temp(*this);
  573. eval_increment(m_backend);
  574. return temp;
  575. }
  576. inline BOOST_MP_CXX14_CONSTEXPR number operator--(int)
  577. {
  578. using default_ops::eval_decrement;
  579. self_type temp(*this);
  580. eval_decrement(m_backend);
  581. return temp;
  582. }
  583. template <class V>
  584. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<V>::value, number&>::type operator<<=(V val)
  585. {
  586. static_assert(number_category<Backend>::value == number_kind_integer, "The left-shift operation is only valid for integer types");
  587. detail::check_shift_range(val, std::integral_constant<bool, (sizeof(V) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<V>::value && boost::multiprecision::detail::is_integral<V>::value > ());
  588. eval_left_shift(m_backend, static_cast<std::size_t>(canonical_value(val)));
  589. return *this;
  590. }
  591. template <class V>
  592. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<V>::value, number&>::type operator>>=(V val)
  593. {
  594. static_assert(number_category<Backend>::value == number_kind_integer, "The right-shift operation is only valid for integer types");
  595. detail::check_shift_range(val, std::integral_constant<bool, (sizeof(V) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<V>::value && boost::multiprecision::detail::is_integral<V>::value>());
  596. eval_right_shift(m_backend, static_cast<std::size_t>(canonical_value(val)));
  597. return *this;
  598. }
  599. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator/=(const self_type& e)
  600. {
  601. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
  602. //
  603. // If the current precision of *this differs from that of expression e, then we
  604. // create a temporary (which will have the correct precision thanks to precision_guard)
  605. // and then move the result into *this. In C++17 we add a leading "if constexpr"
  606. // which causes this code to be eliminated in the common case that this type is
  607. // not actually variable precision. Pre C++17 this code should still be mostly
  608. // optimised away, but we can't prevent instantiation of the dead code leading
  609. // to longer build and possibly link times.
  610. //
  611. BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
  612. if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
  613. {
  614. number t(*this / e);
  615. return *this = std::move(t);
  616. }
  617. do_divide(detail::expression<detail::terminal, self_type>(e), detail::terminal());
  618. return *this;
  619. }
  620. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  621. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator/=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
  622. {
  623. detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(*this, e);
  624. // Create a temporary if the RHS references *this:
  625. if (contains_self(e))
  626. {
  627. self_type temp(e);
  628. do_divide(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
  629. }
  630. else
  631. {
  632. do_divide(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
  633. }
  634. return *this;
  635. }
  636. template <class V>
  637. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
  638. operator/=(const V& v)
  639. {
  640. using default_ops::eval_divide;
  641. eval_divide(m_backend, canonical_value(v));
  642. return *this;
  643. }
  644. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator&=(const self_type& e)
  645. {
  646. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
  647. do_bitwise_and(detail::expression<detail::terminal, self_type>(e), detail::terminal());
  648. return *this;
  649. }
  650. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  651. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator&=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
  652. {
  653. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
  654. // Create a temporary if the RHS references *this, but not
  655. // if we're just doing an x &= x;
  656. if (contains_self(e) && !is_self(e))
  657. {
  658. self_type temp(e);
  659. do_bitwise_and(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
  660. }
  661. else
  662. {
  663. do_bitwise_and(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
  664. }
  665. return *this;
  666. }
  667. template <class V>
  668. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
  669. operator&=(const V& v)
  670. {
  671. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
  672. using default_ops::eval_bitwise_and;
  673. eval_bitwise_and(m_backend, canonical_value(v));
  674. return *this;
  675. }
  676. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator|=(const self_type& e)
  677. {
  678. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
  679. do_bitwise_or(detail::expression<detail::terminal, self_type>(e), detail::terminal());
  680. return *this;
  681. }
  682. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  683. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator|=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
  684. {
  685. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
  686. // Create a temporary if the RHS references *this, but not
  687. // if we're just doing an x |= x;
  688. if (contains_self(e) && !is_self(e))
  689. {
  690. self_type temp(e);
  691. do_bitwise_or(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
  692. }
  693. else
  694. {
  695. do_bitwise_or(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
  696. }
  697. return *this;
  698. }
  699. template <class V>
  700. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
  701. operator|=(const V& v)
  702. {
  703. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
  704. using default_ops::eval_bitwise_or;
  705. eval_bitwise_or(m_backend, canonical_value(v));
  706. return *this;
  707. }
  708. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number& operator^=(const self_type& e)
  709. {
  710. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
  711. do_bitwise_xor(detail::expression<detail::terminal, self_type>(e), detail::terminal());
  712. return *this;
  713. }
  714. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  715. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value, number&>::type operator^=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
  716. {
  717. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
  718. if (contains_self(e))
  719. {
  720. self_type temp(e);
  721. do_bitwise_xor(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
  722. }
  723. else
  724. {
  725. do_bitwise_xor(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
  726. }
  727. return *this;
  728. }
  729. template <class V>
  730. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, self_type>::value, number<Backend, ExpressionTemplates>&>::type
  731. operator^=(const V& v)
  732. {
  733. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
  734. using default_ops::eval_bitwise_xor;
  735. eval_bitwise_xor(m_backend, canonical_value(v));
  736. return *this;
  737. }
  738. //
  739. // swap:
  740. //
  741. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void swap(self_type& other) noexcept(noexcept(std::declval<Backend>().swap(std::declval<Backend&>())))
  742. {
  743. m_backend.swap(other.backend());
  744. }
  745. //
  746. // Zero and sign:
  747. //
  748. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool is_zero() const
  749. {
  750. using default_ops::eval_is_zero;
  751. return eval_is_zero(m_backend);
  752. }
  753. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR int sign() const
  754. {
  755. using default_ops::eval_get_sign;
  756. return eval_get_sign(m_backend);
  757. }
  758. //
  759. // String conversion functions:
  760. //
  761. std::string str(std::streamsize digits = 0, std::ios_base::fmtflags f = std::ios_base::fmtflags(0)) const
  762. {
  763. return m_backend.str(digits, f);
  764. }
  765. template <class Archive>
  766. void serialize(Archive& ar, const unsigned int /*version*/)
  767. {
  768. ar& boost::make_nvp("backend", m_backend);
  769. }
  770. private:
  771. template <class T>
  772. BOOST_MP_CXX14_CONSTEXPR void convert_to_imp(T* result) const
  773. {
  774. using default_ops::eval_convert_to;
  775. eval_convert_to(result, m_backend);
  776. }
  777. template <class B2, expression_template_option ET>
  778. BOOST_MP_CXX14_CONSTEXPR void convert_to_imp(number<B2, ET>* result) const
  779. {
  780. result->assign(*this);
  781. }
  782. BOOST_MP_CXX14_CONSTEXPR void convert_to_imp(std::string* result) const
  783. {
  784. *result = this->str();
  785. }
  786. public:
  787. template <class T>
  788. BOOST_MP_CXX14_CONSTEXPR T convert_to() const
  789. {
  790. T result = T();
  791. convert_to_imp(&result);
  792. return result;
  793. }
  794. //
  795. // Use in boolean context, and explicit conversion operators:
  796. //
  797. #if BOOST_WORKAROUND(BOOST_MSVC, < 1900) || (defined(__apple_build_version__) && BOOST_WORKAROUND(__clang_major__, < 9))
  798. template <class T>
  799. #else
  800. template <class T, class = typename std::enable_if<!(std::is_constructible<T, self_type const&>::value || !std::is_default_constructible<T>::value || (!boost::multiprecision::detail::is_arithmetic<T>::value && !boost::multiprecision::detail::is_complex<T>::value)), T>::type>
  801. #endif
  802. explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
  803. {
  804. return this->template convert_to<T>();
  805. }
  806. BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
  807. {
  808. return !is_zero();
  809. }
  810. //
  811. // Default precision:
  812. //
  813. static BOOST_MP_CXX14_CONSTEXPR unsigned default_precision() noexcept
  814. {
  815. return Backend::default_precision();
  816. }
  817. static BOOST_MP_CXX14_CONSTEXPR void default_precision(unsigned digits10)
  818. {
  819. Backend::default_precision(digits10);
  820. }
  821. BOOST_MP_CXX14_CONSTEXPR unsigned precision() const noexcept
  822. {
  823. return m_backend.precision();
  824. }
  825. BOOST_MP_CXX14_CONSTEXPR void precision(unsigned digits10)
  826. {
  827. m_backend.precision(digits10);
  828. }
  829. //
  830. // Comparison:
  831. //
  832. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR int compare(const number<Backend, ExpressionTemplates>& o) const
  833. noexcept(noexcept(std::declval<Backend>().compare(std::declval<Backend>())))
  834. {
  835. return m_backend.compare(o.m_backend);
  836. }
  837. template <class V>
  838. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<V>::value && (number_category<Backend>::value != number_kind_complex), int>::type compare(const V& o) const
  839. {
  840. using default_ops::eval_get_sign;
  841. if (o == 0)
  842. return eval_get_sign(m_backend);
  843. return m_backend.compare(canonical_value(o));
  844. }
  845. template <class V>
  846. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<V>::value && (number_category<Backend>::value == number_kind_complex), int>::type compare(const V& o) const
  847. {
  848. using default_ops::eval_get_sign;
  849. return m_backend.compare(canonical_value(o));
  850. }
  851. //
  852. // Direct access to the underlying backend:
  853. //
  854. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR Backend& backend() & noexcept
  855. {
  856. return m_backend;
  857. }
  858. BOOST_MP_FORCEINLINE constexpr const Backend& backend() const& noexcept { return m_backend; }
  859. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR Backend&& backend() && noexcept { return static_cast<Backend&&>(m_backend); }
  860. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR Backend const&& backend() const&& noexcept { return static_cast<Backend const&&>(m_backend); }
  861. //
  862. // Complex number real and imag:
  863. //
  864. BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<number<Backend, ExpressionTemplates> >::type
  865. real() const
  866. {
  867. using default_ops::eval_real;
  868. detail::scoped_default_precision<typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type> precision_guard(*this);
  869. typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type result;
  870. eval_real(result.backend(), backend());
  871. return result;
  872. }
  873. BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<number<Backend, ExpressionTemplates> >::type
  874. imag() const
  875. {
  876. using default_ops::eval_imag;
  877. detail::scoped_default_precision<typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type> precision_guard(*this);
  878. typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type result;
  879. eval_imag(result.backend(), backend());
  880. return result;
  881. }
  882. template <class T>
  883. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<T, self_type>::value, self_type&>::type real(const T& val)
  884. {
  885. using default_ops::eval_set_real;
  886. eval_set_real(backend(), canonical_value(val));
  887. return *this;
  888. }
  889. template <class T>
  890. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<T, self_type>::value && number_category<self_type>::value == number_kind_complex, self_type&>::type imag(const T& val)
  891. {
  892. using default_ops::eval_set_imag;
  893. eval_set_imag(backend(), canonical_value(val));
  894. return *this;
  895. }
  896. private:
  897. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  898. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_assignable<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value>::type
  899. do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const std::integral_constant<bool, false>&)
  900. {
  901. // The result of the expression isn't the same type as this -
  902. // create a temporary result and assign it to *this:
  903. using temp_type = typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type;
  904. temp_type t(e);
  905. *this = std::move(t);
  906. }
  907. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  908. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_assignable<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value>::type
  909. do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const std::integral_constant<bool, false>&)
  910. {
  911. // The result of the expression isn't the same type as this -
  912. // create a temporary result and assign it to *this:
  913. using temp_type = typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type;
  914. temp_type t(e);
  915. this->assign(t);
  916. }
  917. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  918. BOOST_MP_CXX14_CONSTEXPR void do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const std::integral_constant<bool, true>&)
  919. {
  920. do_assign(e, tag());
  921. }
  922. template <class Exp>
  923. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::add_immediates&)
  924. {
  925. using default_ops::eval_add;
  926. boost::multiprecision::detail::maybe_promote_precision(this);
  927. eval_add(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
  928. }
  929. template <class Exp>
  930. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::subtract_immediates&)
  931. {
  932. using default_ops::eval_subtract;
  933. boost::multiprecision::detail::maybe_promote_precision(this);
  934. eval_subtract(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
  935. }
  936. template <class Exp>
  937. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiply_immediates&)
  938. {
  939. using default_ops::eval_multiply;
  940. boost::multiprecision::detail::maybe_promote_precision(this);
  941. eval_multiply(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
  942. }
  943. template <class Exp>
  944. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiply_add&)
  945. {
  946. using default_ops::eval_multiply_add;
  947. boost::multiprecision::detail::maybe_promote_precision(this);
  948. eval_multiply_add(m_backend, canonical_value(e.left().value()), canonical_value(e.middle().value()), canonical_value(e.right().value()));
  949. }
  950. template <class Exp>
  951. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiply_subtract&)
  952. {
  953. using default_ops::eval_multiply_subtract;
  954. boost::multiprecision::detail::maybe_promote_precision(this);
  955. eval_multiply_subtract(m_backend, canonical_value(e.left().value()), canonical_value(e.middle().value()), canonical_value(e.right().value()));
  956. }
  957. template <class Exp>
  958. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::divide_immediates&)
  959. {
  960. using default_ops::eval_divide;
  961. boost::multiprecision::detail::maybe_promote_precision(this);
  962. eval_divide(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
  963. }
  964. template <class Exp>
  965. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::negate&)
  966. {
  967. using left_type = typename Exp::left_type;
  968. do_assign(e.left(), typename left_type::tag_type());
  969. m_backend.negate();
  970. }
  971. template <class Exp>
  972. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::plus&)
  973. {
  974. using left_type = typename Exp::left_type ;
  975. using right_type = typename Exp::right_type;
  976. constexpr int const left_depth = left_type::depth;
  977. constexpr int const right_depth = right_type::depth;
  978. bool bl = contains_self(e.left());
  979. bool br = contains_self(e.right());
  980. if (bl && br)
  981. {
  982. self_type temp(e);
  983. temp.m_backend.swap(this->m_backend);
  984. }
  985. else if (bl && is_self(e.left()))
  986. {
  987. // Ignore the left node, it's *this, just add the right:
  988. do_add(e.right(), typename right_type::tag_type());
  989. }
  990. else if (br && is_self(e.right()))
  991. {
  992. // Ignore the right node, it's *this, just add the left:
  993. do_add(e.left(), typename left_type::tag_type());
  994. }
  995. else if (!br && (bl || (left_depth >= right_depth)))
  996. { // br is always false, but if bl is true we must take the this branch:
  997. do_assign(e.left(), typename left_type::tag_type());
  998. do_add(e.right(), typename right_type::tag_type());
  999. }
  1000. else
  1001. {
  1002. do_assign(e.right(), typename right_type::tag_type());
  1003. do_add(e.left(), typename left_type::tag_type());
  1004. }
  1005. }
  1006. template <class Exp>
  1007. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::minus&)
  1008. {
  1009. using left_type = typename Exp::left_type ;
  1010. using right_type = typename Exp::right_type;
  1011. constexpr int const left_depth = left_type::depth;
  1012. constexpr int const right_depth = right_type::depth;
  1013. bool bl = contains_self(e.left());
  1014. bool br = contains_self(e.right());
  1015. if (bl && br)
  1016. {
  1017. self_type temp(e);
  1018. temp.m_backend.swap(this->m_backend);
  1019. }
  1020. else if (bl && is_self(e.left()))
  1021. {
  1022. // Ignore the left node, it's *this, just subtract the right:
  1023. do_subtract(e.right(), typename right_type::tag_type());
  1024. }
  1025. else if (br && is_self(e.right()))
  1026. {
  1027. // Ignore the right node, it's *this, just subtract the left and negate the result:
  1028. do_subtract(e.left(), typename left_type::tag_type());
  1029. m_backend.negate();
  1030. }
  1031. else if (!br && (bl || (left_depth >= right_depth)))
  1032. { // br is always false, but if bl is true we must take the this branch:
  1033. do_assign(e.left(), typename left_type::tag_type());
  1034. do_subtract(e.right(), typename right_type::tag_type());
  1035. }
  1036. else
  1037. {
  1038. do_assign(e.right(), typename right_type::tag_type());
  1039. do_subtract(e.left(), typename left_type::tag_type());
  1040. m_backend.negate();
  1041. }
  1042. }
  1043. template <class Exp>
  1044. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::multiplies&)
  1045. {
  1046. using left_type = typename Exp::left_type ;
  1047. using right_type = typename Exp::right_type;
  1048. constexpr int const left_depth = left_type::depth;
  1049. constexpr int const right_depth = right_type::depth;
  1050. bool bl = contains_self(e.left());
  1051. bool br = contains_self(e.right());
  1052. if (bl && br)
  1053. {
  1054. self_type temp(e);
  1055. temp.m_backend.swap(this->m_backend);
  1056. }
  1057. else if (bl && is_self(e.left()))
  1058. {
  1059. // Ignore the left node, it's *this, just add the right:
  1060. do_multiplies(e.right(), typename right_type::tag_type());
  1061. }
  1062. else if (br && is_self(e.right()))
  1063. {
  1064. // Ignore the right node, it's *this, just add the left:
  1065. do_multiplies(e.left(), typename left_type::tag_type());
  1066. }
  1067. else if (!br && (bl || (left_depth >= right_depth)))
  1068. { // br is always false, but if bl is true we must take the this branch:
  1069. do_assign(e.left(), typename left_type::tag_type());
  1070. do_multiplies(e.right(), typename right_type::tag_type());
  1071. }
  1072. else
  1073. {
  1074. do_assign(e.right(), typename right_type::tag_type());
  1075. do_multiplies(e.left(), typename left_type::tag_type());
  1076. }
  1077. }
  1078. template <class Exp>
  1079. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::divides&)
  1080. {
  1081. using left_type = typename Exp::left_type ;
  1082. using right_type = typename Exp::right_type;
  1083. bool bl = contains_self(e.left());
  1084. bool br = contains_self(e.right());
  1085. if (bl && is_self(e.left()))
  1086. {
  1087. // Ignore the left node, it's *this, just add the right:
  1088. do_divide(e.right(), typename right_type::tag_type());
  1089. }
  1090. else if (br)
  1091. {
  1092. self_type temp(e);
  1093. temp.m_backend.swap(this->m_backend);
  1094. }
  1095. else
  1096. {
  1097. do_assign(e.left(), typename left_type::tag_type());
  1098. do_divide(e.right(), typename right_type::tag_type());
  1099. }
  1100. }
  1101. template <class Exp>
  1102. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::modulus&)
  1103. {
  1104. //
  1105. // This operation is only valid for integer backends:
  1106. //
  1107. static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
  1108. using left_type = typename Exp::left_type ;
  1109. using right_type = typename Exp::right_type;
  1110. bool bl = contains_self(e.left());
  1111. bool br = contains_self(e.right());
  1112. if (bl && is_self(e.left()))
  1113. {
  1114. // Ignore the left node, it's *this, just add the right:
  1115. do_modulus(e.right(), typename right_type::tag_type());
  1116. }
  1117. else if (br)
  1118. {
  1119. self_type temp(e);
  1120. temp.m_backend.swap(this->m_backend);
  1121. }
  1122. else
  1123. {
  1124. do_assign(e.left(), typename left_type::tag_type());
  1125. do_modulus(e.right(), typename right_type::tag_type());
  1126. }
  1127. }
  1128. template <class Exp>
  1129. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::modulus_immediates&)
  1130. {
  1131. static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
  1132. using default_ops::eval_modulus;
  1133. boost::multiprecision::detail::maybe_promote_precision(this);
  1134. eval_modulus(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
  1135. }
  1136. template <class Exp>
  1137. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_and&)
  1138. {
  1139. //
  1140. // This operation is only valid for integer backends:
  1141. //
  1142. static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
  1143. using left_type = typename Exp::left_type ;
  1144. using right_type = typename Exp::right_type;
  1145. constexpr int const left_depth = left_type::depth;
  1146. constexpr int const right_depth = right_type::depth;
  1147. bool bl = contains_self(e.left());
  1148. bool br = contains_self(e.right());
  1149. if (bl && is_self(e.left()))
  1150. {
  1151. // Ignore the left node, it's *this, just add the right:
  1152. do_bitwise_and(e.right(), typename right_type::tag_type());
  1153. }
  1154. else if (br && is_self(e.right()))
  1155. {
  1156. do_bitwise_and(e.left(), typename left_type::tag_type());
  1157. }
  1158. else if (!br && (bl || (left_depth >= right_depth)))
  1159. {
  1160. do_assign(e.left(), typename left_type::tag_type());
  1161. do_bitwise_and(e.right(), typename right_type::tag_type());
  1162. }
  1163. else
  1164. {
  1165. do_assign(e.right(), typename right_type::tag_type());
  1166. do_bitwise_and(e.left(), typename left_type::tag_type());
  1167. }
  1168. }
  1169. template <class Exp>
  1170. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_and_immediates&)
  1171. {
  1172. static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
  1173. using default_ops::eval_bitwise_and;
  1174. eval_bitwise_and(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
  1175. }
  1176. template <class Exp>
  1177. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_or&)
  1178. {
  1179. //
  1180. // This operation is only valid for integer backends:
  1181. //
  1182. static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
  1183. using left_type = typename Exp::left_type ;
  1184. using right_type = typename Exp::right_type;
  1185. constexpr int const left_depth = left_type::depth;
  1186. constexpr int const right_depth = right_type::depth;
  1187. bool bl = contains_self(e.left());
  1188. bool br = contains_self(e.right());
  1189. if (bl && is_self(e.left()))
  1190. {
  1191. // Ignore the left node, it's *this, just add the right:
  1192. do_bitwise_or(e.right(), typename right_type::tag_type());
  1193. }
  1194. else if (br && is_self(e.right()))
  1195. {
  1196. do_bitwise_or(e.left(), typename left_type::tag_type());
  1197. }
  1198. else if (!br && (bl || (left_depth >= right_depth)))
  1199. {
  1200. do_assign(e.left(), typename left_type::tag_type());
  1201. do_bitwise_or(e.right(), typename right_type::tag_type());
  1202. }
  1203. else
  1204. {
  1205. do_assign(e.right(), typename right_type::tag_type());
  1206. do_bitwise_or(e.left(), typename left_type::tag_type());
  1207. }
  1208. }
  1209. template <class Exp>
  1210. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_or_immediates&)
  1211. {
  1212. static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
  1213. using default_ops::eval_bitwise_or;
  1214. eval_bitwise_or(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
  1215. }
  1216. template <class Exp>
  1217. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_xor&)
  1218. {
  1219. //
  1220. // This operation is only valid for integer backends:
  1221. //
  1222. static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
  1223. using left_type = typename Exp::left_type ;
  1224. using right_type = typename Exp::right_type;
  1225. constexpr int const left_depth = left_type::depth;
  1226. constexpr int const right_depth = right_type::depth;
  1227. bool bl = contains_self(e.left());
  1228. bool br = contains_self(e.right());
  1229. if (bl && is_self(e.left()))
  1230. {
  1231. // Ignore the left node, it's *this, just add the right:
  1232. do_bitwise_xor(e.right(), typename right_type::tag_type());
  1233. }
  1234. else if (br && is_self(e.right()))
  1235. {
  1236. do_bitwise_xor(e.left(), typename left_type::tag_type());
  1237. }
  1238. else if (!br && (bl || (left_depth >= right_depth)))
  1239. {
  1240. do_assign(e.left(), typename left_type::tag_type());
  1241. do_bitwise_xor(e.right(), typename right_type::tag_type());
  1242. }
  1243. else
  1244. {
  1245. do_assign(e.right(), typename right_type::tag_type());
  1246. do_bitwise_xor(e.left(), typename left_type::tag_type());
  1247. }
  1248. }
  1249. template <class Exp>
  1250. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_xor_immediates&)
  1251. {
  1252. static_assert(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
  1253. using default_ops::eval_bitwise_xor;
  1254. eval_bitwise_xor(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
  1255. }
  1256. template <class Exp>
  1257. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::terminal&)
  1258. {
  1259. if (!is_self(e))
  1260. {
  1261. m_backend = canonical_value(e.value());
  1262. }
  1263. }
  1264. template <class Exp>
  1265. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::function&)
  1266. {
  1267. using tag_type = typename Exp::arity;
  1268. boost::multiprecision::detail::maybe_promote_precision(this);
  1269. do_assign_function(e, tag_type());
  1270. }
  1271. template <class Exp>
  1272. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::shift_left&)
  1273. {
  1274. // We can only shift by an integer value, not an arbitrary expression:
  1275. using left_type = typename Exp::left_type ;
  1276. using right_type = typename Exp::right_type ;
  1277. using right_arity = typename right_type::arity;
  1278. static_assert(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand.");
  1279. using right_value_type = typename right_type::result_type;
  1280. static_assert(boost::multiprecision::detail::is_integral<right_value_type>::value, "The left shift operator requires an integer value for the shift operand.");
  1281. using tag_type = typename left_type::tag_type;
  1282. do_assign_left_shift(e.left(), canonical_value(e.right().value()), tag_type());
  1283. }
  1284. template <class Exp>
  1285. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::shift_right&)
  1286. {
  1287. // We can only shift by an integer value, not an arbitrary expression:
  1288. using left_type = typename Exp::left_type ;
  1289. using right_type = typename Exp::right_type ;
  1290. using right_arity = typename right_type::arity;
  1291. static_assert(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand.");
  1292. using right_value_type = typename right_type::result_type;
  1293. static_assert(boost::multiprecision::detail::is_integral<right_value_type>::value, "The left shift operator requires an integer value for the shift operand.");
  1294. using tag_type = typename left_type::tag_type;
  1295. do_assign_right_shift(e.left(), canonical_value(e.right().value()), tag_type());
  1296. }
  1297. template <class Exp>
  1298. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::bitwise_complement&)
  1299. {
  1300. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types");
  1301. using default_ops::eval_complement;
  1302. self_type temp(e.left());
  1303. eval_complement(m_backend, temp.backend());
  1304. }
  1305. template <class Exp>
  1306. BOOST_MP_CXX14_CONSTEXPR void do_assign(const Exp& e, const detail::complement_immediates&)
  1307. {
  1308. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types");
  1309. using default_ops::eval_complement;
  1310. eval_complement(m_backend, canonical_value(e.left().value()));
  1311. }
  1312. template <class Exp, class Val>
  1313. BOOST_MP_CXX14_CONSTEXPR void do_assign_right_shift(const Exp& e, const Val& val, const detail::terminal&)
  1314. {
  1315. static_assert(number_category<Backend>::value == number_kind_integer, "The right shift operation is only valid for integer types");
  1316. using default_ops::eval_right_shift;
  1317. detail::check_shift_range(val, std::integral_constant<bool, (sizeof(Val) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<Val>::value&& boost::multiprecision::detail::is_integral<Val>::value>());
  1318. eval_right_shift(m_backend, canonical_value(e.value()), static_cast<std::size_t>(val));
  1319. }
  1320. template <class Exp, class Val>
  1321. BOOST_MP_CXX14_CONSTEXPR void do_assign_left_shift(const Exp& e, const Val& val, const detail::terminal&)
  1322. {
  1323. static_assert(number_category<Backend>::value == number_kind_integer, "The left shift operation is only valid for integer types");
  1324. using default_ops::eval_left_shift;
  1325. detail::check_shift_range(val, std::integral_constant<bool, (sizeof(Val) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<Val>::value&& boost::multiprecision::detail::is_integral<Val>::value>());
  1326. eval_left_shift(m_backend, canonical_value(e.value()), static_cast<std::size_t>(val));
  1327. }
  1328. template <class Exp, class Val, class Tag>
  1329. BOOST_MP_CXX14_CONSTEXPR void do_assign_right_shift(const Exp& e, const Val& val, const Tag&)
  1330. {
  1331. static_assert(number_category<Backend>::value == number_kind_integer, "The right shift operation is only valid for integer types");
  1332. using default_ops::eval_right_shift;
  1333. self_type temp(e);
  1334. detail::check_shift_range(val, std::integral_constant<bool, (sizeof(Val) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<Val>::value&& boost::multiprecision::detail::is_integral<Val>::value>());
  1335. eval_right_shift(m_backend, temp.backend(), static_cast<std::size_t>(val));
  1336. }
  1337. template <class Exp, class Val, class Tag>
  1338. BOOST_MP_CXX14_CONSTEXPR void do_assign_left_shift(const Exp& e, const Val& val, const Tag&)
  1339. {
  1340. static_assert(number_category<Backend>::value == number_kind_integer, "The left shift operation is only valid for integer types");
  1341. using default_ops::eval_left_shift;
  1342. self_type temp(e);
  1343. detail::check_shift_range(val, std::integral_constant<bool, (sizeof(Val) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<Val>::value&& boost::multiprecision::detail::is_integral<Val>::value>());
  1344. eval_left_shift(m_backend, temp.backend(), static_cast<std::size_t>(val));
  1345. }
  1346. template <class Exp>
  1347. BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const std::integral_constant<int, 1>&)
  1348. {
  1349. e.left().value()(&m_backend);
  1350. }
  1351. template <class Exp>
  1352. BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const std::integral_constant<int, 2>&)
  1353. {
  1354. using right_type = typename Exp::right_type ;
  1355. using tag_type = typename right_type::tag_type;
  1356. do_assign_function_1(e.left().value(), e.right_ref(), tag_type());
  1357. }
  1358. template <class F, class Exp>
  1359. BOOST_MP_CXX14_CONSTEXPR void do_assign_function_1(const F& f, const Exp& val, const detail::terminal&)
  1360. {
  1361. f(m_backend, function_arg_value(val));
  1362. }
  1363. template <class F, class Exp, class Tag>
  1364. BOOST_MP_CXX14_CONSTEXPR void do_assign_function_1(const F& f, const Exp& val, const Tag&)
  1365. {
  1366. typename Exp::result_type t(val);
  1367. f(m_backend, t.backend());
  1368. }
  1369. template <class Exp>
  1370. BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const std::integral_constant<int, 3>&)
  1371. {
  1372. using middle_type = typename Exp::middle_type ;
  1373. using tag_type = typename middle_type::tag_type;
  1374. using end_type = typename Exp::right_type ;
  1375. using end_tag = typename end_type::tag_type ;
  1376. do_assign_function_2(e.left().value(), e.middle_ref(), e.right_ref(), tag_type(), end_tag());
  1377. }
  1378. template <class F, class Exp1, class Exp2>
  1379. BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const detail::terminal&)
  1380. {
  1381. f(m_backend, function_arg_value(val1), function_arg_value(val2));
  1382. }
  1383. template <class F, class Exp1, class Exp2, class Tag1>
  1384. BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const detail::terminal&)
  1385. {
  1386. typename Exp1::result_type temp1(val1);
  1387. f(m_backend, std::move(temp1.backend()), function_arg_value(val2));
  1388. }
  1389. template <class F, class Exp1, class Exp2, class Tag2>
  1390. BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const Tag2&)
  1391. {
  1392. typename Exp2::result_type temp2(val2);
  1393. f(m_backend, function_arg_value(val1), std::move(temp2.backend()));
  1394. }
  1395. template <class F, class Exp1, class Exp2, class Tag1, class Tag2>
  1396. BOOST_MP_CXX14_CONSTEXPR void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const Tag2&)
  1397. {
  1398. typename Exp1::result_type temp1(val1);
  1399. typename Exp2::result_type temp2(val2);
  1400. f(m_backend, std::move(temp1.backend()), std::move(temp2.backend()));
  1401. }
  1402. template <class Exp>
  1403. BOOST_MP_CXX14_CONSTEXPR void do_assign_function(const Exp& e, const std::integral_constant<int, 4>&)
  1404. {
  1405. using left_type = typename Exp::left_middle_type ;
  1406. using left_tag_type = typename left_type::tag_type ;
  1407. using middle_type = typename Exp::right_middle_type;
  1408. using middle_tag_type = typename middle_type::tag_type ;
  1409. using right_type = typename Exp::right_type ;
  1410. using right_tag_type = typename right_type::tag_type ;
  1411. do_assign_function_3a(e.left().value(), e.left_middle_ref(), e.right_middle_ref(), e.right_ref(), left_tag_type(), middle_tag_type(), right_tag_type());
  1412. }
  1413. template <class F, class Exp1, class Exp2, class Exp3, class Tag2, class Tag3>
  1414. BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag2& t2, const Tag3& t3)
  1415. {
  1416. do_assign_function_3b(f, val1, val2, val3, t2, t3);
  1417. }
  1418. template <class F, class Exp1, class Exp2, class Exp3, class Tag1, class Tag2, class Tag3>
  1419. BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag1&, const Tag2& t2, const Tag3& t3)
  1420. {
  1421. typename Exp1::result_type t(val1);
  1422. do_assign_function_3b(f, std::move(t), val2, val3, t2, t3);
  1423. }
  1424. template <class F, class Exp1, class Exp2, class Exp3, class Tag3>
  1425. BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag3& t3)
  1426. {
  1427. do_assign_function_3c(f, val1, val2, val3, t3);
  1428. }
  1429. template <class F, class Exp1, class Exp2, class Exp3, class Tag2, class Tag3>
  1430. BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag2& /*t2*/, const Tag3& t3)
  1431. {
  1432. typename Exp2::result_type t(val2);
  1433. do_assign_function_3c(f, val1, std::move(t), val3, t3);
  1434. }
  1435. template <class F, class Exp1, class Exp2, class Exp3>
  1436. BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&)
  1437. {
  1438. f(m_backend, function_arg_value(val1), function_arg_value(val2), function_arg_value(val3));
  1439. }
  1440. template <class F, class Exp1, class Exp2, class Exp3, class Tag3>
  1441. BOOST_MP_CXX14_CONSTEXPR void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag3& /*t3*/)
  1442. {
  1443. typename Exp3::result_type t(val3);
  1444. do_assign_function_3c(f, val1, val2, std::move(t), detail::terminal());
  1445. }
  1446. template <class Exp>
  1447. BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::terminal&)
  1448. {
  1449. using default_ops::eval_add;
  1450. boost::multiprecision::detail::maybe_promote_precision(this);
  1451. eval_add(m_backend, canonical_value(e.value()));
  1452. }
  1453. template <class Exp>
  1454. BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::negate&)
  1455. {
  1456. using left_type = typename Exp::left_type;
  1457. boost::multiprecision::detail::maybe_promote_precision(this);
  1458. do_subtract(e.left(), typename left_type::tag_type());
  1459. }
  1460. template <class Exp>
  1461. BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::plus&)
  1462. {
  1463. using left_type = typename Exp::left_type ;
  1464. using right_type = typename Exp::right_type;
  1465. do_add(e.left(), typename left_type::tag_type());
  1466. do_add(e.right(), typename right_type::tag_type());
  1467. }
  1468. template <class Exp>
  1469. BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::minus&)
  1470. {
  1471. using left_type = typename Exp::left_type ;
  1472. using right_type = typename Exp::right_type;
  1473. do_add(e.left(), typename left_type::tag_type());
  1474. do_subtract(e.right(), typename right_type::tag_type());
  1475. }
  1476. template <class Exp, class unknown>
  1477. BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const unknown&)
  1478. {
  1479. self_type temp(e);
  1480. do_add(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
  1481. }
  1482. template <class Exp>
  1483. BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::add_immediates&)
  1484. {
  1485. using default_ops::eval_add;
  1486. boost::multiprecision::detail::maybe_promote_precision(this);
  1487. eval_add(m_backend, canonical_value(e.left().value()));
  1488. eval_add(m_backend, canonical_value(e.right().value()));
  1489. }
  1490. template <class Exp>
  1491. BOOST_MP_CXX14_CONSTEXPR void do_add(const Exp& e, const detail::subtract_immediates&)
  1492. {
  1493. using default_ops::eval_add;
  1494. using default_ops::eval_subtract;
  1495. boost::multiprecision::detail::maybe_promote_precision(this);
  1496. eval_add(m_backend, canonical_value(e.left().value()));
  1497. eval_subtract(m_backend, canonical_value(e.right().value()));
  1498. }
  1499. template <class Exp>
  1500. BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::terminal&)
  1501. {
  1502. using default_ops::eval_subtract;
  1503. boost::multiprecision::detail::maybe_promote_precision(this);
  1504. eval_subtract(m_backend, canonical_value(e.value()));
  1505. }
  1506. template <class Exp>
  1507. BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::negate&)
  1508. {
  1509. using left_type = typename Exp::left_type;
  1510. do_add(e.left(), typename left_type::tag_type());
  1511. }
  1512. template <class Exp>
  1513. BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::plus&)
  1514. {
  1515. using left_type = typename Exp::left_type ;
  1516. using right_type = typename Exp::right_type;
  1517. do_subtract(e.left(), typename left_type::tag_type());
  1518. do_subtract(e.right(), typename right_type::tag_type());
  1519. }
  1520. template <class Exp>
  1521. BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::minus&)
  1522. {
  1523. using left_type = typename Exp::left_type ;
  1524. using right_type = typename Exp::right_type;
  1525. do_subtract(e.left(), typename left_type::tag_type());
  1526. do_add(e.right(), typename right_type::tag_type());
  1527. }
  1528. template <class Exp>
  1529. BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::add_immediates&)
  1530. {
  1531. using default_ops::eval_subtract;
  1532. boost::multiprecision::detail::maybe_promote_precision(this);
  1533. eval_subtract(m_backend, canonical_value(e.left().value()));
  1534. eval_subtract(m_backend, canonical_value(e.right().value()));
  1535. }
  1536. template <class Exp>
  1537. BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const detail::subtract_immediates&)
  1538. {
  1539. using default_ops::eval_add;
  1540. using default_ops::eval_subtract;
  1541. eval_subtract(m_backend, canonical_value(e.left().value()));
  1542. eval_add(m_backend, canonical_value(e.right().value()));
  1543. }
  1544. template <class Exp, class unknown>
  1545. BOOST_MP_CXX14_CONSTEXPR void do_subtract(const Exp& e, const unknown&)
  1546. {
  1547. self_type temp(e);
  1548. do_subtract(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
  1549. }
  1550. template <class Exp>
  1551. BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::terminal&)
  1552. {
  1553. using default_ops::eval_multiply;
  1554. boost::multiprecision::detail::maybe_promote_precision(this);
  1555. eval_multiply(m_backend, canonical_value(e.value()));
  1556. }
  1557. template <class Exp>
  1558. BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::negate&)
  1559. {
  1560. using left_type = typename Exp::left_type;
  1561. do_multiplies(e.left(), typename left_type::tag_type());
  1562. m_backend.negate();
  1563. }
  1564. template <class Exp>
  1565. BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::multiplies&)
  1566. {
  1567. using left_type = typename Exp::left_type ;
  1568. using right_type = typename Exp::right_type;
  1569. do_multiplies(e.left(), typename left_type::tag_type());
  1570. do_multiplies(e.right(), typename right_type::tag_type());
  1571. }
  1572. //
  1573. // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
  1574. // the disable_if dependent on the template argument (the size of 1 can never occur in practice).
  1575. //
  1576. template <class Exp>
  1577. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
  1578. do_multiplies(const Exp& e, const detail::divides&)
  1579. {
  1580. using left_type = typename Exp::left_type ;
  1581. using right_type = typename Exp::right_type;
  1582. do_multiplies(e.left(), typename left_type::tag_type());
  1583. do_divide(e.right(), typename right_type::tag_type());
  1584. }
  1585. template <class Exp>
  1586. BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const detail::multiply_immediates&)
  1587. {
  1588. using default_ops::eval_multiply;
  1589. boost::multiprecision::detail::maybe_promote_precision(this);
  1590. eval_multiply(m_backend, canonical_value(e.left().value()));
  1591. eval_multiply(m_backend, canonical_value(e.right().value()));
  1592. }
  1593. //
  1594. // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
  1595. // the disable_if dependent on the template argument (the size of 1 can never occur in practice).
  1596. //
  1597. template <class Exp>
  1598. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
  1599. do_multiplies(const Exp& e, const detail::divide_immediates&)
  1600. {
  1601. using default_ops::eval_divide;
  1602. using default_ops::eval_multiply;
  1603. boost::multiprecision::detail::maybe_promote_precision(this);
  1604. eval_multiply(m_backend, canonical_value(e.left().value()));
  1605. eval_divide(m_backend, canonical_value(e.right().value()));
  1606. }
  1607. template <class Exp, class unknown>
  1608. BOOST_MP_CXX14_CONSTEXPR void do_multiplies(const Exp& e, const unknown&)
  1609. {
  1610. using default_ops::eval_multiply;
  1611. boost::multiprecision::detail::maybe_promote_precision(this);
  1612. self_type temp(e);
  1613. eval_multiply(m_backend, temp.m_backend);
  1614. }
  1615. template <class Exp>
  1616. BOOST_MP_CXX14_CONSTEXPR void do_divide(const Exp& e, const detail::terminal&)
  1617. {
  1618. using default_ops::eval_divide;
  1619. boost::multiprecision::detail::maybe_promote_precision(this);
  1620. eval_divide(m_backend, canonical_value(e.value()));
  1621. }
  1622. template <class Exp>
  1623. BOOST_MP_CXX14_CONSTEXPR void do_divide(const Exp& e, const detail::negate&)
  1624. {
  1625. using left_type = typename Exp::left_type;
  1626. do_divide(e.left(), typename left_type::tag_type());
  1627. m_backend.negate();
  1628. }
  1629. //
  1630. // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
  1631. // the disable_if dependent on the template argument (the size of 1 can never occur in practice).
  1632. //
  1633. template <class Exp>
  1634. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
  1635. do_divide(const Exp& e, const detail::multiplies&)
  1636. {
  1637. using left_type = typename Exp::left_type ;
  1638. using right_type = typename Exp::right_type;
  1639. do_divide(e.left(), typename left_type::tag_type());
  1640. do_divide(e.right(), typename right_type::tag_type());
  1641. }
  1642. //
  1643. // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
  1644. // the disable_if dependent on the template argument (the size of 1 can never occur in practice).
  1645. //
  1646. template <class Exp>
  1647. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
  1648. do_divide(const Exp& e, const detail::divides&)
  1649. {
  1650. using left_type = typename Exp::left_type ;
  1651. using right_type = typename Exp::right_type;
  1652. do_divide(e.left(), typename left_type::tag_type());
  1653. do_multiplies(e.right(), typename right_type::tag_type());
  1654. }
  1655. //
  1656. // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
  1657. // the disable_if dependent on the template argument (the size of 1 can never occur in practice).
  1658. //
  1659. template <class Exp>
  1660. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
  1661. do_divides(const Exp& e, const detail::multiply_immediates&)
  1662. {
  1663. using default_ops::eval_divide;
  1664. boost::multiprecision::detail::maybe_promote_precision(this);
  1665. eval_divide(m_backend, canonical_value(e.left().value()));
  1666. eval_divide(m_backend, canonical_value(e.right().value()));
  1667. }
  1668. //
  1669. // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
  1670. // the disable_if dependent on the template argument (the size of 1 can never occur in practice).
  1671. //
  1672. template <class Exp>
  1673. BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1)>::type
  1674. do_divides(const Exp& e, const detail::divide_immediates&)
  1675. {
  1676. using default_ops::eval_divide;
  1677. using default_ops::eval_multiply;
  1678. boost::multiprecision::detail::maybe_promote_precision(this);
  1679. eval_divide(m_backend, canonical_value(e.left().value()));
  1680. mutiply(m_backend, canonical_value(e.right().value()));
  1681. }
  1682. template <class Exp, class unknown>
  1683. BOOST_MP_CXX14_CONSTEXPR void do_divide(const Exp& e, const unknown&)
  1684. {
  1685. using default_ops::eval_multiply;
  1686. boost::multiprecision::detail::maybe_promote_precision(this);
  1687. self_type temp(e);
  1688. eval_divide(m_backend, temp.m_backend);
  1689. }
  1690. template <class Exp>
  1691. BOOST_MP_CXX14_CONSTEXPR void do_modulus(const Exp& e, const detail::terminal&)
  1692. {
  1693. static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
  1694. using default_ops::eval_modulus;
  1695. boost::multiprecision::detail::maybe_promote_precision(this);
  1696. eval_modulus(m_backend, canonical_value(e.value()));
  1697. }
  1698. template <class Exp, class Unknown>
  1699. BOOST_MP_CXX14_CONSTEXPR void do_modulus(const Exp& e, const Unknown&)
  1700. {
  1701. static_assert(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
  1702. using default_ops::eval_modulus;
  1703. boost::multiprecision::detail::maybe_promote_precision(this);
  1704. self_type temp(e);
  1705. eval_modulus(m_backend, canonical_value(temp));
  1706. }
  1707. template <class Exp>
  1708. BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const detail::terminal&)
  1709. {
  1710. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
  1711. using default_ops::eval_bitwise_and;
  1712. eval_bitwise_and(m_backend, canonical_value(e.value()));
  1713. }
  1714. template <class Exp>
  1715. BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const detail::bitwise_and&)
  1716. {
  1717. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
  1718. using left_type = typename Exp::left_type ;
  1719. using right_type = typename Exp::right_type;
  1720. do_bitwise_and(e.left(), typename left_type::tag_type());
  1721. do_bitwise_and(e.right(), typename right_type::tag_type());
  1722. }
  1723. template <class Exp, class unknown>
  1724. BOOST_MP_CXX14_CONSTEXPR void do_bitwise_and(const Exp& e, const unknown&)
  1725. {
  1726. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
  1727. using default_ops::eval_bitwise_and;
  1728. self_type temp(e);
  1729. eval_bitwise_and(m_backend, temp.m_backend);
  1730. }
  1731. template <class Exp>
  1732. BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const detail::terminal&)
  1733. {
  1734. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
  1735. using default_ops::eval_bitwise_or;
  1736. eval_bitwise_or(m_backend, canonical_value(e.value()));
  1737. }
  1738. template <class Exp>
  1739. BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const detail::bitwise_or&)
  1740. {
  1741. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
  1742. using left_type = typename Exp::left_type ;
  1743. using right_type = typename Exp::right_type;
  1744. do_bitwise_or(e.left(), typename left_type::tag_type());
  1745. do_bitwise_or(e.right(), typename right_type::tag_type());
  1746. }
  1747. template <class Exp, class unknown>
  1748. BOOST_MP_CXX14_CONSTEXPR void do_bitwise_or(const Exp& e, const unknown&)
  1749. {
  1750. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
  1751. using default_ops::eval_bitwise_or;
  1752. self_type temp(e);
  1753. eval_bitwise_or(m_backend, temp.m_backend);
  1754. }
  1755. template <class Exp>
  1756. BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const detail::terminal&)
  1757. {
  1758. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
  1759. using default_ops::eval_bitwise_xor;
  1760. eval_bitwise_xor(m_backend, canonical_value(e.value()));
  1761. }
  1762. template <class Exp>
  1763. BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const detail::bitwise_xor&)
  1764. {
  1765. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
  1766. using left_type = typename Exp::left_type ;
  1767. using right_type = typename Exp::right_type;
  1768. do_bitwise_xor(e.left(), typename left_type::tag_type());
  1769. do_bitwise_xor(e.right(), typename right_type::tag_type());
  1770. }
  1771. template <class Exp, class unknown>
  1772. BOOST_MP_CXX14_CONSTEXPR void do_bitwise_xor(const Exp& e, const unknown&)
  1773. {
  1774. static_assert(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
  1775. using default_ops::eval_bitwise_xor;
  1776. self_type temp(e);
  1777. eval_bitwise_xor(m_backend, temp.m_backend);
  1778. }
  1779. // Tests if the expression contains a reference to *this:
  1780. template <class Exp>
  1781. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e) const noexcept
  1782. {
  1783. return contains_self(e, typename Exp::arity());
  1784. }
  1785. template <class Exp>
  1786. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 0> const&) const noexcept
  1787. {
  1788. return is_realy_self(e.value());
  1789. }
  1790. template <class Exp>
  1791. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 1> const&) const noexcept
  1792. {
  1793. using child_type = typename Exp::left_type;
  1794. return contains_self(e.left(), typename child_type::arity());
  1795. }
  1796. template <class Exp>
  1797. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 2> const&) const noexcept
  1798. {
  1799. using child0_type = typename Exp::left_type ;
  1800. using child1_type = typename Exp::right_type;
  1801. return contains_self(e.left(), typename child0_type::arity()) || contains_self(e.right(), typename child1_type::arity());
  1802. }
  1803. template <class Exp>
  1804. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 3> const&) const noexcept
  1805. {
  1806. using child0_type = typename Exp::left_type ;
  1807. using child1_type = typename Exp::middle_type;
  1808. using child2_type = typename Exp::right_type ;
  1809. return contains_self(e.left(), typename child0_type::arity()) || contains_self(e.middle(), typename child1_type::arity()) || contains_self(e.right(), typename child2_type::arity());
  1810. }
  1811. // Test if the expression is a reference to *this:
  1812. template <class Exp>
  1813. BOOST_MP_FORCEINLINE constexpr bool is_self(const Exp& e) const noexcept
  1814. {
  1815. return is_self(e, typename Exp::arity());
  1816. }
  1817. template <class Exp>
  1818. BOOST_MP_FORCEINLINE constexpr bool is_self(const Exp& e, std::integral_constant<int, 0> const&) const noexcept
  1819. {
  1820. return is_realy_self(e.value());
  1821. }
  1822. template <class Exp, int v>
  1823. BOOST_MP_FORCEINLINE constexpr bool is_self(const Exp&, std::integral_constant<int, v> const&) const noexcept
  1824. {
  1825. return false;
  1826. }
  1827. template <class Val>
  1828. BOOST_MP_FORCEINLINE constexpr bool is_realy_self(const Val&) const noexcept { return false; }
  1829. BOOST_MP_FORCEINLINE constexpr bool is_realy_self(const self_type& v) const noexcept { return &v == this; }
  1830. static BOOST_MP_FORCEINLINE constexpr const Backend& function_arg_value(const self_type& v) noexcept { return v.backend(); }
  1831. template <class Other, expression_template_option ET2>
  1832. static BOOST_MP_FORCEINLINE constexpr const Other& function_arg_value(const number<Other, ET2>& v) noexcept { return v.backend(); }
  1833. template <class V>
  1834. static BOOST_MP_FORCEINLINE constexpr const V& function_arg_value(const V& v) noexcept { return v; }
  1835. template <class A1, class A2, class A3, class A4>
  1836. static BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR const A1& function_arg_value(const detail::expression<detail::terminal, A1, A2, A3, A4>& exp) noexcept { return exp.value(); }
  1837. template <class A2, class A3, class A4>
  1838. static BOOST_MP_FORCEINLINE constexpr const Backend& function_arg_value(const detail::expression<detail::terminal, number<Backend>, A2, A3, A4>& exp) noexcept { return exp.value().backend(); }
  1839. Backend m_backend;
  1840. public:
  1841. //
  1842. // These shouldn't really need to be public, or even member functions, but it makes implementing
  1843. // the non-member operators way easier if they are:
  1844. //
  1845. static BOOST_MP_FORCEINLINE constexpr const Backend& canonical_value(const self_type& v) noexcept { return v.m_backend; }
  1846. template <class B2, expression_template_option ET>
  1847. static BOOST_MP_FORCEINLINE constexpr const B2& canonical_value(const number<B2, ET>& v) noexcept { return v.backend(); }
  1848. template <class B2, expression_template_option ET>
  1849. static BOOST_MP_FORCEINLINE constexpr B2&& canonical_value(number<B2, ET>&& v) noexcept { return static_cast<number<B2, ET>&&>(v).backend(); }
  1850. template <class V>
  1851. static BOOST_MP_FORCEINLINE constexpr typename std::enable_if<!std::is_same<typename detail::canonical<V, Backend>::type, V>::value, typename detail::canonical<V, Backend>::type>::type
  1852. canonical_value(const V& v) noexcept { return static_cast<typename detail::canonical<V, Backend>::type>(v); }
  1853. template <class V>
  1854. static BOOST_MP_FORCEINLINE constexpr typename std::enable_if<std::is_same<typename detail::canonical<V, Backend>::type, V>::value, const V&>::type
  1855. canonical_value(const V& v) noexcept { return v; }
  1856. static BOOST_MP_FORCEINLINE typename detail::canonical<std::string, Backend>::type canonical_value(const std::string& v) noexcept { return v.c_str(); }
  1857. };
  1858. template <class Backend, expression_template_option ExpressionTemplates>
  1859. inline std::ostream& operator<<(std::ostream& os, const number<Backend, ExpressionTemplates>& r)
  1860. {
  1861. std::streamsize d = os.precision();
  1862. std::string s = r.str(d, os.flags());
  1863. std::streamsize ss = os.width();
  1864. if (ss > static_cast<std::streamsize>(s.size()))
  1865. {
  1866. char fill = os.fill();
  1867. if ((os.flags() & std::ios_base::left) == std::ios_base::left)
  1868. s.append(static_cast<std::string::size_type>(ss - s.size()), fill);
  1869. else
  1870. s.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(ss - s.size()), fill);
  1871. }
  1872. return os << s;
  1873. }
  1874. namespace detail {
  1875. template <class tag, class A1, class A2, class A3, class A4>
  1876. inline std::ostream& operator<<(std::ostream& os, const expression<tag, A1, A2, A3, A4>& r)
  1877. {
  1878. using value_type = typename expression<tag, A1, A2, A3, A4>::result_type;
  1879. value_type temp(r);
  1880. return os << temp;
  1881. }
  1882. //
  1883. // What follows is the input streaming code: this is not "proper" iostream code at all
  1884. // but that's fiendishly hard to write when dealing with multiple backends all
  1885. // with different requirements... yes we could deligate this to the backend author...
  1886. // but we really want backends to be EASY to write!
  1887. // For now just pull in all the characters that could possibly form the number
  1888. // and let the backend's string parser make use of it. This fixes most use cases
  1889. // including CSV type formats such as those used by the Random lib.
  1890. //
  1891. inline std::string read_string_while(std::istream& is, std::string const& permitted_chars)
  1892. {
  1893. std::ios_base::iostate state = std::ios_base::goodbit;
  1894. const std::istream::sentry sentry_check(is);
  1895. std::string result;
  1896. if (sentry_check)
  1897. {
  1898. int c = is.rdbuf()->sgetc();
  1899. for (;; c = is.rdbuf()->snextc())
  1900. if (std::istream::traits_type::eq_int_type(std::istream::traits_type::eof(), c))
  1901. { // end of file:
  1902. state |= std::ios_base::eofbit;
  1903. break;
  1904. }
  1905. else if (permitted_chars.find_first_of(std::istream::traits_type::to_char_type(c)) == std::string::npos)
  1906. {
  1907. // Invalid numeric character, stop reading:
  1908. //is.rdbuf()->sputbackc(static_cast<char>(c));
  1909. break;
  1910. }
  1911. else
  1912. {
  1913. result.append(1, std::istream::traits_type::to_char_type(c));
  1914. }
  1915. }
  1916. if (!result.size())
  1917. state |= std::ios_base::failbit;
  1918. is.setstate(state);
  1919. return result;
  1920. }
  1921. } // namespace detail
  1922. template <class Backend, expression_template_option ExpressionTemplates>
  1923. inline std::istream& operator>>(std::istream& is, number<Backend, ExpressionTemplates>& r)
  1924. {
  1925. bool hex_format = (is.flags() & std::ios_base::hex) == std::ios_base::hex;
  1926. bool oct_format = (is.flags() & std::ios_base::oct) == std::ios_base::oct;
  1927. std::string s;
  1928. switch (boost::multiprecision::number_category<number<Backend, ExpressionTemplates> >::value)
  1929. {
  1930. case boost::multiprecision::number_kind_integer:
  1931. if (oct_format)
  1932. s = detail::read_string_while(is, "+-01234567");
  1933. else if (hex_format)
  1934. s = detail::read_string_while(is, "+-xXabcdefABCDEF0123456789");
  1935. else
  1936. s = detail::read_string_while(is, "+-0123456789");
  1937. break;
  1938. case boost::multiprecision::number_kind_floating_point:
  1939. s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY");
  1940. break;
  1941. default:
  1942. is >> s;
  1943. }
  1944. if (s.size())
  1945. {
  1946. if (hex_format && (number_category<Backend>::value == number_kind_integer) && ((s[0] != '0') || (s[1] != 'x')))
  1947. s.insert(s.find_first_not_of("+-"), "0x");
  1948. if (oct_format && (number_category<Backend>::value == number_kind_integer) && (s[0] != '0'))
  1949. s.insert(s.find_first_not_of("+-"), "0");
  1950. r.assign(s);
  1951. }
  1952. else if (!is.fail())
  1953. is.setstate(std::istream::failbit);
  1954. return is;
  1955. }
  1956. template <class Backend, expression_template_option ExpressionTemplates>
  1957. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void swap(number<Backend, ExpressionTemplates>& a, number<Backend, ExpressionTemplates>& b)
  1958. noexcept(noexcept(std::declval<number<Backend, ExpressionTemplates>&>() = std::declval<number<Backend, ExpressionTemplates>&>()))
  1959. {
  1960. a.swap(b);
  1961. }
  1962. //
  1963. // Boost.Hash support, just call hash_value for the backend, which may or may not be supported:
  1964. //
  1965. template <class Backend, expression_template_option ExpressionTemplates>
  1966. inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const number<Backend, ExpressionTemplates>& val)
  1967. {
  1968. return hash_value(val.backend());
  1969. }
  1970. } // namespace multiprecision
  1971. template <class T>
  1972. class rational;
  1973. template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
  1974. inline std::istream& operator>>(std::istream& is, rational<multiprecision::number<Backend, ExpressionTemplates> >& r)
  1975. {
  1976. std::string s1;
  1977. multiprecision::number<Backend, ExpressionTemplates> v1, v2;
  1978. char c;
  1979. bool have_hex = false;
  1980. bool hex_format = (is.flags() & std::ios_base::hex) == std::ios_base::hex;
  1981. bool oct_format = (is.flags() & std::ios_base::oct) == std::ios_base::oct;
  1982. while ((EOF != (c = static_cast<char>(is.peek()))) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))
  1983. {
  1984. if (c == 'x' || c == 'X')
  1985. have_hex = true;
  1986. s1.append(1, c);
  1987. is.get();
  1988. }
  1989. if (hex_format && ((s1[0] != '0') || (s1[1] != 'x')))
  1990. s1.insert(static_cast<std::string::size_type>(0), "0x");
  1991. if (oct_format && (s1[0] != '0'))
  1992. s1.insert(static_cast<std::string::size_type>(0), "0");
  1993. v1.assign(s1);
  1994. s1.erase();
  1995. if (c == '/')
  1996. {
  1997. is.get();
  1998. while ((EOF != (c = static_cast<char>(is.peek()))) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))
  1999. {
  2000. if (c == 'x' || c == 'X')
  2001. have_hex = true;
  2002. s1.append(1, c);
  2003. is.get();
  2004. }
  2005. if (hex_format && ((s1[0] != '0') || (s1[1] != 'x')))
  2006. s1.insert(static_cast<std::string::size_type>(0), "0x");
  2007. if (oct_format && (s1[0] != '0'))
  2008. s1.insert(static_cast<std::string::size_type>(0), "0");
  2009. v2.assign(s1);
  2010. }
  2011. else
  2012. v2 = 1;
  2013. r.assign(v1, v2);
  2014. return is;
  2015. }
  2016. template <class T, multiprecision::expression_template_option ExpressionTemplates>
  2017. inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<T, ExpressionTemplates> numerator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
  2018. {
  2019. return a.numerator();
  2020. }
  2021. template <class T, multiprecision::expression_template_option ExpressionTemplates>
  2022. inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<T, ExpressionTemplates> denominator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
  2023. {
  2024. return a.denominator();
  2025. }
  2026. template <class T, multiprecision::expression_template_option ExpressionTemplates>
  2027. inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const rational<multiprecision::number<T, ExpressionTemplates> >& val)
  2028. {
  2029. std::size_t result = hash_value(val.numerator());
  2030. boost::hash_combine(result, hash_value(val.denominator()));
  2031. return result;
  2032. }
  2033. namespace multiprecision {
  2034. template <class I>
  2035. struct component_type<boost::rational<I> >
  2036. {
  2037. using type = I;
  2038. };
  2039. } // namespace multiprecision
  2040. #ifdef BOOST_MSVC
  2041. #pragma warning(pop)
  2042. #endif
  2043. } // namespace boost
  2044. namespace std {
  2045. template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
  2046. struct hash<boost::multiprecision::number<Backend, ExpressionTemplates> >
  2047. {
  2048. BOOST_MP_CXX14_CONSTEXPR std::size_t operator()(const boost::multiprecision::number<Backend, ExpressionTemplates>& val) const { return hash_value(val); }
  2049. };
  2050. template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
  2051. struct hash<boost::rational<boost::multiprecision::number<Backend, ExpressionTemplates> > >
  2052. {
  2053. BOOST_MP_CXX14_CONSTEXPR std::size_t operator()(const boost::rational<boost::multiprecision::number<Backend, ExpressionTemplates> >& val) const
  2054. {
  2055. std::size_t result = hash_value(val.numerator());
  2056. boost::hash_combine(result, hash_value(val.denominator()));
  2057. return result;
  2058. }
  2059. };
  2060. } // namespace std
  2061. #include <boost/multiprecision/detail/ublas_interop.hpp>
  2062. #endif