number.hpp 118 KB

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