number_base.hpp 75 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806
  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_BIG_NUM_BASE_HPP
  6. #define BOOST_MATH_BIG_NUM_BASE_HPP
  7. #include <limits>
  8. #include <boost/utility/enable_if.hpp>
  9. #include <boost/core/nvp.hpp>
  10. #include <boost/type_traits/is_convertible.hpp>
  11. #include <boost/type_traits/is_constructible.hpp>
  12. #include <boost/type_traits/decay.hpp>
  13. #include <boost/math/tools/complex.hpp>
  14. #ifdef BOOST_MSVC
  15. #pragma warning(push)
  16. #pragma warning(disable : 4307)
  17. #endif
  18. #include <boost/lexical_cast.hpp>
  19. #ifdef BOOST_MSVC
  20. #pragma warning(pop)
  21. #endif
  22. #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || defined(BOOST_NO_CXX11_HDR_ARRAY)\
  23. || defined(BOOST_NO_CXX11_ALLOCATOR) || defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) || defined(BOOST_NO_CXX11_CONSTEXPR)\
  24. || defined(BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || defined(BOOST_NO_CXX11_REF_QUALIFIERS) || defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)\
  25. || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_USER_DEFINED_LITERALS) || defined(BOOST_NO_CXX11_THREAD_LOCAL)\
  26. || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_STATIC_ASSERT) || defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)\
  27. || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_REF_QUALIFIERS)
  28. //
  29. // The above list includes everything we use, plus a few we're likely to use soon.
  30. // As from March 2020, C++03 support is deprecated, and as from March 2021 will be removed,
  31. // so mark up as such:
  32. //
  33. #if (defined(_MSC_VER) || defined(__GNUC__)) && !defined(BOOST_MP_DISABLE_DEPRECATE_03_WARNING)
  34. #pragma message("CAUTION: One or more C++11 features were found to be unavailable")
  35. #pragma message("CAUTION: Compiling Boost.Multiprecision in non-C++11 or later conformance modes is now deprecated and will be removed from March 2021.")
  36. #pragma message("CAUTION: Define BOOST_MP_DISABLE_DEPRECATE_03_WARNING to suppress this message.")
  37. #endif
  38. #endif
  39. #if defined(NDEBUG) && !defined(_DEBUG)
  40. #define BOOST_MP_FORCEINLINE BOOST_FORCEINLINE
  41. #else
  42. #define BOOST_MP_FORCEINLINE inline
  43. #endif
  44. #if (defined(BOOST_GCC) && (BOOST_GCC <= 40700)) || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5140) || (defined(__clang_major__) && (__clang_major__ == 3) && (__clang_minor__ < 5))
  45. #define BOOST_MP_NOEXCEPT_IF(x)
  46. #else
  47. #define BOOST_MP_NOEXCEPT_IF(x) BOOST_NOEXCEPT_IF(x)
  48. #endif
  49. #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5140)
  50. #define BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
  51. #endif
  52. //
  53. // Thread local storage:
  54. // Note fails on Mingw, see https://sourceforge.net/p/mingw-w64/bugs/527/
  55. //
  56. #if !defined(BOOST_NO_CXX11_THREAD_LOCAL) && !defined(BOOST_INTEL) && !defined(__MINGW32__)
  57. #define BOOST_MP_THREAD_LOCAL thread_local
  58. #define BOOST_MP_USING_THREAD_LOCAL
  59. #else
  60. #define BOOST_MP_THREAD_LOCAL
  61. #endif
  62. #ifdef __has_include
  63. # if __has_include(<version>)
  64. # include <version>
  65. # ifdef __cpp_lib_is_constant_evaluated
  66. # include <type_traits>
  67. # define BOOST_MP_HAS_IS_CONSTANT_EVALUATED
  68. # endif
  69. # endif
  70. #endif
  71. #ifdef __has_builtin
  72. #if __has_builtin(__builtin_is_constant_evaluated) && !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
  73. #define BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED
  74. #endif
  75. #endif
  76. //
  77. // MSVC also supports __builtin_is_constant_evaluated if it's recent enough:
  78. //
  79. #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 192528326)
  80. # define BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED
  81. #endif
  82. //
  83. // As does GCC-9:
  84. //
  85. #if defined(BOOST_GCC) && !defined(BOOST_NO_CXX14_CONSTEXPR) && (__GNUC__ >= 9) && !defined(BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED)
  86. # define BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED
  87. #endif
  88. #if defined(BOOST_MP_HAS_IS_CONSTANT_EVALUATED) && !defined(BOOST_NO_CXX14_CONSTEXPR)
  89. # define BOOST_MP_IS_CONST_EVALUATED(x) std::is_constant_evaluated()
  90. #elif defined(BOOST_MP_HAS_BUILTIN_IS_CONSTANT_EVALUATED)
  91. # define BOOST_MP_IS_CONST_EVALUATED(x) __builtin_is_constant_evaluated()
  92. #elif !defined(BOOST_NO_CXX14_CONSTEXPR) && defined(BOOST_GCC) && (__GNUC__ >= 6)
  93. # define BOOST_MP_IS_CONST_EVALUATED(x) __builtin_constant_p(x)
  94. #else
  95. # define BOOST_MP_NO_CONSTEXPR_DETECTION
  96. #endif
  97. #define BOOST_MP_CXX14_CONSTEXPR BOOST_CXX14_CONSTEXPR
  98. //
  99. // Early compiler versions trip over the constexpr code:
  100. //
  101. #if defined(__clang__) && (__clang_major__ < 5)
  102. #undef BOOST_MP_CXX14_CONSTEXPR
  103. #define BOOST_MP_CXX14_CONSTEXPR
  104. #endif
  105. #if defined(__apple_build_version__) && (__clang_major__ < 9)
  106. #undef BOOST_MP_CXX14_CONSTEXPR
  107. #define BOOST_MP_CXX14_CONSTEXPR
  108. #endif
  109. #if defined(BOOST_GCC) && (__GNUC__ < 6)
  110. #undef BOOST_MP_CXX14_CONSTEXPR
  111. #define BOOST_MP_CXX14_CONSTEXPR
  112. #endif
  113. #if defined(BOOST_INTEL)
  114. #undef BOOST_MP_CXX14_CONSTEXPR
  115. #define BOOST_MP_CXX14_CONSTEXPR
  116. #define BOOST_MP_NO_CONSTEXPR_DETECTION
  117. #endif
  118. #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
  119. # define BOOST_CXX14_CONSTEXPR_IF_DETECTION
  120. #else
  121. # define BOOST_CXX14_CONSTEXPR_IF_DETECTION constexpr
  122. #endif
  123. #ifdef BOOST_MSVC
  124. #pragma warning(push)
  125. #pragma warning(disable : 6326)
  126. #endif
  127. namespace boost {
  128. namespace multiprecision {
  129. enum expression_template_option
  130. {
  131. et_off = 0,
  132. et_on = 1
  133. };
  134. template <class Backend>
  135. struct expression_template_default
  136. {
  137. static const expression_template_option value = et_on;
  138. };
  139. template <class Backend, expression_template_option ExpressionTemplates = expression_template_default<Backend>::value>
  140. class number;
  141. template <class T>
  142. struct is_number : public mpl::false_
  143. {};
  144. template <class Backend, expression_template_option ExpressionTemplates>
  145. struct is_number<number<Backend, ExpressionTemplates> > : public mpl::true_
  146. {};
  147. template <class T>
  148. struct is_et_number : public mpl::false_
  149. {};
  150. template <class Backend>
  151. struct is_et_number<number<Backend, et_on> > : public mpl::true_
  152. {};
  153. template <class T>
  154. struct is_no_et_number : public mpl::false_
  155. {};
  156. template <class Backend>
  157. struct is_no_et_number<number<Backend, et_off> > : public mpl::true_
  158. {};
  159. namespace detail {
  160. // Forward-declare an expression wrapper
  161. template <class tag, class Arg1 = void, class Arg2 = void, class Arg3 = void, class Arg4 = void>
  162. struct expression;
  163. } // namespace detail
  164. template <class T>
  165. struct is_number_expression : public mpl::false_
  166. {};
  167. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  168. struct is_number_expression<detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > : public mpl::true_
  169. {};
  170. template <class T, class Num>
  171. struct is_compatible_arithmetic_type
  172. : public mpl::bool_<
  173. is_convertible<T, Num>::value && !is_same<T, Num>::value && !is_number_expression<T>::value>
  174. {};
  175. namespace detail {
  176. //
  177. // Workaround for missing abs(boost::long_long_type) and abs(__int128) on some compilers:
  178. //
  179. template <class T>
  180. BOOST_CONSTEXPR typename enable_if_c<(is_signed<T>::value || is_floating_point<T>::value), T>::type abs(T t) BOOST_NOEXCEPT
  181. {
  182. // This strange expression avoids a hardware trap in the corner case
  183. // that val is the most negative value permitted in boost::long_long_type.
  184. // See https://svn.boost.org/trac/boost/ticket/9740.
  185. return t < 0 ? T(1u) + T(-(t + 1)) : t;
  186. }
  187. template <class T>
  188. BOOST_CONSTEXPR typename enable_if_c<(is_unsigned<T>::value), T>::type abs(T t) BOOST_NOEXCEPT
  189. {
  190. return t;
  191. }
  192. #define BOOST_MP_USING_ABS using boost::multiprecision::detail::abs;
  193. template <class T>
  194. BOOST_CONSTEXPR typename enable_if_c<(is_signed<T>::value || is_floating_point<T>::value), typename make_unsigned<T>::type>::type unsigned_abs(T t) BOOST_NOEXCEPT
  195. {
  196. // This strange expression avoids a hardware trap in the corner case
  197. // that val is the most negative value permitted in boost::long_long_type.
  198. // See https://svn.boost.org/trac/boost/ticket/9740.
  199. return t < 0 ? static_cast<typename make_unsigned<T>::type>(1u) + static_cast<typename make_unsigned<T>::type>(-(t + 1)) : static_cast<typename make_unsigned<T>::type>(t);
  200. }
  201. template <class T>
  202. BOOST_CONSTEXPR typename enable_if_c<(is_unsigned<T>::value), T>::type unsigned_abs(T t) BOOST_NOEXCEPT
  203. {
  204. return t;
  205. }
  206. //
  207. // Move support:
  208. //
  209. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  210. #define BOOST_MP_MOVE(x) std::move(x)
  211. #else
  212. #define BOOST_MP_MOVE(x) x
  213. #endif
  214. template <class T>
  215. struct bits_of
  216. {
  217. BOOST_STATIC_ASSERT(is_integral<T>::value || is_enum<T>::value || std::numeric_limits<T>::is_specialized);
  218. static const unsigned value =
  219. std::numeric_limits<T>::is_specialized ? std::numeric_limits<T>::digits
  220. : sizeof(T) * CHAR_BIT - (is_signed<T>::value ? 1 : 0);
  221. };
  222. #if defined(_GLIBCXX_USE_FLOAT128) && defined(BOOST_GCC) && !defined(__STRICT_ANSI__)
  223. #define BOOST_MP_BITS_OF_FLOAT128_DEFINED
  224. template <>
  225. struct bits_of<__float128>
  226. {
  227. static const unsigned value = 113;
  228. };
  229. #endif
  230. template <int b>
  231. struct has_enough_bits
  232. {
  233. template <class T>
  234. struct type : public mpl::bool_<bits_of<T>::value >= b>
  235. {};
  236. };
  237. template <class Val, class Backend, class Tag>
  238. struct canonical_imp
  239. {
  240. typedef typename remove_cv<typename decay<const Val>::type>::type type;
  241. };
  242. template <class B, class Backend, class Tag>
  243. struct canonical_imp<number<B, et_on>, Backend, Tag>
  244. {
  245. typedef B type;
  246. };
  247. template <class B, class Backend, class Tag>
  248. struct canonical_imp<number<B, et_off>, Backend, Tag>
  249. {
  250. typedef B type;
  251. };
  252. #ifdef __SUNPRO_CC
  253. template <class B, class Backend>
  254. struct canonical_imp<number<B, et_on>, Backend, mpl::int_<3> >
  255. {
  256. typedef B type;
  257. };
  258. template <class B, class Backend>
  259. struct canonical_imp<number<B, et_off>, Backend, mpl::int_<3> >
  260. {
  261. typedef B type;
  262. };
  263. #endif
  264. template <class Val, class Backend>
  265. struct canonical_imp<Val, Backend, mpl::int_<0> >
  266. {
  267. typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
  268. typedef typename mpl::find_if<
  269. typename Backend::signed_types,
  270. pred_type>::type iter_type;
  271. typedef typename mpl::end<typename Backend::signed_types>::type end_type;
  272. typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
  273. };
  274. template <class Val, class Backend>
  275. struct canonical_imp<Val, Backend, mpl::int_<1> >
  276. {
  277. typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
  278. typedef typename mpl::find_if<
  279. typename Backend::unsigned_types,
  280. pred_type>::type iter_type;
  281. typedef typename mpl::end<typename Backend::unsigned_types>::type end_type;
  282. typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
  283. };
  284. template <class Val, class Backend>
  285. struct canonical_imp<Val, Backend, mpl::int_<2> >
  286. {
  287. typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
  288. typedef typename mpl::find_if<
  289. typename Backend::float_types,
  290. pred_type>::type iter_type;
  291. typedef typename mpl::end<typename Backend::float_types>::type end_type;
  292. typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
  293. };
  294. template <class Val, class Backend>
  295. struct canonical_imp<Val, Backend, mpl::int_<3> >
  296. {
  297. typedef const char* type;
  298. };
  299. template <class Val, class Backend>
  300. struct canonical
  301. {
  302. typedef typename mpl::if_<
  303. is_signed<Val>,
  304. mpl::int_<0>,
  305. typename mpl::if_<
  306. is_unsigned<Val>,
  307. mpl::int_<1>,
  308. typename mpl::if_<
  309. is_floating_point<Val>,
  310. mpl::int_<2>,
  311. typename mpl::if_<
  312. mpl::or_<
  313. is_convertible<Val, const char*>,
  314. is_same<Val, std::string> >,
  315. mpl::int_<3>,
  316. mpl::int_<4> >::type>::type>::type>::type tag_type;
  317. typedef typename canonical_imp<Val, Backend, tag_type>::type type;
  318. };
  319. struct terminal
  320. {};
  321. struct negate
  322. {};
  323. struct plus
  324. {};
  325. struct minus
  326. {};
  327. struct multiplies
  328. {};
  329. struct divides
  330. {};
  331. struct modulus
  332. {};
  333. struct shift_left
  334. {};
  335. struct shift_right
  336. {};
  337. struct bitwise_and
  338. {};
  339. struct bitwise_or
  340. {};
  341. struct bitwise_xor
  342. {};
  343. struct bitwise_complement
  344. {};
  345. struct add_immediates
  346. {};
  347. struct subtract_immediates
  348. {};
  349. struct multiply_immediates
  350. {};
  351. struct divide_immediates
  352. {};
  353. struct modulus_immediates
  354. {};
  355. struct bitwise_and_immediates
  356. {};
  357. struct bitwise_or_immediates
  358. {};
  359. struct bitwise_xor_immediates
  360. {};
  361. struct complement_immediates
  362. {};
  363. struct function
  364. {};
  365. struct multiply_add
  366. {};
  367. struct multiply_subtract
  368. {};
  369. template <class T>
  370. struct backend_type;
  371. template <class T, expression_template_option ExpressionTemplates>
  372. struct backend_type<number<T, ExpressionTemplates> >
  373. {
  374. typedef T type;
  375. };
  376. template <class tag, class A1, class A2, class A3, class A4>
  377. struct backend_type<expression<tag, A1, A2, A3, A4> >
  378. {
  379. typedef typename backend_type<typename expression<tag, A1, A2, A3, A4>::result_type>::type type;
  380. };
  381. template <class T1, class T2>
  382. struct combine_expression
  383. {
  384. #ifdef BOOST_NO_CXX11_DECLTYPE
  385. typedef typename mpl::if_c<(sizeof(T1() + T2()) == sizeof(T1)), T1, T2>::type type;
  386. #else
  387. typedef decltype(T1() + T2()) type;
  388. #endif
  389. };
  390. template <class T1, expression_template_option ExpressionTemplates, class T2>
  391. struct combine_expression<number<T1, ExpressionTemplates>, T2>
  392. {
  393. typedef number<T1, ExpressionTemplates> type;
  394. };
  395. template <class T1, class T2, expression_template_option ExpressionTemplates>
  396. struct combine_expression<T1, number<T2, ExpressionTemplates> >
  397. {
  398. typedef number<T2, ExpressionTemplates> type;
  399. };
  400. template <class T, expression_template_option ExpressionTemplates>
  401. struct combine_expression<number<T, ExpressionTemplates>, number<T, ExpressionTemplates> >
  402. {
  403. typedef number<T, ExpressionTemplates> type;
  404. };
  405. template <class T1, expression_template_option ExpressionTemplates1, class T2, expression_template_option ExpressionTemplates2>
  406. struct combine_expression<number<T1, ExpressionTemplates1>, number<T2, ExpressionTemplates2> >
  407. {
  408. typedef typename mpl::if_c<
  409. is_convertible<number<T2, ExpressionTemplates2>, number<T1, ExpressionTemplates2> >::value,
  410. number<T1, ExpressionTemplates1>,
  411. number<T2, ExpressionTemplates2> >::type type;
  412. };
  413. template <class T>
  414. struct arg_type
  415. {
  416. typedef expression<terminal, T> type;
  417. };
  418. template <class Tag, class Arg1, class Arg2, class Arg3, class Arg4>
  419. struct arg_type<expression<Tag, Arg1, Arg2, Arg3, Arg4> >
  420. {
  421. typedef expression<Tag, Arg1, Arg2, Arg3, Arg4> type;
  422. };
  423. struct unmentionable
  424. {
  425. unmentionable* proc() { return 0; }
  426. };
  427. typedef unmentionable* (unmentionable::*unmentionable_type)();
  428. template <class T, bool b>
  429. struct expression_storage_base
  430. {
  431. typedef const T& type;
  432. };
  433. template <class T>
  434. struct expression_storage_base<T, true>
  435. {
  436. typedef T type;
  437. };
  438. template <class T>
  439. struct expression_storage : public expression_storage_base<T, boost::is_arithmetic<T>::value>
  440. {};
  441. template <class T>
  442. struct expression_storage<T*>
  443. {
  444. typedef T* type;
  445. };
  446. template <class T>
  447. struct expression_storage<const T*>
  448. {
  449. typedef const T* type;
  450. };
  451. template <class tag, class A1, class A2, class A3, class A4>
  452. struct expression_storage<expression<tag, A1, A2, A3, A4> >
  453. {
  454. typedef expression<tag, A1, A2, A3, A4> type;
  455. };
  456. template <class tag, class Arg1>
  457. struct expression<tag, Arg1, void, void, void>
  458. {
  459. typedef mpl::int_<1> arity;
  460. typedef typename arg_type<Arg1>::type left_type;
  461. typedef typename left_type::result_type left_result_type;
  462. typedef typename left_type::result_type result_type;
  463. typedef tag tag_type;
  464. explicit BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a) : arg(a) {}
  465. BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg(e.arg) {}
  466. #ifndef BOOST_NO_CXX11_STATIC_ASSERT
  467. //
  468. // If we have static_assert we can give a more useful error message
  469. // than if we simply have no operator defined at all:
  470. //
  471. template <class Other>
  472. BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
  473. {
  474. // This should always fail:
  475. static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  476. return *this;
  477. }
  478. BOOST_MP_CXX14_CONSTEXPR expression& operator++()
  479. {
  480. // This should always fail:
  481. static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  482. return *this;
  483. }
  484. BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
  485. {
  486. // This should always fail:
  487. static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  488. return *this;
  489. }
  490. BOOST_MP_CXX14_CONSTEXPR expression& operator--()
  491. {
  492. // This should always fail:
  493. static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  494. return *this;
  495. }
  496. BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
  497. {
  498. // This should always fail:
  499. static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  500. return *this;
  501. }
  502. template <class Other>
  503. BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
  504. {
  505. // This should always fail:
  506. static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  507. return *this;
  508. }
  509. template <class Other>
  510. BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
  511. {
  512. // This should always fail:
  513. static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  514. return *this;
  515. }
  516. template <class Other>
  517. BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
  518. {
  519. // This should always fail:
  520. static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  521. return *this;
  522. }
  523. template <class Other>
  524. BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
  525. {
  526. // This should always fail:
  527. static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  528. return *this;
  529. }
  530. template <class Other>
  531. BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
  532. {
  533. // This should always fail:
  534. static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  535. return *this;
  536. }
  537. template <class Other>
  538. BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
  539. {
  540. // This should always fail:
  541. static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  542. return *this;
  543. }
  544. template <class Other>
  545. BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
  546. {
  547. // This should always fail:
  548. static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  549. return *this;
  550. }
  551. template <class Other>
  552. BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
  553. {
  554. // This should always fail:
  555. static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  556. return *this;
  557. }
  558. template <class Other>
  559. BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
  560. {
  561. // This should always fail:
  562. static_assert(sizeof(Other) == INT_MAX, "You can not use operator<<= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  563. return *this;
  564. }
  565. template <class Other>
  566. BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
  567. {
  568. // This should always fail:
  569. static_assert(sizeof(Other) == INT_MAX, "You can not use operator>>= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  570. return *this;
  571. }
  572. #endif
  573. BOOST_MP_CXX14_CONSTEXPR left_type left() const
  574. {
  575. return left_type(arg);
  576. }
  577. BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg; }
  578. static const unsigned depth = left_type::depth + 1;
  579. #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
  580. #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
  581. //
  582. // Horrible workaround for gcc-4.6.x which always prefers the template
  583. // operator bool() rather than the non-template operator when converting to
  584. // an arithmetic type:
  585. //
  586. template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
  587. explicit operator T() const
  588. {
  589. result_type r(*this);
  590. return static_cast<bool>(r);
  591. }
  592. template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
  593. explicit operator T() const
  594. {
  595. return static_cast<T>(static_cast<result_type>(*this));
  596. }
  597. #else
  598. template <class T
  599. #ifndef __SUNPRO_CC
  600. ,
  601. typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value || !is_constructible<T, result_type>::value, int>::type = 0
  602. #endif
  603. >
  604. explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
  605. {
  606. return static_cast<T>(static_cast<result_type>(*this));
  607. }
  608. BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
  609. {
  610. result_type r(*this);
  611. return static_cast<bool>(r);
  612. }
  613. #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
  614. BOOST_MP_FORCEINLINE explicit operator void() const
  615. {}
  616. #endif
  617. #endif
  618. #else
  619. operator unmentionable_type() const
  620. {
  621. result_type r(*this);
  622. return r ? &unmentionable::proc : 0;
  623. }
  624. #endif
  625. template <class T>
  626. BOOST_MP_CXX14_CONSTEXPR T convert_to()
  627. {
  628. result_type r(*this);
  629. return r.template convert_to<T>();
  630. }
  631. private:
  632. typename expression_storage<Arg1>::type arg;
  633. expression& operator=(const expression&);
  634. };
  635. template <class Arg1>
  636. struct expression<terminal, Arg1, void, void, void>
  637. {
  638. typedef mpl::int_<0> arity;
  639. typedef Arg1 result_type;
  640. typedef terminal tag_type;
  641. explicit BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a) : arg(a) {}
  642. BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg(e.arg) {}
  643. #ifndef BOOST_NO_CXX11_STATIC_ASSERT
  644. //
  645. // If we have static_assert we can give a more useful error message
  646. // than if we simply have no operator defined at all:
  647. //
  648. template <class Other>
  649. BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
  650. {
  651. // This should always fail:
  652. static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  653. return *this;
  654. }
  655. BOOST_MP_CXX14_CONSTEXPR expression& operator++()
  656. {
  657. // This should always fail:
  658. static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  659. return *this;
  660. }
  661. BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
  662. {
  663. // This should always fail:
  664. static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  665. return *this;
  666. }
  667. BOOST_MP_CXX14_CONSTEXPR expression& operator--()
  668. {
  669. // This should always fail:
  670. static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  671. return *this;
  672. }
  673. BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
  674. {
  675. // This should always fail:
  676. static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  677. return *this;
  678. }
  679. template <class Other>
  680. BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
  681. {
  682. // This should always fail:
  683. static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  684. return *this;
  685. }
  686. template <class Other>
  687. BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
  688. {
  689. // This should always fail:
  690. static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  691. return *this;
  692. }
  693. template <class Other>
  694. BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
  695. {
  696. // This should always fail:
  697. static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  698. return *this;
  699. }
  700. template <class Other>
  701. BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
  702. {
  703. // This should always fail:
  704. static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  705. return *this;
  706. }
  707. template <class Other>
  708. BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
  709. {
  710. // This should always fail:
  711. static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  712. return *this;
  713. }
  714. template <class Other>
  715. BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
  716. {
  717. // This should always fail:
  718. static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  719. return *this;
  720. }
  721. template <class Other>
  722. BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
  723. {
  724. // This should always fail:
  725. static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  726. return *this;
  727. }
  728. template <class Other>
  729. BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
  730. {
  731. // This should always fail:
  732. static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  733. return *this;
  734. }
  735. template <class Other>
  736. BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
  737. {
  738. // This should always fail:
  739. static_assert(sizeof(Other) == INT_MAX, "You can not use operator<<= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  740. return *this;
  741. }
  742. template <class Other>
  743. BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
  744. {
  745. // This should always fail:
  746. static_assert(sizeof(Other) == INT_MAX, "You can not use operator>>= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  747. return *this;
  748. }
  749. #endif
  750. BOOST_MP_CXX14_CONSTEXPR const Arg1& value() const BOOST_NOEXCEPT
  751. {
  752. return arg;
  753. }
  754. static const unsigned depth = 0;
  755. #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
  756. #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
  757. //
  758. // Horrible workaround for gcc-4.6.x which always prefers the template
  759. // operator bool() rather than the non-template operator when converting to
  760. // an arithmetic type:
  761. //
  762. template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
  763. explicit operator T() const
  764. {
  765. result_type r(*this);
  766. return static_cast<bool>(r);
  767. }
  768. template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
  769. explicit operator T() const
  770. {
  771. return static_cast<T>(static_cast<result_type>(*this));
  772. }
  773. #else
  774. template <class T
  775. #ifndef __SUNPRO_CC
  776. ,
  777. typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value || !is_constructible<T, result_type>::value, int>::type = 0
  778. #endif
  779. >
  780. explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
  781. {
  782. return static_cast<T>(static_cast<result_type>(*this));
  783. }
  784. BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
  785. {
  786. result_type r(*this);
  787. return static_cast<bool>(r);
  788. }
  789. #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
  790. BOOST_MP_FORCEINLINE explicit operator void() const
  791. {}
  792. #endif
  793. #endif
  794. #else
  795. operator unmentionable_type() const
  796. {
  797. return arg ? &unmentionable::proc : 0;
  798. }
  799. #endif
  800. template <class T>
  801. BOOST_MP_CXX14_CONSTEXPR T convert_to()
  802. {
  803. result_type r(*this);
  804. return r.template convert_to<T>();
  805. }
  806. private:
  807. typename expression_storage<Arg1>::type arg;
  808. expression& operator=(const expression&);
  809. };
  810. template <class tag, class Arg1, class Arg2>
  811. struct expression<tag, Arg1, Arg2, void, void>
  812. {
  813. typedef mpl::int_<2> arity;
  814. typedef typename arg_type<Arg1>::type left_type;
  815. typedef typename arg_type<Arg2>::type right_type;
  816. typedef typename left_type::result_type left_result_type;
  817. typedef typename right_type::result_type right_result_type;
  818. typedef typename combine_expression<left_result_type, right_result_type>::type result_type;
  819. typedef tag tag_type;
  820. BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2) : arg1(a1), arg2(a2) {}
  821. BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2) {}
  822. #ifndef BOOST_NO_CXX11_STATIC_ASSERT
  823. //
  824. // If we have static_assert we can give a more useful error message
  825. // than if we simply have no operator defined at all:
  826. //
  827. template <class Other>
  828. BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
  829. {
  830. // This should always fail:
  831. static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  832. return *this;
  833. }
  834. BOOST_MP_CXX14_CONSTEXPR expression& operator++()
  835. {
  836. // This should always fail:
  837. static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  838. return *this;
  839. }
  840. BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
  841. {
  842. // This should always fail:
  843. static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  844. return *this;
  845. }
  846. BOOST_MP_CXX14_CONSTEXPR expression& operator--()
  847. {
  848. // This should always fail:
  849. static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  850. return *this;
  851. }
  852. BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
  853. {
  854. // This should always fail:
  855. static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  856. return *this;
  857. }
  858. template <class Other>
  859. BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
  860. {
  861. // This should always fail:
  862. static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  863. return *this;
  864. }
  865. template <class Other>
  866. BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
  867. {
  868. // This should always fail:
  869. static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  870. return *this;
  871. }
  872. template <class Other>
  873. BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
  874. {
  875. // This should always fail:
  876. static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  877. return *this;
  878. }
  879. template <class Other>
  880. BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
  881. {
  882. // This should always fail:
  883. static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  884. return *this;
  885. }
  886. template <class Other>
  887. BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
  888. {
  889. // This should always fail:
  890. static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  891. return *this;
  892. }
  893. template <class Other>
  894. BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
  895. {
  896. // This should always fail:
  897. static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  898. return *this;
  899. }
  900. template <class Other>
  901. BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
  902. {
  903. // This should always fail:
  904. static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  905. return *this;
  906. }
  907. template <class Other>
  908. BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
  909. {
  910. // This should always fail:
  911. static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  912. return *this;
  913. }
  914. template <class Other>
  915. BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
  916. {
  917. // This should always fail:
  918. static_assert(sizeof(Other) == INT_MAX, "You can not use operator<<= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  919. return *this;
  920. }
  921. template <class Other>
  922. BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
  923. {
  924. // This should always fail:
  925. static_assert(sizeof(Other) == INT_MAX, "You can not use operator>>= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  926. return *this;
  927. }
  928. #endif
  929. BOOST_MP_CXX14_CONSTEXPR left_type left() const
  930. {
  931. return left_type(arg1);
  932. }
  933. BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg2); }
  934. BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg1; }
  935. BOOST_MP_CXX14_CONSTEXPR const Arg2& right_ref() const BOOST_NOEXCEPT { return arg2; }
  936. #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
  937. #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
  938. //
  939. // Horrible workaround for gcc-4.6.x which always prefers the template
  940. // operator bool() rather than the non-template operator when converting to
  941. // an arithmetic type:
  942. //
  943. template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
  944. explicit operator T() const
  945. {
  946. result_type r(*this);
  947. return static_cast<bool>(r);
  948. }
  949. template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
  950. explicit operator T() const
  951. {
  952. return static_cast<T>(static_cast<result_type>(*this));
  953. }
  954. #else
  955. template <class T
  956. #ifndef __SUNPRO_CC
  957. ,
  958. typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value || !is_constructible<T, result_type>::value, int>::type = 0
  959. #endif
  960. >
  961. explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
  962. {
  963. return static_cast<T>(static_cast<result_type>(*this));
  964. }
  965. BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
  966. {
  967. result_type r(*this);
  968. return static_cast<bool>(r);
  969. }
  970. #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
  971. BOOST_MP_FORCEINLINE explicit operator void() const
  972. {}
  973. #endif
  974. #endif
  975. #else
  976. operator unmentionable_type() const
  977. {
  978. result_type r(*this);
  979. return r ? &unmentionable::proc : 0;
  980. }
  981. #endif
  982. template <class T>
  983. BOOST_MP_CXX14_CONSTEXPR T convert_to()
  984. {
  985. result_type r(*this);
  986. return r.template convert_to<T>();
  987. }
  988. static const BOOST_MP_CXX14_CONSTEXPR unsigned left_depth = left_type::depth + 1;
  989. static const BOOST_MP_CXX14_CONSTEXPR unsigned right_depth = right_type::depth + 1;
  990. static const BOOST_MP_CXX14_CONSTEXPR unsigned depth = left_depth > right_depth ? left_depth : right_depth;
  991. private:
  992. typename expression_storage<Arg1>::type arg1;
  993. typename expression_storage<Arg2>::type arg2;
  994. expression& operator=(const expression&);
  995. };
  996. template <class tag, class Arg1, class Arg2, class Arg3>
  997. struct expression<tag, Arg1, Arg2, Arg3, void>
  998. {
  999. typedef mpl::int_<3> arity;
  1000. typedef typename arg_type<Arg1>::type left_type;
  1001. typedef typename arg_type<Arg2>::type middle_type;
  1002. typedef typename arg_type<Arg3>::type right_type;
  1003. typedef typename left_type::result_type left_result_type;
  1004. typedef typename middle_type::result_type middle_result_type;
  1005. typedef typename right_type::result_type right_result_type;
  1006. typedef typename combine_expression<
  1007. left_result_type,
  1008. typename combine_expression<right_result_type, middle_result_type>::type>::type result_type;
  1009. typedef tag tag_type;
  1010. BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2, const Arg3& a3) : arg1(a1), arg2(a2), arg3(a3) {}
  1011. BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.arg3) {}
  1012. #ifndef BOOST_NO_CXX11_STATIC_ASSERT
  1013. //
  1014. // If we have static_assert we can give a more useful error message
  1015. // than if we simply have no operator defined at all:
  1016. //
  1017. template <class Other>
  1018. BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
  1019. {
  1020. // This should always fail:
  1021. static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1022. return *this;
  1023. }
  1024. BOOST_MP_CXX14_CONSTEXPR expression& operator++()
  1025. {
  1026. // This should always fail:
  1027. static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1028. return *this;
  1029. }
  1030. BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
  1031. {
  1032. // This should always fail:
  1033. static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1034. return *this;
  1035. }
  1036. BOOST_MP_CXX14_CONSTEXPR expression& operator--()
  1037. {
  1038. // This should always fail:
  1039. static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1040. return *this;
  1041. }
  1042. BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
  1043. {
  1044. // This should always fail:
  1045. static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1046. return *this;
  1047. }
  1048. template <class Other>
  1049. BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
  1050. {
  1051. // This should always fail:
  1052. static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1053. return *this;
  1054. }
  1055. template <class Other>
  1056. BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
  1057. {
  1058. // This should always fail:
  1059. static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1060. return *this;
  1061. }
  1062. template <class Other>
  1063. BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
  1064. {
  1065. // This should always fail:
  1066. static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1067. return *this;
  1068. }
  1069. template <class Other>
  1070. BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
  1071. {
  1072. // This should always fail:
  1073. static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1074. return *this;
  1075. }
  1076. template <class Other>
  1077. BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
  1078. {
  1079. // This should always fail:
  1080. static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1081. return *this;
  1082. }
  1083. template <class Other>
  1084. BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
  1085. {
  1086. // This should always fail:
  1087. static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1088. return *this;
  1089. }
  1090. template <class Other>
  1091. BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
  1092. {
  1093. // This should always fail:
  1094. static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1095. return *this;
  1096. }
  1097. template <class Other>
  1098. BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
  1099. {
  1100. // This should always fail:
  1101. static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1102. return *this;
  1103. }
  1104. template <class Other>
  1105. BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
  1106. {
  1107. // This should always fail:
  1108. static_assert(sizeof(Other) == INT_MAX, "You can not use operator<<= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1109. return *this;
  1110. }
  1111. template <class Other>
  1112. BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
  1113. {
  1114. // This should always fail:
  1115. static_assert(sizeof(Other) == INT_MAX, "You can not use operator>>= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1116. return *this;
  1117. }
  1118. #endif
  1119. BOOST_MP_CXX14_CONSTEXPR left_type left() const
  1120. {
  1121. return left_type(arg1);
  1122. }
  1123. BOOST_MP_CXX14_CONSTEXPR middle_type middle() const { return middle_type(arg2); }
  1124. BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg3); }
  1125. BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg1; }
  1126. BOOST_MP_CXX14_CONSTEXPR const Arg2& middle_ref() const BOOST_NOEXCEPT { return arg2; }
  1127. BOOST_MP_CXX14_CONSTEXPR const Arg3& right_ref() const BOOST_NOEXCEPT { return arg3; }
  1128. #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
  1129. #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
  1130. //
  1131. // Horrible workaround for gcc-4.6.x which always prefers the template
  1132. // operator bool() rather than the non-template operator when converting to
  1133. // an arithmetic type:
  1134. //
  1135. template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
  1136. explicit operator T() const
  1137. {
  1138. result_type r(*this);
  1139. return static_cast<bool>(r);
  1140. }
  1141. template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
  1142. explicit operator T() const
  1143. {
  1144. return static_cast<T>(static_cast<result_type>(*this));
  1145. }
  1146. #else
  1147. template <class T
  1148. #ifndef __SUNPRO_CC
  1149. ,
  1150. typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value || !is_constructible<T, result_type>::value, int>::type = 0
  1151. #endif
  1152. >
  1153. explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
  1154. {
  1155. return static_cast<T>(static_cast<result_type>(*this));
  1156. }
  1157. BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
  1158. {
  1159. result_type r(*this);
  1160. return static_cast<bool>(r);
  1161. }
  1162. #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
  1163. BOOST_MP_FORCEINLINE explicit operator void() const
  1164. {}
  1165. #endif
  1166. #endif
  1167. #else
  1168. operator unmentionable_type() const
  1169. {
  1170. result_type r(*this);
  1171. return r ? &unmentionable::proc : 0;
  1172. }
  1173. #endif
  1174. template <class T>
  1175. BOOST_MP_CXX14_CONSTEXPR T convert_to()
  1176. {
  1177. result_type r(*this);
  1178. return r.template convert_to<T>();
  1179. }
  1180. static const unsigned left_depth = left_type::depth + 1;
  1181. static const unsigned middle_depth = middle_type::depth + 1;
  1182. static const unsigned right_depth = right_type::depth + 1;
  1183. static const unsigned depth = left_depth > right_depth ? (left_depth > middle_depth ? left_depth : middle_depth) : (right_depth > middle_depth ? right_depth : middle_depth);
  1184. private:
  1185. typename expression_storage<Arg1>::type arg1;
  1186. typename expression_storage<Arg2>::type arg2;
  1187. typename expression_storage<Arg3>::type arg3;
  1188. expression& operator=(const expression&);
  1189. };
  1190. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1191. struct expression
  1192. {
  1193. typedef mpl::int_<4> arity;
  1194. typedef typename arg_type<Arg1>::type left_type;
  1195. typedef typename arg_type<Arg2>::type left_middle_type;
  1196. typedef typename arg_type<Arg3>::type right_middle_type;
  1197. typedef typename arg_type<Arg4>::type right_type;
  1198. typedef typename left_type::result_type left_result_type;
  1199. typedef typename left_middle_type::result_type left_middle_result_type;
  1200. typedef typename right_middle_type::result_type right_middle_result_type;
  1201. typedef typename right_type::result_type right_result_type;
  1202. typedef typename combine_expression<
  1203. left_result_type,
  1204. typename combine_expression<
  1205. left_middle_result_type,
  1206. typename combine_expression<right_middle_result_type, right_result_type>::type>::type>::type result_type;
  1207. typedef tag tag_type;
  1208. BOOST_MP_CXX14_CONSTEXPR expression(const Arg1& a1, const Arg2& a2, const Arg3& a3, const Arg4& a4) : arg1(a1), arg2(a2), arg3(a3), arg4(a4) {}
  1209. BOOST_MP_CXX14_CONSTEXPR expression(const expression& e) : arg1(e.arg1), arg2(e.arg2), arg3(e.arg3), arg4(e.arg4) {}
  1210. #ifndef BOOST_NO_CXX11_STATIC_ASSERT
  1211. //
  1212. // If we have static_assert we can give a more useful error message
  1213. // than if we simply have no operator defined at all:
  1214. //
  1215. template <class Other>
  1216. BOOST_MP_CXX14_CONSTEXPR expression& operator=(const Other&)
  1217. {
  1218. // This should always fail:
  1219. static_assert(sizeof(Other) == INT_MAX, "You can not assign to a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1220. return *this;
  1221. }
  1222. BOOST_MP_CXX14_CONSTEXPR expression& operator++()
  1223. {
  1224. // This should always fail:
  1225. static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1226. return *this;
  1227. }
  1228. BOOST_MP_CXX14_CONSTEXPR expression& operator++(int)
  1229. {
  1230. // This should always fail:
  1231. static_assert(sizeof(*this) == INT_MAX, "You can not increment a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1232. return *this;
  1233. }
  1234. BOOST_MP_CXX14_CONSTEXPR expression& operator--()
  1235. {
  1236. // This should always fail:
  1237. static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1238. return *this;
  1239. }
  1240. BOOST_MP_CXX14_CONSTEXPR expression& operator--(int)
  1241. {
  1242. // This should always fail:
  1243. static_assert(sizeof(*this) == INT_MAX, "You can not decrement a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1244. return *this;
  1245. }
  1246. template <class Other>
  1247. BOOST_MP_CXX14_CONSTEXPR expression& operator+=(const Other&)
  1248. {
  1249. // This should always fail:
  1250. static_assert(sizeof(Other) == INT_MAX, "You can not use operator+= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1251. return *this;
  1252. }
  1253. template <class Other>
  1254. BOOST_MP_CXX14_CONSTEXPR expression& operator-=(const Other&)
  1255. {
  1256. // This should always fail:
  1257. static_assert(sizeof(Other) == INT_MAX, "You can not use operator-= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1258. return *this;
  1259. }
  1260. template <class Other>
  1261. BOOST_MP_CXX14_CONSTEXPR expression& operator*=(const Other&)
  1262. {
  1263. // This should always fail:
  1264. static_assert(sizeof(Other) == INT_MAX, "You can not use operator*= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1265. return *this;
  1266. }
  1267. template <class Other>
  1268. BOOST_MP_CXX14_CONSTEXPR expression& operator/=(const Other&)
  1269. {
  1270. // This should always fail:
  1271. static_assert(sizeof(Other) == INT_MAX, "You can not use operator/= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1272. return *this;
  1273. }
  1274. template <class Other>
  1275. BOOST_MP_CXX14_CONSTEXPR expression& operator%=(const Other&)
  1276. {
  1277. // This should always fail:
  1278. static_assert(sizeof(Other) == INT_MAX, "You can not use operator%= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1279. return *this;
  1280. }
  1281. template <class Other>
  1282. BOOST_MP_CXX14_CONSTEXPR expression& operator|=(const Other&)
  1283. {
  1284. // This should always fail:
  1285. static_assert(sizeof(Other) == INT_MAX, "You can not use operator|= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1286. return *this;
  1287. }
  1288. template <class Other>
  1289. BOOST_MP_CXX14_CONSTEXPR expression& operator&=(const Other&)
  1290. {
  1291. // This should always fail:
  1292. static_assert(sizeof(Other) == INT_MAX, "You can not use operator&= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1293. return *this;
  1294. }
  1295. template <class Other>
  1296. BOOST_MP_CXX14_CONSTEXPR expression& operator^=(const Other&)
  1297. {
  1298. // This should always fail:
  1299. static_assert(sizeof(Other) == INT_MAX, "You can not use operator^= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1300. return *this;
  1301. }
  1302. template <class Other>
  1303. BOOST_MP_CXX14_CONSTEXPR expression& operator<<=(const Other&)
  1304. {
  1305. // This should always fail:
  1306. static_assert(sizeof(Other) == INT_MAX, "You can not use operator<<= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1307. return *this;
  1308. }
  1309. template <class Other>
  1310. BOOST_MP_CXX14_CONSTEXPR expression& operator>>=(const Other&)
  1311. {
  1312. // This should always fail:
  1313. static_assert(sizeof(Other) == INT_MAX, "You can not use operator>>= on a Boost.Multiprecision expression template: did you inadvertantly store an expression template in a \"auto\" variable? Or pass an expression to a template function with deduced temnplate arguments?");
  1314. return *this;
  1315. }
  1316. #endif
  1317. BOOST_MP_CXX14_CONSTEXPR left_type left() const
  1318. {
  1319. return left_type(arg1);
  1320. }
  1321. BOOST_MP_CXX14_CONSTEXPR left_middle_type left_middle() const { return left_middle_type(arg2); }
  1322. BOOST_MP_CXX14_CONSTEXPR right_middle_type right_middle() const { return right_middle_type(arg3); }
  1323. BOOST_MP_CXX14_CONSTEXPR right_type right() const { return right_type(arg4); }
  1324. BOOST_MP_CXX14_CONSTEXPR const Arg1& left_ref() const BOOST_NOEXCEPT { return arg1; }
  1325. BOOST_MP_CXX14_CONSTEXPR const Arg2& left_middle_ref() const BOOST_NOEXCEPT { return arg2; }
  1326. BOOST_MP_CXX14_CONSTEXPR const Arg3& right_middle_ref() const BOOST_NOEXCEPT { return arg3; }
  1327. BOOST_MP_CXX14_CONSTEXPR const Arg4& right_ref() const BOOST_NOEXCEPT { return arg4; }
  1328. #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
  1329. #if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
  1330. //
  1331. // Horrible workaround for gcc-4.6.x which always prefers the template
  1332. // operator bool() rather than the non-template operator when converting to
  1333. // an arithmetic type:
  1334. //
  1335. template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
  1336. explicit operator T() const
  1337. {
  1338. result_type r(*this);
  1339. return static_cast<bool>(r);
  1340. }
  1341. template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
  1342. explicit operator T() const
  1343. {
  1344. return static_cast<T>(static_cast<result_type>(*this));
  1345. }
  1346. #else
  1347. template <class T
  1348. #ifndef __SUNPRO_CC
  1349. ,
  1350. typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value || !is_constructible<T, result_type>::value, int>::type = 0
  1351. #endif
  1352. >
  1353. explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
  1354. {
  1355. return static_cast<T>(static_cast<result_type>(*this));
  1356. }
  1357. BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR operator bool() const
  1358. {
  1359. result_type r(*this);
  1360. return static_cast<bool>(r);
  1361. }
  1362. #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
  1363. BOOST_MP_FORCEINLINE explicit operator void() const
  1364. {}
  1365. #endif
  1366. #endif
  1367. #else
  1368. operator unmentionable_type() const
  1369. {
  1370. result_type r(*this);
  1371. return r ? &unmentionable::proc : 0;
  1372. }
  1373. #endif
  1374. template <class T>
  1375. BOOST_MP_CXX14_CONSTEXPR T convert_to()
  1376. {
  1377. result_type r(*this);
  1378. return r.template convert_to<T>();
  1379. }
  1380. static const unsigned left_depth = left_type::depth + 1;
  1381. static const unsigned left_middle_depth = left_middle_type::depth + 1;
  1382. static const unsigned right_middle_depth = right_middle_type::depth + 1;
  1383. static const unsigned right_depth = right_type::depth + 1;
  1384. static const unsigned left_max_depth = left_depth > left_middle_depth ? left_depth : left_middle_depth;
  1385. static const unsigned right_max_depth = right_depth > right_middle_depth ? right_depth : right_middle_depth;
  1386. static const unsigned depth = left_max_depth > right_max_depth ? left_max_depth : right_max_depth;
  1387. private:
  1388. typename expression_storage<Arg1>::type arg1;
  1389. typename expression_storage<Arg2>::type arg2;
  1390. typename expression_storage<Arg3>::type arg3;
  1391. typename expression_storage<Arg4>::type arg4;
  1392. expression& operator=(const expression&);
  1393. };
  1394. template <class T>
  1395. struct digits2
  1396. {
  1397. BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
  1398. BOOST_STATIC_ASSERT((std::numeric_limits<T>::radix == 2) || (std::numeric_limits<T>::radix == 10));
  1399. // If we really have so many digits that this fails, then we're probably going to hit other problems anyway:
  1400. BOOST_STATIC_ASSERT(LONG_MAX / 1000 > (std::numeric_limits<T>::digits + 1));
  1401. static const long m_value = std::numeric_limits<T>::radix == 10 ? (((std::numeric_limits<T>::digits + 1) * 1000L) / 301L) : std::numeric_limits<T>::digits;
  1402. static inline BOOST_CONSTEXPR long value() BOOST_NOEXCEPT { return m_value; }
  1403. };
  1404. #ifndef BOOST_MP_MIN_EXPONENT_DIGITS
  1405. #ifdef _MSC_VER
  1406. #define BOOST_MP_MIN_EXPONENT_DIGITS 2
  1407. #else
  1408. #define BOOST_MP_MIN_EXPONENT_DIGITS 2
  1409. #endif
  1410. #endif
  1411. template <class S>
  1412. void format_float_string(S& str, boost::intmax_t my_exp, boost::intmax_t digits, std::ios_base::fmtflags f, bool iszero)
  1413. {
  1414. typedef typename S::size_type size_type;
  1415. bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
  1416. bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed;
  1417. bool showpoint = (f & std::ios_base::showpoint) == std::ios_base::showpoint;
  1418. bool showpos = (f & std::ios_base::showpos) == std::ios_base::showpos;
  1419. bool neg = str.size() && (str[0] == '-');
  1420. if (neg)
  1421. str.erase(0, 1);
  1422. if (digits == 0)
  1423. {
  1424. digits = (std::max)(str.size(), size_type(16));
  1425. }
  1426. if (iszero || str.empty() || (str.find_first_not_of('0') == S::npos))
  1427. {
  1428. // We will be printing zero, even though the value might not
  1429. // actually be zero (it just may have been rounded to zero).
  1430. str = "0";
  1431. if (scientific || fixed)
  1432. {
  1433. str.append(1, '.');
  1434. str.append(size_type(digits), '0');
  1435. if (scientific)
  1436. str.append("e+00");
  1437. }
  1438. else
  1439. {
  1440. if (showpoint)
  1441. {
  1442. str.append(1, '.');
  1443. if (digits > 1)
  1444. str.append(size_type(digits - 1), '0');
  1445. }
  1446. }
  1447. if (neg)
  1448. str.insert(static_cast<std::string::size_type>(0), 1, '-');
  1449. else if (showpos)
  1450. str.insert(static_cast<std::string::size_type>(0), 1, '+');
  1451. return;
  1452. }
  1453. if (!fixed && !scientific && !showpoint)
  1454. {
  1455. //
  1456. // Suppress trailing zeros:
  1457. //
  1458. std::string::iterator pos = str.end();
  1459. while (pos != str.begin() && *--pos == '0')
  1460. {
  1461. }
  1462. if (pos != str.end())
  1463. ++pos;
  1464. str.erase(pos, str.end());
  1465. if (str.empty())
  1466. str = '0';
  1467. }
  1468. else if (!fixed || (my_exp >= 0))
  1469. {
  1470. //
  1471. // Pad out the end with zero's if we need to:
  1472. //
  1473. boost::intmax_t chars = str.size();
  1474. chars = digits - chars;
  1475. if (scientific)
  1476. ++chars;
  1477. if (chars > 0)
  1478. {
  1479. str.append(static_cast<std::string::size_type>(chars), '0');
  1480. }
  1481. }
  1482. if (fixed || (!scientific && (my_exp >= -4) && (my_exp < digits)))
  1483. {
  1484. if (1 + my_exp > static_cast<boost::intmax_t>(str.size()))
  1485. {
  1486. // Just pad out the end with zeros:
  1487. str.append(static_cast<std::string::size_type>(1 + my_exp - str.size()), '0');
  1488. if (showpoint || fixed)
  1489. str.append(".");
  1490. }
  1491. else if (my_exp + 1 < static_cast<boost::intmax_t>(str.size()))
  1492. {
  1493. if (my_exp < 0)
  1494. {
  1495. str.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(-1 - my_exp), '0');
  1496. str.insert(static_cast<std::string::size_type>(0), "0.");
  1497. }
  1498. else
  1499. {
  1500. // Insert the decimal point:
  1501. str.insert(static_cast<std::string::size_type>(my_exp + 1), 1, '.');
  1502. }
  1503. }
  1504. else if (showpoint || fixed) // we have exactly the digits we require to left of the point
  1505. str += ".";
  1506. if (fixed)
  1507. {
  1508. // We may need to add trailing zeros:
  1509. boost::intmax_t l = str.find('.') + 1;
  1510. l = digits - (str.size() - l);
  1511. if (l > 0)
  1512. str.append(size_type(l), '0');
  1513. }
  1514. }
  1515. else
  1516. {
  1517. BOOST_MP_USING_ABS
  1518. // Scientific format:
  1519. if (showpoint || (str.size() > 1))
  1520. str.insert(static_cast<std::string::size_type>(1u), 1, '.');
  1521. str.append(static_cast<std::string::size_type>(1u), 'e');
  1522. S e = boost::lexical_cast<S>(abs(my_exp));
  1523. if (e.size() < BOOST_MP_MIN_EXPONENT_DIGITS)
  1524. e.insert(static_cast<std::string::size_type>(0), BOOST_MP_MIN_EXPONENT_DIGITS - e.size(), '0');
  1525. if (my_exp < 0)
  1526. e.insert(static_cast<std::string::size_type>(0), 1, '-');
  1527. else
  1528. e.insert(static_cast<std::string::size_type>(0), 1, '+');
  1529. str.append(e);
  1530. }
  1531. if (neg)
  1532. str.insert(static_cast<std::string::size_type>(0), 1, '-');
  1533. else if (showpos)
  1534. str.insert(static_cast<std::string::size_type>(0), 1, '+');
  1535. }
  1536. template <class V>
  1537. BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const mpl::true_&, const mpl::true_&)
  1538. {
  1539. if (val > (std::numeric_limits<std::size_t>::max)())
  1540. BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
  1541. if (val < 0)
  1542. BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
  1543. }
  1544. template <class V>
  1545. BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const mpl::false_&, const mpl::true_&)
  1546. {
  1547. if (val < 0)
  1548. BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
  1549. }
  1550. template <class V>
  1551. BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V val, const mpl::true_&, const mpl::false_&)
  1552. {
  1553. if (val > (std::numeric_limits<std::size_t>::max)())
  1554. BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
  1555. }
  1556. template <class V>
  1557. BOOST_MP_CXX14_CONSTEXPR void check_shift_range(V, const mpl::false_&, const mpl::false_&) BOOST_NOEXCEPT {}
  1558. template <class T>
  1559. BOOST_MP_CXX14_CONSTEXPR const T& evaluate_if_expression(const T& val) { return val; }
  1560. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  1561. BOOST_MP_CXX14_CONSTEXPR typename expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type evaluate_if_expression(const expression<tag, Arg1, Arg2, Arg3, Arg4>& val) { return val; }
  1562. } // namespace detail
  1563. //
  1564. // Traits class, lets us know what kind of number we have, defaults to a floating point type:
  1565. //
  1566. enum number_category_type
  1567. {
  1568. number_kind_unknown = -1,
  1569. number_kind_integer = 0,
  1570. number_kind_floating_point = 1,
  1571. number_kind_rational = 2,
  1572. number_kind_fixed_point = 3,
  1573. number_kind_complex = 4
  1574. };
  1575. template <class Num, bool, bool>
  1576. struct number_category_base : public mpl::int_<number_kind_unknown>
  1577. {};
  1578. template <class Num>
  1579. struct number_category_base<Num, true, false> : public mpl::int_<std::numeric_limits<Num>::is_integer ? number_kind_integer : (std::numeric_limits<Num>::max_exponent ? number_kind_floating_point : number_kind_unknown)>
  1580. {};
  1581. template <class Num>
  1582. struct number_category : public number_category_base<Num, boost::is_class<Num>::value || boost::is_arithmetic<Num>::value, boost::is_abstract<Num>::value>
  1583. {};
  1584. template <class Backend, expression_template_option ExpressionTemplates>
  1585. struct number_category<number<Backend, ExpressionTemplates> > : public number_category<Backend>
  1586. {};
  1587. template <class tag, class A1, class A2, class A3, class A4>
  1588. struct number_category<detail::expression<tag, A1, A2, A3, A4> > : public number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>
  1589. {};
  1590. //
  1591. // Specializations for types which do not always have numberic_limits specializations:
  1592. //
  1593. #ifdef BOOST_HAS_INT128
  1594. template <>
  1595. struct number_category<boost::int128_type> : public mpl::int_<number_kind_integer>
  1596. {};
  1597. template <>
  1598. struct number_category<boost::uint128_type> : public mpl::int_<number_kind_integer>
  1599. {};
  1600. #endif
  1601. #ifdef BOOST_HAS_FLOAT128
  1602. template <>
  1603. struct number_category<__float128> : public mpl::int_<number_kind_floating_point>
  1604. {};
  1605. #endif
  1606. template <class T>
  1607. struct component_type
  1608. {
  1609. typedef T type;
  1610. };
  1611. template <class tag, class A1, class A2, class A3, class A4>
  1612. struct component_type<detail::expression<tag, A1, A2, A3, A4> > : public component_type<typename detail::expression<tag, A1, A2, A3, A4>::result_type>
  1613. {};
  1614. template <class T>
  1615. struct scalar_result_from_possible_complex
  1616. {
  1617. typedef typename mpl::if_c<number_category<T>::value == number_kind_complex,
  1618. typename component_type<T>::type, T>::type type;
  1619. };
  1620. template <class T>
  1621. struct complex_result_from_scalar; // individual backends must specialize this trait.
  1622. template <class T>
  1623. struct is_unsigned_number : public mpl::false_
  1624. {};
  1625. template <class Backend, expression_template_option ExpressionTemplates>
  1626. struct is_unsigned_number<number<Backend, ExpressionTemplates> > : public is_unsigned_number<Backend>
  1627. {};
  1628. template <class T>
  1629. struct is_signed_number : public mpl::bool_<!is_unsigned_number<T>::value>
  1630. {};
  1631. template <class T>
  1632. struct is_interval_number : public mpl::false_
  1633. {};
  1634. template <class Backend, expression_template_option ExpressionTemplates>
  1635. struct is_interval_number<number<Backend, ExpressionTemplates> > : public is_interval_number<Backend>
  1636. {};
  1637. } // namespace multiprecision
  1638. } // namespace boost
  1639. namespace boost { namespace math {
  1640. namespace tools {
  1641. template <class T>
  1642. struct promote_arg;
  1643. template <class tag, class A1, class A2, class A3, class A4>
  1644. struct promote_arg<boost::multiprecision::detail::expression<tag, A1, A2, A3, A4> >
  1645. {
  1646. typedef typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type type;
  1647. };
  1648. template <class R, class B, boost::multiprecision::expression_template_option ET>
  1649. inline R real_cast(const boost::multiprecision::number<B, ET>& val)
  1650. {
  1651. return val.template convert_to<R>();
  1652. }
  1653. template <class R, class tag, class A1, class A2, class A3, class A4>
  1654. inline R real_cast(const boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>& val)
  1655. {
  1656. typedef typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type val_type;
  1657. return val_type(val).template convert_to<R>();
  1658. }
  1659. template <class B, boost::multiprecision::expression_template_option ET>
  1660. struct is_complex_type<boost::multiprecision::number<B, ET> > : public boost::mpl::bool_<boost::multiprecision::number_category<B>::value == boost::multiprecision::number_kind_complex> {};
  1661. } // namespace tools
  1662. namespace constants {
  1663. template <class T>
  1664. struct is_explicitly_convertible_from_string;
  1665. template <class B, boost::multiprecision::expression_template_option ET>
  1666. struct is_explicitly_convertible_from_string<boost::multiprecision::number<B, ET> >
  1667. {
  1668. static const bool value = true;
  1669. };
  1670. } // namespace constants
  1671. }} // namespace boost::math
  1672. #ifdef BOOST_MSVC
  1673. #pragma warning(pop)
  1674. #endif
  1675. #endif // BOOST_MATH_BIG_NUM_BASE_HPP