number.hpp 95 KB

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