number_base.hpp 73 KB

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