mpfi.hpp 74 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857
  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_BN_MPFI_HPP
  6. #define BOOST_MATH_BN_MPFI_HPP
  7. #include <boost/multiprecision/number.hpp>
  8. #include <boost/math/special_functions/fpclassify.hpp>
  9. #include <boost/cstdint.hpp>
  10. #include <boost/multiprecision/detail/big_lanczos.hpp>
  11. #include <boost/multiprecision/detail/digits.hpp>
  12. #include <boost/multiprecision/mpfr.hpp>
  13. #include <boost/multiprecision/logged_adaptor.hpp>
  14. #include <boost/math/constants/constants.hpp>
  15. #include <boost/functional/hash_fwd.hpp>
  16. #include <mpfi.h>
  17. #include <cmath>
  18. #include <algorithm>
  19. #ifndef BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION
  20. #define BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION 20
  21. #endif
  22. namespace boost {
  23. namespace multiprecision {
  24. namespace backends {
  25. template <unsigned digits10>
  26. struct mpfi_float_backend;
  27. } // namespace backends
  28. template <unsigned digits10>
  29. struct number_category<backends::mpfi_float_backend<digits10> > : public mpl::int_<number_kind_floating_point>
  30. {};
  31. struct interval_error : public std::runtime_error
  32. {
  33. interval_error(const std::string& s) : std::runtime_error(s) {}
  34. };
  35. namespace backends {
  36. namespace detail {
  37. inline int mpfi_sgn(mpfi_srcptr p)
  38. {
  39. if (mpfi_is_zero(p))
  40. return 0;
  41. if (mpfi_is_strictly_pos(p))
  42. return 1;
  43. if (mpfi_is_strictly_neg(p))
  44. return -1;
  45. BOOST_THROW_EXCEPTION(interval_error("Sign of interval is ambiguous."));
  46. }
  47. template <unsigned digits10>
  48. struct mpfi_float_imp;
  49. template <unsigned digits10>
  50. struct mpfi_float_imp
  51. {
  52. #ifdef BOOST_HAS_LONG_LONG
  53. typedef mpl::list<long, boost::long_long_type> signed_types;
  54. typedef mpl::list<unsigned long, boost::ulong_long_type> unsigned_types;
  55. #else
  56. typedef mpl::list<long> signed_types;
  57. typedef mpl::list<unsigned long> unsigned_types;
  58. #endif
  59. typedef mpl::list<double, long double> float_types;
  60. typedef long exponent_type;
  61. mpfi_float_imp()
  62. {
  63. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
  64. mpfi_set_ui(m_data, 0u);
  65. }
  66. mpfi_float_imp(unsigned prec)
  67. {
  68. mpfi_init2(m_data, prec);
  69. mpfi_set_ui(m_data, 0u);
  70. }
  71. mpfi_float_imp(const mpfi_float_imp& o)
  72. {
  73. mpfi_init2(m_data, mpfi_get_prec(o.data()));
  74. if (o.m_data[0].left._mpfr_d)
  75. mpfi_set(m_data, o.m_data);
  76. }
  77. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  78. mpfi_float_imp(mpfi_float_imp&& o) BOOST_NOEXCEPT
  79. {
  80. m_data[0] = o.m_data[0];
  81. o.m_data[0].left._mpfr_d = 0;
  82. }
  83. #endif
  84. mpfi_float_imp& operator=(const mpfi_float_imp& o)
  85. {
  86. if (m_data[0].left._mpfr_d == 0)
  87. mpfi_init2(m_data, mpfi_get_prec(o.data()));
  88. if (mpfi_get_prec(o.data()) != mpfi_get_prec(data()))
  89. {
  90. mpfi_float_imp t(mpfi_get_prec(o.data()));
  91. t = o;
  92. t.swap(*this);
  93. }
  94. else
  95. {
  96. if (o.m_data[0].left._mpfr_d)
  97. mpfi_set(m_data, o.m_data);
  98. }
  99. return *this;
  100. }
  101. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  102. mpfi_float_imp& operator=(mpfi_float_imp&& o) BOOST_NOEXCEPT
  103. {
  104. mpfi_swap(m_data, o.m_data);
  105. return *this;
  106. }
  107. #endif
  108. #ifdef BOOST_HAS_LONG_LONG
  109. #ifdef _MPFR_H_HAVE_INTMAX_T
  110. mpfi_float_imp& operator=(boost::ulong_long_type i)
  111. {
  112. if (m_data[0].left._mpfr_d == 0)
  113. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
  114. mpfr_set_uj(left_data(), i, GMP_RNDD);
  115. mpfr_set_uj(right_data(), i, GMP_RNDU);
  116. return *this;
  117. }
  118. mpfi_float_imp& operator=(boost::long_long_type i)
  119. {
  120. if (m_data[0].left._mpfr_d == 0)
  121. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
  122. mpfr_set_sj(left_data(), i, GMP_RNDD);
  123. mpfr_set_sj(right_data(), i, GMP_RNDU);
  124. return *this;
  125. }
  126. #else
  127. mpfi_float_imp& operator=(boost::ulong_long_type i)
  128. {
  129. if (m_data[0].left._mpfr_d == 0)
  130. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
  131. boost::ulong_long_type mask = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1u);
  132. unsigned shift = 0;
  133. mpfi_t t;
  134. mpfi_init2(t, (std::max)(static_cast<unsigned long>(std::numeric_limits<boost::ulong_long_type>::digits), static_cast<unsigned long>(multiprecision::detail::digits10_2_2(digits10))));
  135. mpfi_set_ui(m_data, 0);
  136. while (i)
  137. {
  138. mpfi_set_ui(t, static_cast<unsigned long>(i & mask));
  139. if (shift)
  140. mpfi_mul_2exp(t, t, shift);
  141. mpfi_add(m_data, m_data, t);
  142. shift += std::numeric_limits<unsigned long>::digits;
  143. i >>= std::numeric_limits<unsigned long>::digits;
  144. }
  145. mpfi_clear(t);
  146. return *this;
  147. }
  148. mpfi_float_imp& operator=(boost::long_long_type i)
  149. {
  150. if (m_data[0].left._mpfr_d == 0)
  151. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
  152. bool neg = i < 0;
  153. *this = boost::multiprecision::detail::unsigned_abs(i);
  154. if (neg)
  155. mpfi_neg(m_data, m_data);
  156. return *this;
  157. }
  158. #endif
  159. #endif
  160. mpfi_float_imp& operator=(unsigned long i)
  161. {
  162. if (m_data[0].left._mpfr_d == 0)
  163. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
  164. mpfi_set_ui(m_data, i);
  165. return *this;
  166. }
  167. mpfi_float_imp& operator=(long i)
  168. {
  169. if (m_data[0].left._mpfr_d == 0)
  170. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
  171. mpfi_set_si(m_data, i);
  172. return *this;
  173. }
  174. mpfi_float_imp& operator=(double d)
  175. {
  176. if (m_data[0].left._mpfr_d == 0)
  177. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
  178. mpfi_set_d(m_data, d);
  179. return *this;
  180. }
  181. mpfi_float_imp& operator=(long double a)
  182. {
  183. if (m_data[0].left._mpfr_d == 0)
  184. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
  185. mpfr_set_ld(left_data(), a, GMP_RNDD);
  186. mpfr_set_ld(right_data(), a, GMP_RNDU);
  187. return *this;
  188. }
  189. mpfi_float_imp& operator=(const char* s)
  190. {
  191. using default_ops::eval_fpclassify;
  192. if (m_data[0].left._mpfr_d == 0)
  193. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
  194. if (s && (*s == '{'))
  195. {
  196. mpfr_float_backend<digits10> a, b;
  197. std::string part;
  198. const char* p = ++s;
  199. while (*p && (*p != ',') && (*p != '}'))
  200. ++p;
  201. part.assign(s + 1, p);
  202. a = part.c_str();
  203. s = p;
  204. if (*p && (*p != '}'))
  205. {
  206. ++p;
  207. while (*p && (*p != ',') && (*p != '}'))
  208. ++p;
  209. part.assign(s + 1, p);
  210. }
  211. else
  212. part.erase();
  213. b = part.c_str();
  214. if (eval_fpclassify(a) == (int)FP_NAN)
  215. {
  216. mpfi_set_fr(this->data(), a.data());
  217. }
  218. else if (eval_fpclassify(b) == (int)FP_NAN)
  219. {
  220. mpfi_set_fr(this->data(), b.data());
  221. }
  222. else
  223. {
  224. if (a.compare(b) > 0)
  225. {
  226. BOOST_THROW_EXCEPTION(std::runtime_error("Attempt to create interval with invalid range (start is greater than end)."));
  227. }
  228. mpfi_interv_fr(m_data, a.data(), b.data());
  229. }
  230. }
  231. else if (mpfi_set_str(m_data, s, 10) != 0)
  232. {
  233. BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Unable to parse string \"") + s + std::string("\"as a valid floating point number.")));
  234. }
  235. return *this;
  236. }
  237. void swap(mpfi_float_imp& o) BOOST_NOEXCEPT
  238. {
  239. mpfi_swap(m_data, o.m_data);
  240. }
  241. std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
  242. {
  243. BOOST_ASSERT(m_data[0].left._mpfr_d);
  244. mpfr_float_backend<digits10> a, b;
  245. mpfi_get_left(a.data(), m_data);
  246. mpfi_get_right(b.data(), m_data);
  247. if (a.compare(b) == 0)
  248. return a.str(digits, f);
  249. return "{" + a.str(digits, f) + "," + b.str(digits, f) + "}";
  250. }
  251. ~mpfi_float_imp() BOOST_NOEXCEPT
  252. {
  253. if (m_data[0].left._mpfr_d)
  254. mpfi_clear(m_data);
  255. }
  256. void negate() BOOST_NOEXCEPT
  257. {
  258. BOOST_ASSERT(m_data[0].left._mpfr_d);
  259. mpfi_neg(m_data, m_data);
  260. }
  261. int compare(const mpfi_float_imp& o) const BOOST_NOEXCEPT
  262. {
  263. BOOST_ASSERT(m_data[0].left._mpfr_d && o.m_data[0].left._mpfr_d);
  264. if (mpfr_cmp(right_data(), o.left_data()) < 0)
  265. return -1;
  266. if (mpfr_cmp(left_data(), o.right_data()) > 0)
  267. return 1;
  268. if ((mpfr_cmp(left_data(), o.left_data()) == 0) && (mpfr_cmp(right_data(), o.right_data()) == 0))
  269. return 0;
  270. BOOST_THROW_EXCEPTION(interval_error("Ambiguous comparison between two values."));
  271. return 0;
  272. }
  273. template <class V>
  274. int compare(V v) const BOOST_NOEXCEPT
  275. {
  276. mpfi_float_imp d;
  277. d = v;
  278. return compare(d);
  279. }
  280. mpfi_t& data() BOOST_NOEXCEPT
  281. {
  282. BOOST_ASSERT(m_data[0].left._mpfr_d);
  283. return m_data;
  284. }
  285. const mpfi_t& data() const BOOST_NOEXCEPT
  286. {
  287. BOOST_ASSERT(m_data[0].left._mpfr_d);
  288. return m_data;
  289. }
  290. mpfr_ptr left_data() BOOST_NOEXCEPT
  291. {
  292. BOOST_ASSERT(m_data[0].left._mpfr_d);
  293. return &(m_data[0].left);
  294. }
  295. mpfr_srcptr left_data() const BOOST_NOEXCEPT
  296. {
  297. BOOST_ASSERT(m_data[0].left._mpfr_d);
  298. return &(m_data[0].left);
  299. }
  300. mpfr_ptr right_data() BOOST_NOEXCEPT
  301. {
  302. BOOST_ASSERT(m_data[0].left._mpfr_d);
  303. return &(m_data[0].right);
  304. }
  305. mpfr_srcptr right_data() const BOOST_NOEXCEPT
  306. {
  307. BOOST_ASSERT(m_data[0].left._mpfr_d);
  308. return &(m_data[0].right);
  309. }
  310. protected:
  311. mpfi_t m_data;
  312. static unsigned& get_default_precision() BOOST_NOEXCEPT
  313. {
  314. static unsigned val = BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION;
  315. return val;
  316. }
  317. };
  318. } // namespace detail
  319. template <unsigned digits10>
  320. struct mpfi_float_backend : public detail::mpfi_float_imp<digits10>
  321. {
  322. mpfi_float_backend() : detail::mpfi_float_imp<digits10>() {}
  323. mpfi_float_backend(const mpfi_float_backend& o) : detail::mpfi_float_imp<digits10>(o) {}
  324. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  325. mpfi_float_backend(mpfi_float_backend&& o) : detail::mpfi_float_imp<digits10>(static_cast<detail::mpfi_float_imp<digits10>&&>(o))
  326. {}
  327. #endif
  328. template <unsigned D>
  329. mpfi_float_backend(const mpfi_float_backend<D>& val, typename enable_if_c<D <= digits10>::type* = 0)
  330. : detail::mpfi_float_imp<digits10>()
  331. {
  332. mpfi_set(this->m_data, val.data());
  333. }
  334. template <unsigned D>
  335. explicit mpfi_float_backend(const mpfi_float_backend<D>& val, typename disable_if_c<D <= digits10>::type* = 0)
  336. : detail::mpfi_float_imp<digits10>()
  337. {
  338. mpfi_set(this->m_data, val.data());
  339. }
  340. mpfi_float_backend(const mpfi_t val)
  341. : detail::mpfi_float_imp<digits10>()
  342. {
  343. mpfi_set(this->m_data, val);
  344. }
  345. mpfi_float_backend& operator=(const mpfi_float_backend& o)
  346. {
  347. *static_cast<detail::mpfi_float_imp<digits10>*>(this) = static_cast<detail::mpfi_float_imp<digits10> const&>(o);
  348. return *this;
  349. }
  350. template <unsigned D>
  351. mpfi_float_backend(const mpfr_float_backend<D>& val, typename enable_if_c<D <= digits10>::type* = 0)
  352. : detail::mpfi_float_imp<digits10>()
  353. {
  354. mpfi_set_fr(this->m_data, val.data());
  355. }
  356. template <unsigned D>
  357. mpfi_float_backend& operator=(const mpfr_float_backend<D>& val)
  358. {
  359. mpfi_set_fr(this->m_data, val.data());
  360. return *this;
  361. }
  362. template <unsigned D>
  363. explicit mpfi_float_backend(const mpfr_float_backend<D>& val, typename disable_if_c<D <= digits10>::type* = 0)
  364. : detail::mpfi_float_imp<digits10>()
  365. {
  366. mpfi_set_fr(this->m_data, val.data());
  367. }
  368. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  369. mpfi_float_backend& operator=(mpfi_float_backend&& o) BOOST_NOEXCEPT
  370. {
  371. *static_cast<detail::mpfi_float_imp<digits10>*>(this) = static_cast<detail::mpfi_float_imp<digits10>&&>(o);
  372. return *this;
  373. }
  374. #endif
  375. template <class V>
  376. mpfi_float_backend& operator=(const V& v)
  377. {
  378. *static_cast<detail::mpfi_float_imp<digits10>*>(this) = v;
  379. return *this;
  380. }
  381. mpfi_float_backend& operator=(const mpfi_t val)
  382. {
  383. mpfi_set(this->m_data, val);
  384. return *this;
  385. }
  386. // We don't change our precision here, this is a fixed precision type:
  387. template <unsigned D>
  388. mpfi_float_backend& operator=(const mpfi_float_backend<D>& val)
  389. {
  390. mpfi_set(this->m_data, val.data());
  391. return *this;
  392. }
  393. };
  394. template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType>
  395. void assign_components(mpfi_float_backend<D1>& result, const mpfr_float_backend<D2, AllocationType>& a, const mpfr_float_backend<D2, AllocationType>& b);
  396. template <unsigned Digits10, class V>
  397. typename enable_if_c<boost::is_constructible<number<mpfr_float_backend<Digits10, allocate_dynamic>, et_on>, V>::value || boost::is_convertible<V, const char*>::value>::type
  398. assign_components(mpfi_float_backend<Digits10>& result, const V& a, const V& b);
  399. template <>
  400. struct mpfi_float_backend<0> : public detail::mpfi_float_imp<0>
  401. {
  402. mpfi_float_backend() : detail::mpfi_float_imp<0>() {}
  403. mpfi_float_backend(const mpfi_t val)
  404. : detail::mpfi_float_imp<0>(mpfi_get_prec(val))
  405. {
  406. mpfi_set(this->m_data, val);
  407. }
  408. mpfi_float_backend(const mpfi_float_backend& o) : detail::mpfi_float_imp<0>(o) {}
  409. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  410. mpfi_float_backend(mpfi_float_backend&& o) BOOST_NOEXCEPT : detail::mpfi_float_imp<0>(static_cast<detail::mpfi_float_imp<0>&&>(o))
  411. {}
  412. #endif
  413. mpfi_float_backend(const mpfi_float_backend& o, unsigned digits10)
  414. : detail::mpfi_float_imp<0>(multiprecision::detail::digits10_2_2(digits10))
  415. {
  416. mpfi_set(this->m_data, o.data());
  417. }
  418. template <class V>
  419. mpfi_float_backend(const V& a, const V& b, unsigned digits10)
  420. : detail::mpfi_float_imp<0>(multiprecision::detail::digits10_2_2(digits10))
  421. {
  422. assign_components(*this, a, b);
  423. }
  424. template <unsigned D>
  425. mpfi_float_backend(const mpfi_float_backend<D>& val)
  426. : detail::mpfi_float_imp<0>(mpfi_get_prec(val.data()))
  427. {
  428. mpfi_set(this->m_data, val.data());
  429. }
  430. mpfi_float_backend& operator=(const mpfi_float_backend& o)
  431. {
  432. mpfi_set_prec(this->m_data, mpfi_get_prec(o.data()));
  433. mpfi_set(this->m_data, o.data());
  434. return *this;
  435. }
  436. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  437. mpfi_float_backend& operator=(mpfi_float_backend&& o) BOOST_NOEXCEPT
  438. {
  439. *static_cast<detail::mpfi_float_imp<0>*>(this) = static_cast<detail::mpfi_float_imp<0>&&>(o);
  440. return *this;
  441. }
  442. #endif
  443. template <class V>
  444. mpfi_float_backend& operator=(const V& v)
  445. {
  446. *static_cast<detail::mpfi_float_imp<0>*>(this) = v;
  447. return *this;
  448. }
  449. mpfi_float_backend& operator=(const mpfi_t val)
  450. {
  451. mpfi_set_prec(this->m_data, mpfi_get_prec(val));
  452. mpfi_set(this->m_data, val);
  453. return *this;
  454. }
  455. template <unsigned D>
  456. mpfi_float_backend& operator=(const mpfi_float_backend<D>& val)
  457. {
  458. mpfi_set_prec(this->m_data, mpfi_get_prec(val.data()));
  459. mpfi_set(this->m_data, val.data());
  460. return *this;
  461. }
  462. static unsigned default_precision() BOOST_NOEXCEPT
  463. {
  464. return get_default_precision();
  465. }
  466. static void default_precision(unsigned v) BOOST_NOEXCEPT
  467. {
  468. get_default_precision() = v;
  469. }
  470. unsigned precision() const BOOST_NOEXCEPT
  471. {
  472. return multiprecision::detail::digits2_2_10(mpfi_get_prec(this->m_data));
  473. }
  474. void precision(unsigned digits10) BOOST_NOEXCEPT
  475. {
  476. mpfi_float_backend t(*this, digits10);
  477. this->swap(t);
  478. }
  479. };
  480. template <unsigned digits10, class T>
  481. inline typename enable_if<is_arithmetic<T>, bool>::type eval_eq(const mpfi_float_backend<digits10>& a, const T& b) BOOST_NOEXCEPT
  482. {
  483. return a.compare(b) == 0;
  484. }
  485. template <unsigned digits10, class T>
  486. inline typename enable_if<is_arithmetic<T>, bool>::type eval_lt(const mpfi_float_backend<digits10>& a, const T& b) BOOST_NOEXCEPT
  487. {
  488. return a.compare(b) < 0;
  489. }
  490. template <unsigned digits10, class T>
  491. inline typename enable_if<is_arithmetic<T>, bool>::type eval_gt(const mpfi_float_backend<digits10>& a, const T& b) BOOST_NOEXCEPT
  492. {
  493. return a.compare(b) > 0;
  494. }
  495. template <unsigned D1, unsigned D2>
  496. inline void eval_add(mpfi_float_backend<D1>& result, const mpfi_float_backend<D2>& o)
  497. {
  498. mpfi_add(result.data(), result.data(), o.data());
  499. }
  500. template <unsigned D1, unsigned D2>
  501. inline void eval_subtract(mpfi_float_backend<D1>& result, const mpfi_float_backend<D2>& o)
  502. {
  503. mpfi_sub(result.data(), result.data(), o.data());
  504. }
  505. template <unsigned D1, unsigned D2>
  506. inline void eval_multiply(mpfi_float_backend<D1>& result, const mpfi_float_backend<D2>& o)
  507. {
  508. if ((void*)&result == (void*)&o)
  509. mpfi_sqr(result.data(), o.data());
  510. else
  511. mpfi_mul(result.data(), result.data(), o.data());
  512. }
  513. template <unsigned D1, unsigned D2>
  514. inline void eval_divide(mpfi_float_backend<D1>& result, const mpfi_float_backend<D2>& o)
  515. {
  516. mpfi_div(result.data(), result.data(), o.data());
  517. }
  518. template <unsigned digits10>
  519. inline void eval_add(mpfi_float_backend<digits10>& result, unsigned long i)
  520. {
  521. mpfi_add_ui(result.data(), result.data(), i);
  522. }
  523. template <unsigned digits10>
  524. inline void eval_subtract(mpfi_float_backend<digits10>& result, unsigned long i)
  525. {
  526. mpfi_sub_ui(result.data(), result.data(), i);
  527. }
  528. template <unsigned digits10>
  529. inline void eval_multiply(mpfi_float_backend<digits10>& result, unsigned long i)
  530. {
  531. mpfi_mul_ui(result.data(), result.data(), i);
  532. }
  533. template <unsigned digits10>
  534. inline void eval_divide(mpfi_float_backend<digits10>& result, unsigned long i)
  535. {
  536. mpfi_div_ui(result.data(), result.data(), i);
  537. }
  538. template <unsigned digits10>
  539. inline void eval_add(mpfi_float_backend<digits10>& result, long i)
  540. {
  541. if (i > 0)
  542. mpfi_add_ui(result.data(), result.data(), i);
  543. else
  544. mpfi_sub_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
  545. }
  546. template <unsigned digits10>
  547. inline void eval_subtract(mpfi_float_backend<digits10>& result, long i)
  548. {
  549. if (i > 0)
  550. mpfi_sub_ui(result.data(), result.data(), i);
  551. else
  552. mpfi_add_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
  553. }
  554. template <unsigned digits10>
  555. inline void eval_multiply(mpfi_float_backend<digits10>& result, long i)
  556. {
  557. mpfi_mul_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
  558. if (i < 0)
  559. mpfi_neg(result.data(), result.data());
  560. }
  561. template <unsigned digits10>
  562. inline void eval_divide(mpfi_float_backend<digits10>& result, long i)
  563. {
  564. mpfi_div_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
  565. if (i < 0)
  566. mpfi_neg(result.data(), result.data());
  567. }
  568. //
  569. // Specialised 3 arg versions of the basic operators:
  570. //
  571. template <unsigned D1, unsigned D2, unsigned D3>
  572. inline void eval_add(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, const mpfi_float_backend<D3>& y)
  573. {
  574. mpfi_add(a.data(), x.data(), y.data());
  575. }
  576. template <unsigned D1, unsigned D2>
  577. inline void eval_add(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, unsigned long y)
  578. {
  579. mpfi_add_ui(a.data(), x.data(), y);
  580. }
  581. template <unsigned D1, unsigned D2>
  582. inline void eval_add(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, long y)
  583. {
  584. if (y < 0)
  585. mpfi_sub_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
  586. else
  587. mpfi_add_ui(a.data(), x.data(), y);
  588. }
  589. template <unsigned D1, unsigned D2>
  590. inline void eval_add(mpfi_float_backend<D1>& a, unsigned long x, const mpfi_float_backend<D2>& y)
  591. {
  592. mpfi_add_ui(a.data(), y.data(), x);
  593. }
  594. template <unsigned D1, unsigned D2>
  595. inline void eval_add(mpfi_float_backend<D1>& a, long x, const mpfi_float_backend<D2>& y)
  596. {
  597. if (x < 0)
  598. {
  599. mpfi_ui_sub(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data());
  600. mpfi_neg(a.data(), a.data());
  601. }
  602. else
  603. mpfi_add_ui(a.data(), y.data(), x);
  604. }
  605. template <unsigned D1, unsigned D2, unsigned D3>
  606. inline void eval_subtract(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, const mpfi_float_backend<D3>& y)
  607. {
  608. mpfi_sub(a.data(), x.data(), y.data());
  609. }
  610. template <unsigned D1, unsigned D2>
  611. inline void eval_subtract(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, unsigned long y)
  612. {
  613. mpfi_sub_ui(a.data(), x.data(), y);
  614. }
  615. template <unsigned D1, unsigned D2>
  616. inline void eval_subtract(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, long y)
  617. {
  618. if (y < 0)
  619. mpfi_add_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
  620. else
  621. mpfi_sub_ui(a.data(), x.data(), y);
  622. }
  623. template <unsigned D1, unsigned D2>
  624. inline void eval_subtract(mpfi_float_backend<D1>& a, unsigned long x, const mpfi_float_backend<D2>& y)
  625. {
  626. mpfi_ui_sub(a.data(), x, y.data());
  627. }
  628. template <unsigned D1, unsigned D2>
  629. inline void eval_subtract(mpfi_float_backend<D1>& a, long x, const mpfi_float_backend<D2>& y)
  630. {
  631. if (x < 0)
  632. {
  633. mpfi_add_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x));
  634. mpfi_neg(a.data(), a.data());
  635. }
  636. else
  637. mpfi_ui_sub(a.data(), x, y.data());
  638. }
  639. template <unsigned D1, unsigned D2, unsigned D3>
  640. inline void eval_multiply(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, const mpfi_float_backend<D3>& y)
  641. {
  642. if ((void*)&x == (void*)&y)
  643. mpfi_sqr(a.data(), x.data());
  644. else
  645. mpfi_mul(a.data(), x.data(), y.data());
  646. }
  647. template <unsigned D1, unsigned D2>
  648. inline void eval_multiply(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, unsigned long y)
  649. {
  650. mpfi_mul_ui(a.data(), x.data(), y);
  651. }
  652. template <unsigned D1, unsigned D2>
  653. inline void eval_multiply(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, long y)
  654. {
  655. if (y < 0)
  656. {
  657. mpfi_mul_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
  658. a.negate();
  659. }
  660. else
  661. mpfi_mul_ui(a.data(), x.data(), y);
  662. }
  663. template <unsigned D1, unsigned D2>
  664. inline void eval_multiply(mpfi_float_backend<D1>& a, unsigned long x, const mpfi_float_backend<D2>& y)
  665. {
  666. mpfi_mul_ui(a.data(), y.data(), x);
  667. }
  668. template <unsigned D1, unsigned D2>
  669. inline void eval_multiply(mpfi_float_backend<D1>& a, long x, const mpfi_float_backend<D2>& y)
  670. {
  671. if (x < 0)
  672. {
  673. mpfi_mul_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x));
  674. mpfi_neg(a.data(), a.data());
  675. }
  676. else
  677. mpfi_mul_ui(a.data(), y.data(), x);
  678. }
  679. template <unsigned D1, unsigned D2, unsigned D3>
  680. inline void eval_divide(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, const mpfi_float_backend<D3>& y)
  681. {
  682. mpfi_div(a.data(), x.data(), y.data());
  683. }
  684. template <unsigned D1, unsigned D2>
  685. inline void eval_divide(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, unsigned long y)
  686. {
  687. mpfi_div_ui(a.data(), x.data(), y);
  688. }
  689. template <unsigned D1, unsigned D2>
  690. inline void eval_divide(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, long y)
  691. {
  692. if (y < 0)
  693. {
  694. mpfi_div_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
  695. a.negate();
  696. }
  697. else
  698. mpfi_div_ui(a.data(), x.data(), y);
  699. }
  700. template <unsigned D1, unsigned D2>
  701. inline void eval_divide(mpfi_float_backend<D1>& a, unsigned long x, const mpfi_float_backend<D2>& y)
  702. {
  703. mpfi_ui_div(a.data(), x, y.data());
  704. }
  705. template <unsigned D1, unsigned D2>
  706. inline void eval_divide(mpfi_float_backend<D1>& a, long x, const mpfi_float_backend<D2>& y)
  707. {
  708. if (x < 0)
  709. {
  710. mpfi_ui_div(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data());
  711. mpfi_neg(a.data(), a.data());
  712. }
  713. else
  714. mpfi_ui_div(a.data(), x, y.data());
  715. }
  716. template <unsigned digits10>
  717. inline bool eval_is_zero(const mpfi_float_backend<digits10>& val) BOOST_NOEXCEPT
  718. {
  719. return 0 != mpfi_is_zero(val.data());
  720. }
  721. template <unsigned digits10>
  722. inline int eval_get_sign(const mpfi_float_backend<digits10>& val)
  723. {
  724. return detail::mpfi_sgn(val.data());
  725. }
  726. template <unsigned digits10>
  727. inline void eval_convert_to(unsigned long* result, const mpfi_float_backend<digits10>& val)
  728. {
  729. mpfr_float_backend<digits10> t;
  730. mpfi_mid(t.data(), val.data());
  731. eval_convert_to(result, t);
  732. }
  733. template <unsigned digits10>
  734. inline void eval_convert_to(long* result, const mpfi_float_backend<digits10>& val)
  735. {
  736. mpfr_float_backend<digits10> t;
  737. mpfi_mid(t.data(), val.data());
  738. eval_convert_to(result, t);
  739. }
  740. #ifdef _MPFR_H_HAVE_INTMAX_T
  741. template <unsigned digits10>
  742. inline void eval_convert_to(boost::ulong_long_type* result, const mpfi_float_backend<digits10>& val)
  743. {
  744. mpfr_float_backend<digits10> t;
  745. mpfi_mid(t.data(), val.data());
  746. eval_convert_to(result, t);
  747. }
  748. template <unsigned digits10>
  749. inline void eval_convert_to(boost::long_long_type* result, const mpfi_float_backend<digits10>& val)
  750. {
  751. mpfr_float_backend<digits10> t;
  752. mpfi_mid(t.data(), val.data());
  753. eval_convert_to(result, t);
  754. }
  755. #endif
  756. template <unsigned digits10>
  757. inline void eval_convert_to(double* result, const mpfi_float_backend<digits10>& val) BOOST_NOEXCEPT
  758. {
  759. *result = mpfi_get_d(val.data());
  760. }
  761. template <unsigned digits10>
  762. inline void eval_convert_to(long double* result, const mpfi_float_backend<digits10>& val) BOOST_NOEXCEPT
  763. {
  764. mpfr_float_backend<digits10> t;
  765. mpfi_mid(t.data(), val.data());
  766. eval_convert_to(result, t);
  767. }
  768. template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType>
  769. inline void assign_components(mpfi_float_backend<D1>& result, const mpfr_float_backend<D2, AllocationType>& a, const mpfr_float_backend<D2, AllocationType>& b)
  770. {
  771. using default_ops::eval_fpclassify;
  772. if (eval_fpclassify(a) == (int)FP_NAN)
  773. {
  774. mpfi_set_fr(result.data(), a.data());
  775. }
  776. else if (eval_fpclassify(b) == (int)FP_NAN)
  777. {
  778. mpfi_set_fr(result.data(), b.data());
  779. }
  780. else
  781. {
  782. if (a.compare(b) > 0)
  783. {
  784. BOOST_THROW_EXCEPTION(std::runtime_error("Attempt to create interval with invalid range (start is greater than end)."));
  785. }
  786. mpfi_interv_fr(result.data(), a.data(), b.data());
  787. }
  788. }
  789. template <unsigned Digits10, class V>
  790. inline typename enable_if_c<boost::is_constructible<number<mpfr_float_backend<Digits10, allocate_dynamic>, et_on>, V>::value || boost::is_convertible<V, const char*>::value>::type
  791. assign_components(mpfi_float_backend<Digits10>& result, const V& a, const V& b)
  792. {
  793. number<mpfr_float_backend<Digits10, allocate_dynamic>, et_on> x(a), y(b);
  794. assign_components(result, x.backend(), y.backend());
  795. }
  796. //
  797. // Native non-member operations:
  798. //
  799. template <unsigned Digits10>
  800. inline void eval_sqrt(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val)
  801. {
  802. mpfi_sqrt(result.data(), val.data());
  803. }
  804. template <unsigned Digits10>
  805. inline void eval_abs(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val)
  806. {
  807. mpfi_abs(result.data(), val.data());
  808. }
  809. template <unsigned Digits10>
  810. inline void eval_fabs(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val)
  811. {
  812. mpfi_abs(result.data(), val.data());
  813. }
  814. template <unsigned Digits10>
  815. inline void eval_ceil(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val)
  816. {
  817. mpfr_float_backend<Digits10> a, b;
  818. mpfr_set(a.data(), val.left_data(), GMP_RNDN);
  819. mpfr_set(b.data(), val.right_data(), GMP_RNDN);
  820. eval_ceil(a, a);
  821. eval_ceil(b, b);
  822. if (a.compare(b) != 0)
  823. {
  824. BOOST_THROW_EXCEPTION(interval_error("Attempt to take the ceil of a value that straddles an integer boundary."));
  825. }
  826. mpfi_set_fr(result.data(), a.data());
  827. }
  828. template <unsigned Digits10>
  829. inline void eval_floor(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val)
  830. {
  831. mpfr_float_backend<Digits10> a, b;
  832. mpfr_set(a.data(), val.left_data(), GMP_RNDN);
  833. mpfr_set(b.data(), val.right_data(), GMP_RNDN);
  834. eval_floor(a, a);
  835. eval_floor(b, b);
  836. if (a.compare(b) != 0)
  837. {
  838. BOOST_THROW_EXCEPTION(interval_error("Attempt to take the floor of a value that straddles an integer boundary."));
  839. }
  840. mpfi_set_fr(result.data(), a.data());
  841. }
  842. template <unsigned Digits10>
  843. inline void eval_ldexp(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val, long e)
  844. {
  845. if (e > 0)
  846. mpfi_mul_2exp(result.data(), val.data(), e);
  847. else if (e < 0)
  848. mpfi_div_2exp(result.data(), val.data(), -e);
  849. else
  850. result = val;
  851. }
  852. template <unsigned Digits10>
  853. inline void eval_frexp(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val, int* e)
  854. {
  855. mpfr_float_backend<Digits10> t, rt;
  856. mpfi_mid(t.data(), val.data());
  857. eval_frexp(rt, t, e);
  858. eval_ldexp(result, val, -*e);
  859. }
  860. template <unsigned Digits10>
  861. inline void eval_frexp(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val, long* e)
  862. {
  863. mpfr_float_backend<Digits10> t, rt;
  864. mpfi_mid(t.data(), val.data());
  865. eval_frexp(rt, t, e);
  866. eval_ldexp(result, val, -*e);
  867. }
  868. template <unsigned Digits10>
  869. inline int eval_fpclassify(const mpfi_float_backend<Digits10>& val) BOOST_NOEXCEPT
  870. {
  871. return mpfi_inf_p(val.data()) ? FP_INFINITE : mpfi_nan_p(val.data()) ? FP_NAN : mpfi_is_zero(val.data()) ? FP_ZERO : FP_NORMAL;
  872. }
  873. template <unsigned Digits10>
  874. inline void eval_pow(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& b, const mpfi_float_backend<Digits10>& e)
  875. {
  876. typedef typename boost::multiprecision::detail::canonical<unsigned, mpfi_float_backend<Digits10> >::type ui_type;
  877. using default_ops::eval_get_sign;
  878. int s = eval_get_sign(b);
  879. if (s == 0)
  880. {
  881. if (eval_get_sign(e) == 0)
  882. {
  883. result = ui_type(1);
  884. }
  885. else
  886. {
  887. result = ui_type(0);
  888. }
  889. return;
  890. }
  891. if (s < 0)
  892. {
  893. if (eval_get_sign(e) < 0)
  894. {
  895. mpfi_float_backend<Digits10> t1, t2;
  896. t1 = e;
  897. t1.negate();
  898. eval_pow(t2, b, t1);
  899. t1 = ui_type(1);
  900. eval_divide(result, t1, t2);
  901. return;
  902. }
  903. typename boost::multiprecision::detail::canonical<boost::uintmax_t, mpfi_float_backend<Digits10> >::type an;
  904. #ifndef BOOST_NO_EXCEPTIONS
  905. try
  906. {
  907. #endif
  908. using default_ops::eval_convert_to;
  909. eval_convert_to(&an, e);
  910. if (e.compare(an) == 0)
  911. {
  912. mpfi_float_backend<Digits10> pb(b);
  913. pb.negate();
  914. eval_pow(result, pb, e);
  915. if (an & 1u)
  916. result.negate();
  917. return;
  918. }
  919. #ifndef BOOST_NO_EXCEPTIONS
  920. }
  921. catch (const std::exception&)
  922. {
  923. // conversion failed, just fall through, value is not an integer.
  924. }
  925. #endif
  926. result = std::numeric_limits<number<mpfi_float_backend<Digits10>, et_on> >::quiet_NaN().backend();
  927. return;
  928. }
  929. mpfi_log(result.data(), b.data());
  930. mpfi_mul(result.data(), result.data(), e.data());
  931. mpfi_exp(result.data(), result.data());
  932. }
  933. template <unsigned Digits10>
  934. inline void eval_exp(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  935. {
  936. mpfi_exp(result.data(), arg.data());
  937. }
  938. template <unsigned Digits10>
  939. inline void eval_exp2(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  940. {
  941. mpfi_exp2(result.data(), arg.data());
  942. }
  943. template <unsigned Digits10>
  944. inline void eval_log(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  945. {
  946. mpfi_log(result.data(), arg.data());
  947. }
  948. template <unsigned Digits10>
  949. inline void eval_log10(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  950. {
  951. mpfi_log10(result.data(), arg.data());
  952. }
  953. template <unsigned Digits10>
  954. inline void eval_sin(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  955. {
  956. mpfi_sin(result.data(), arg.data());
  957. }
  958. template <unsigned Digits10>
  959. inline void eval_cos(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  960. {
  961. mpfi_cos(result.data(), arg.data());
  962. }
  963. template <unsigned Digits10>
  964. inline void eval_tan(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  965. {
  966. mpfi_tan(result.data(), arg.data());
  967. }
  968. template <unsigned Digits10>
  969. inline void eval_asin(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  970. {
  971. mpfi_asin(result.data(), arg.data());
  972. }
  973. template <unsigned Digits10>
  974. inline void eval_acos(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  975. {
  976. mpfi_acos(result.data(), arg.data());
  977. }
  978. template <unsigned Digits10>
  979. inline void eval_atan(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  980. {
  981. mpfi_atan(result.data(), arg.data());
  982. }
  983. template <unsigned Digits10>
  984. inline void eval_atan2(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg1, const mpfi_float_backend<Digits10>& arg2)
  985. {
  986. mpfi_atan2(result.data(), arg1.data(), arg2.data());
  987. }
  988. template <unsigned Digits10>
  989. inline void eval_sinh(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  990. {
  991. mpfi_sinh(result.data(), arg.data());
  992. }
  993. template <unsigned Digits10>
  994. inline void eval_cosh(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  995. {
  996. mpfi_cosh(result.data(), arg.data());
  997. }
  998. template <unsigned Digits10>
  999. inline void eval_tanh(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  1000. {
  1001. mpfi_tanh(result.data(), arg.data());
  1002. }
  1003. template <unsigned Digits10>
  1004. inline void eval_log2(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  1005. {
  1006. mpfi_log2(result.data(), arg.data());
  1007. }
  1008. template <unsigned Digits10>
  1009. inline std::size_t hash_value(const mpfi_float_backend<Digits10>& val)
  1010. {
  1011. std::size_t result = 0;
  1012. std::size_t len = val.left_data()[0]._mpfr_prec / mp_bits_per_limb;
  1013. if (val.left_data()[0]._mpfr_prec % mp_bits_per_limb)
  1014. ++len;
  1015. for (std::size_t i = 0; i < len; ++i)
  1016. boost::hash_combine(result, val.left_data()[0]._mpfr_d[i]);
  1017. boost::hash_combine(result, val.left_data()[0]._mpfr_exp);
  1018. boost::hash_combine(result, val.left_data()[0]._mpfr_sign);
  1019. len = val.right_data()[0]._mpfr_prec / mp_bits_per_limb;
  1020. if (val.right_data()[0]._mpfr_prec % mp_bits_per_limb)
  1021. ++len;
  1022. for (std::size_t i = 0; i < len; ++i)
  1023. boost::hash_combine(result, val.right_data()[0]._mpfr_d[i]);
  1024. boost::hash_combine(result, val.right_data()[0]._mpfr_exp);
  1025. boost::hash_combine(result, val.right_data()[0]._mpfr_sign);
  1026. return result;
  1027. }
  1028. template <class To, unsigned D>
  1029. void generic_interconvert(To& to, const mpfi_float_backend<D>& from, const mpl::int_<number_kind_integer>& to_type, const mpl::int_<number_kind_floating_point>& from_type)
  1030. {
  1031. using boost::multiprecision::detail::generic_interconvert;
  1032. mpfr_float_backend<D> t;
  1033. mpfi_mid(t.data(), from.data());
  1034. generic_interconvert(to, t, to_type, from_type);
  1035. }
  1036. template <class To, unsigned D>
  1037. void generic_interconvert(To& to, const mpfi_float_backend<D>& from, const mpl::int_<number_kind_rational>& to_type, const mpl::int_<number_kind_floating_point>& from_type)
  1038. {
  1039. using boost::multiprecision::detail::generic_interconvert;
  1040. mpfr_float_backend<D> t;
  1041. mpfi_mid(t.data(), from.data());
  1042. generic_interconvert(to, t, to_type, from_type);
  1043. }
  1044. template <class To, unsigned D>
  1045. void generic_interconvert(To& to, const mpfi_float_backend<D>& from, const mpl::int_<number_kind_floating_point>& to_type, const mpl::int_<number_kind_floating_point>& from_type)
  1046. {
  1047. using boost::multiprecision::detail::generic_interconvert;
  1048. mpfr_float_backend<D> t;
  1049. mpfi_mid(t.data(), from.data());
  1050. generic_interconvert(to, t, to_type, from_type);
  1051. }
  1052. } // namespace backends
  1053. #ifdef BOOST_NO_SFINAE_EXPR
  1054. namespace detail {
  1055. template <unsigned D1, unsigned D2>
  1056. struct is_explicitly_convertible<backends::mpfi_float_backend<D1>, backends::mpfi_float_backend<D2> > : public mpl::true_
  1057. {};
  1058. } // namespace detail
  1059. #endif
  1060. namespace detail {
  1061. template <>
  1062. struct is_variable_precision<backends::mpfi_float_backend<0> > : public true_type
  1063. {};
  1064. } // namespace detail
  1065. template <>
  1066. struct number_category<detail::canonical<mpfi_t, backends::mpfi_float_backend<0> >::type> : public mpl::int_<number_kind_floating_point>
  1067. {};
  1068. template <unsigned Digits10>
  1069. struct is_interval_number<backends::mpfi_float_backend<Digits10> > : public mpl::true_
  1070. {};
  1071. using boost::multiprecision::backends::mpfi_float_backend;
  1072. typedef number<mpfi_float_backend<50> > mpfi_float_50;
  1073. typedef number<mpfi_float_backend<100> > mpfi_float_100;
  1074. typedef number<mpfi_float_backend<500> > mpfi_float_500;
  1075. typedef number<mpfi_float_backend<1000> > mpfi_float_1000;
  1076. typedef number<mpfi_float_backend<0> > mpfi_float;
  1077. //
  1078. // Special interval specific functions:
  1079. //
  1080. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1081. inline number<mpfr_float_backend<Digits10>, ExpressionTemplates> lower(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val)
  1082. {
  1083. boost::multiprecision::detail::scoped_default_precision<number<mpfr_float_backend<Digits10>, ExpressionTemplates> > precision_guard(val);
  1084. number<mpfr_float_backend<Digits10> > result;
  1085. mpfr_set(result.backend().data(), val.backend().left_data(), GMP_RNDN);
  1086. return result;
  1087. }
  1088. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1089. inline number<mpfr_float_backend<Digits10>, ExpressionTemplates> upper(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val)
  1090. {
  1091. boost::multiprecision::detail::scoped_default_precision<number<mpfr_float_backend<Digits10>, ExpressionTemplates> > precision_guard(val);
  1092. number<mpfr_float_backend<Digits10> > result;
  1093. mpfr_set(result.backend().data(), val.backend().right_data(), GMP_RNDN);
  1094. return result;
  1095. }
  1096. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1097. inline number<mpfr_float_backend<Digits10>, ExpressionTemplates> median(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val)
  1098. {
  1099. boost::multiprecision::detail::scoped_default_precision<number<mpfr_float_backend<Digits10>, ExpressionTemplates> > precision_guard(val);
  1100. number<mpfr_float_backend<Digits10> > result;
  1101. mpfi_mid(result.backend().data(), val.backend().data());
  1102. return result;
  1103. }
  1104. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1105. inline number<mpfr_float_backend<Digits10>, ExpressionTemplates> width(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val)
  1106. {
  1107. boost::multiprecision::detail::scoped_default_precision<number<mpfr_float_backend<Digits10>, ExpressionTemplates> > precision_guard(val);
  1108. number<mpfr_float_backend<Digits10> > result;
  1109. mpfi_diam_abs(result.backend().data(), val.backend().data());
  1110. return result;
  1111. }
  1112. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1113. inline number<mpfi_float_backend<Digits10>, ExpressionTemplates> intersect(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b)
  1114. {
  1115. boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(a, b);
  1116. number<mpfi_float_backend<Digits10>, ExpressionTemplates> result;
  1117. mpfi_intersect(result.backend().data(), a.backend().data(), b.backend().data());
  1118. return result;
  1119. }
  1120. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1121. inline number<mpfi_float_backend<Digits10>, ExpressionTemplates> hull(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b)
  1122. {
  1123. boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(a, b);
  1124. number<mpfi_float_backend<Digits10>, ExpressionTemplates> result;
  1125. mpfi_union(result.backend().data(), a.backend().data(), b.backend().data());
  1126. return result;
  1127. }
  1128. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1129. inline bool overlap(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b)
  1130. {
  1131. return (lower(a) <= lower(b) && lower(b) <= upper(a)) ||
  1132. (lower(b) <= lower(a) && lower(a) <= upper(b));
  1133. }
  1134. template <unsigned Digits10, expression_template_option ExpressionTemplates1, expression_template_option ExpressionTemplates2>
  1135. inline bool in(const number<mpfr_float_backend<Digits10>, ExpressionTemplates1>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates2>& b)
  1136. {
  1137. return mpfi_is_inside_fr(a.backend().data(), b.backend().data()) != 0;
  1138. }
  1139. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1140. inline bool zero_in(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a)
  1141. {
  1142. return mpfi_has_zero(a.backend().data()) != 0;
  1143. }
  1144. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1145. inline bool subset(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b)
  1146. {
  1147. return mpfi_is_inside(a.backend().data(), b.backend().data()) != 0;
  1148. }
  1149. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1150. inline bool proper_subset(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b)
  1151. {
  1152. return mpfi_is_strictly_inside(a.backend().data(), b.backend().data()) != 0;
  1153. }
  1154. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1155. inline bool empty(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a)
  1156. {
  1157. return mpfi_is_empty(a.backend().data()) != 0;
  1158. }
  1159. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1160. inline bool singleton(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a)
  1161. {
  1162. return mpfr_cmp(a.backend().left_data(), a.backend().right_data()) == 0;
  1163. }
  1164. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1165. struct component_type<number<mpfi_float_backend<Digits10>, ExpressionTemplates> >
  1166. {
  1167. typedef number<mpfr_float_backend<Digits10>, ExpressionTemplates> type;
  1168. };
  1169. //
  1170. // Overloaded special functions which call native mpfr routines:
  1171. //
  1172. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1173. inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
  1174. {
  1175. boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
  1176. boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
  1177. mpfi_asinh(result.backend().data(), arg.backend().data());
  1178. return result;
  1179. }
  1180. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1181. inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
  1182. {
  1183. boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
  1184. boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
  1185. mpfi_acosh(result.backend().data(), arg.backend().data());
  1186. return result;
  1187. }
  1188. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1189. inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
  1190. {
  1191. boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
  1192. boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
  1193. mpfi_atanh(result.backend().data(), arg.backend().data());
  1194. return result;
  1195. }
  1196. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1197. inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
  1198. {
  1199. boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
  1200. boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
  1201. mpfi_cbrt(result.backend().data(), arg.backend().data());
  1202. return result;
  1203. }
  1204. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1205. inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
  1206. {
  1207. boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
  1208. boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
  1209. mpfi_expm1(result.backend().data(), arg.backend().data());
  1210. return result;
  1211. }
  1212. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1213. inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
  1214. {
  1215. boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
  1216. boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
  1217. mpfi_log1p(result.backend().data(), arg.backend().data());
  1218. return result;
  1219. }
  1220. } // namespace multiprecision
  1221. namespace math {
  1222. namespace tools {
  1223. template <>
  1224. inline int digits<boost::multiprecision::mpfi_float>()
  1225. #ifdef BOOST_MATH_NOEXCEPT
  1226. BOOST_NOEXCEPT
  1227. #endif
  1228. {
  1229. return multiprecision::detail::digits10_2_2(boost::multiprecision::mpfi_float::default_precision());
  1230. }
  1231. template <>
  1232. inline int digits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> >()
  1233. #ifdef BOOST_MATH_NOEXCEPT
  1234. BOOST_NOEXCEPT
  1235. #endif
  1236. {
  1237. return multiprecision::detail::digits10_2_2(boost::multiprecision::mpfi_float::default_precision());
  1238. }
  1239. template <>
  1240. inline boost::multiprecision::mpfi_float
  1241. max_value<boost::multiprecision::mpfi_float>()
  1242. {
  1243. boost::multiprecision::mpfi_float result(0.5);
  1244. mpfi_mul_2exp(result.backend().data(), result.backend().data(), mpfr_get_emax());
  1245. //BOOST_ASSERT(mpfi_number_p(result.backend().data()));
  1246. return result;
  1247. }
  1248. template <>
  1249. inline boost::multiprecision::mpfi_float
  1250. min_value<boost::multiprecision::mpfi_float>()
  1251. {
  1252. boost::multiprecision::mpfi_float result(0.5);
  1253. mpfi_div_2exp(result.backend().data(), result.backend().data(), -mpfr_get_emin());
  1254. //BOOST_ASSERT(mpfi_number_p(result.backend().data()));
  1255. return result;
  1256. }
  1257. template <>
  1258. inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off>
  1259. max_value<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> >()
  1260. {
  1261. boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> result(0.5);
  1262. mpfi_mul_2exp(result.backend().data(), result.backend().data(), mpfr_get_emax());
  1263. //BOOST_ASSERT(mpfi_number_p(result.backend().data()));
  1264. return result;
  1265. }
  1266. template <>
  1267. inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off>
  1268. min_value<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> >()
  1269. {
  1270. boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> result(0.5);
  1271. mpfi_div_2exp(result.backend().data(), result.backend().data(), -mpfr_get_emin());
  1272. //BOOST_ASSERT(mpfi_number_p(result.backend().data()));
  1273. return result;
  1274. }
  1275. // mpfi gets used with logged_adaptor fairly often, so specialize for that use case as well:
  1276. typedef boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float::backend_type>, boost::multiprecision::et_on> logged_type1;
  1277. typedef boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float::backend_type>, boost::multiprecision::et_off> logged_type2;
  1278. template <>
  1279. inline int digits<logged_type1>()
  1280. #ifdef BOOST_MATH_NOEXCEPT
  1281. BOOST_NOEXCEPT
  1282. #endif
  1283. {
  1284. return multiprecision::detail::digits10_2_2(logged_type1::default_precision());
  1285. }
  1286. template <>
  1287. inline int digits<logged_type2>()
  1288. #ifdef BOOST_MATH_NOEXCEPT
  1289. BOOST_NOEXCEPT
  1290. #endif
  1291. {
  1292. return multiprecision::detail::digits10_2_2(logged_type1::default_precision());
  1293. }
  1294. template <>
  1295. inline logged_type1
  1296. max_value<logged_type1>()
  1297. {
  1298. logged_type1 result(0.5);
  1299. mpfi_mul_2exp(result.backend().value().data(), result.backend().value().data(), mpfr_get_emax());
  1300. //BOOST_ASSERT(mpfi_number_p(result.backend().data()));
  1301. return result;
  1302. }
  1303. template <>
  1304. inline logged_type1
  1305. min_value<logged_type1>()
  1306. {
  1307. logged_type1 result(0.5);
  1308. mpfi_div_2exp(result.backend().value().data(), result.backend().value().data(), -mpfr_get_emin());
  1309. //BOOST_ASSERT(mpfi_number_p(result.backend().data()));
  1310. return result;
  1311. }
  1312. template <>
  1313. inline logged_type2
  1314. max_value<logged_type2>()
  1315. {
  1316. logged_type2 result(0.5);
  1317. mpfi_mul_2exp(result.backend().value().data(), result.backend().value().data(), mpfr_get_emax());
  1318. //BOOST_ASSERT(mpfi_number_p(result.backend().data()));
  1319. return result;
  1320. }
  1321. template <>
  1322. inline logged_type2
  1323. min_value<logged_type2>()
  1324. {
  1325. logged_type2 result(0.5);
  1326. mpfi_div_2exp(result.backend().value().data(), result.backend().value().data(), -mpfr_get_emin());
  1327. //BOOST_ASSERT(mpfi_number_p(result.backend().data()));
  1328. return result;
  1329. }
  1330. } // namespace tools
  1331. namespace constants { namespace detail {
  1332. template <class T>
  1333. struct constant_pi;
  1334. template <class T>
  1335. struct constant_ln_two;
  1336. template <class T>
  1337. struct constant_euler;
  1338. template <class T>
  1339. struct constant_catalan;
  1340. //
  1341. // Initializer: ensure all our constants are initialized prior to the first call of main:
  1342. //
  1343. template <class T>
  1344. struct mpfi_initializer
  1345. {
  1346. struct init
  1347. {
  1348. init()
  1349. {
  1350. boost::math::constants::pi<T>();
  1351. boost::math::constants::ln_two<T>();
  1352. boost::math::constants::euler<T>();
  1353. boost::math::constants::catalan<T>();
  1354. }
  1355. void force_instantiate() const {}
  1356. };
  1357. static const init initializer;
  1358. static void force_instantiate()
  1359. {
  1360. initializer.force_instantiate();
  1361. }
  1362. };
  1363. template <class T>
  1364. const typename mpfi_initializer<T>::init mpfi_initializer<T>::initializer;
  1365. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1366. struct constant_pi<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
  1367. {
  1368. typedef boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result_type;
  1369. template <int N>
  1370. static inline const result_type& get(const mpl::int_<N>&)
  1371. {
  1372. mpfi_initializer<result_type>::force_instantiate();
  1373. static result_type result;
  1374. static bool has_init = false;
  1375. if (!has_init)
  1376. {
  1377. has_init = true;
  1378. mpfi_const_pi(result.backend().data());
  1379. }
  1380. return result;
  1381. }
  1382. static inline result_type get(const mpl::int_<0>&)
  1383. {
  1384. result_type result;
  1385. mpfi_const_pi(result.backend().data());
  1386. return result;
  1387. }
  1388. };
  1389. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1390. struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
  1391. {
  1392. typedef boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result_type;
  1393. template <int N>
  1394. static inline const result_type& get(const mpl::int_<N>&)
  1395. {
  1396. mpfi_initializer<result_type>::force_instantiate();
  1397. static result_type result;
  1398. static bool has_init = false;
  1399. if (!has_init)
  1400. {
  1401. has_init = true;
  1402. mpfi_const_log2(result.backend().data());
  1403. }
  1404. return result;
  1405. }
  1406. static inline result_type get(const mpl::int_<0>&)
  1407. {
  1408. result_type result;
  1409. mpfi_const_log2(result.backend().data());
  1410. return result;
  1411. }
  1412. };
  1413. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1414. struct constant_euler<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
  1415. {
  1416. typedef boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result_type;
  1417. template <int N>
  1418. static inline result_type const& get(const mpl::int_<N>&)
  1419. {
  1420. mpfi_initializer<result_type>::force_instantiate();
  1421. static result_type result;
  1422. static bool has_init = false;
  1423. if (!has_init)
  1424. {
  1425. has_init = true;
  1426. mpfi_const_euler(result.backend().data());
  1427. }
  1428. return result;
  1429. }
  1430. static inline result_type get(const mpl::int_<0>&)
  1431. {
  1432. result_type result;
  1433. mpfi_const_euler(result.backend().data());
  1434. return result;
  1435. }
  1436. };
  1437. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1438. struct constant_catalan<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
  1439. {
  1440. typedef boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result_type;
  1441. template <int N>
  1442. static inline result_type const& get(const mpl::int_<N>&)
  1443. {
  1444. mpfi_initializer<result_type>::force_instantiate();
  1445. static result_type result;
  1446. static bool has_init = false;
  1447. if (!has_init)
  1448. {
  1449. has_init = true;
  1450. mpfi_const_catalan(result.backend().data());
  1451. }
  1452. return result;
  1453. }
  1454. static inline result_type get(const mpl::int_<0>&)
  1455. {
  1456. result_type result;
  1457. mpfi_const_catalan(result.backend().data());
  1458. return result;
  1459. }
  1460. };
  1461. }} // namespace constants::detail
  1462. } // namespace math
  1463. } // namespace boost
  1464. namespace std {
  1465. //
  1466. // numeric_limits [partial] specializations for the types declared in this header:
  1467. //
  1468. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1469. class numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
  1470. {
  1471. typedef boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> number_type;
  1472. public:
  1473. BOOST_STATIC_CONSTEXPR bool is_specialized = true;
  1474. static number_type(min)()
  1475. {
  1476. initializer.do_nothing();
  1477. static std::pair<bool, number_type> value;
  1478. if (!value.first)
  1479. {
  1480. value.first = true;
  1481. value.second = 0.5;
  1482. mpfi_div_2exp(value.second.backend().data(), value.second.backend().data(), -mpfr_get_emin());
  1483. }
  1484. return value.second;
  1485. }
  1486. static number_type(max)()
  1487. {
  1488. initializer.do_nothing();
  1489. static std::pair<bool, number_type> value;
  1490. if (!value.first)
  1491. {
  1492. value.first = true;
  1493. value.second = 0.5;
  1494. mpfi_mul_2exp(value.second.backend().data(), value.second.backend().data(), mpfr_get_emax());
  1495. }
  1496. return value.second;
  1497. }
  1498. BOOST_STATIC_CONSTEXPR number_type lowest()
  1499. {
  1500. return -(max)();
  1501. }
  1502. BOOST_STATIC_CONSTEXPR int digits = static_cast<int>((Digits10 * 1000L) / 301L + ((Digits10 * 1000L) % 301 ? 2 : 1));
  1503. BOOST_STATIC_CONSTEXPR int digits10 = Digits10;
  1504. // Is this really correct???
  1505. BOOST_STATIC_CONSTEXPR int max_digits10 = Digits10 + 3;
  1506. BOOST_STATIC_CONSTEXPR bool is_signed = true;
  1507. BOOST_STATIC_CONSTEXPR bool is_integer = false;
  1508. BOOST_STATIC_CONSTEXPR bool is_exact = false;
  1509. BOOST_STATIC_CONSTEXPR int radix = 2;
  1510. static number_type epsilon()
  1511. {
  1512. initializer.do_nothing();
  1513. static std::pair<bool, number_type> value;
  1514. if (!value.first)
  1515. {
  1516. value.first = true;
  1517. value.second = 1;
  1518. mpfi_div_2exp(value.second.backend().data(), value.second.backend().data(), std::numeric_limits<number_type>::digits - 1);
  1519. }
  1520. return value.second;
  1521. }
  1522. // What value should this be????
  1523. static number_type round_error()
  1524. {
  1525. // returns epsilon/2
  1526. initializer.do_nothing();
  1527. static std::pair<bool, number_type> value;
  1528. if (!value.first)
  1529. {
  1530. value.first = true;
  1531. value.second = 1;
  1532. mpfi_div_2exp(value.second.backend().data(), value.second.backend().data(), 1);
  1533. }
  1534. return value.second;
  1535. }
  1536. BOOST_STATIC_CONSTEXPR long min_exponent = MPFR_EMIN_DEFAULT;
  1537. BOOST_STATIC_CONSTEXPR long min_exponent10 = (MPFR_EMIN_DEFAULT / 1000) * 301L;
  1538. BOOST_STATIC_CONSTEXPR long max_exponent = MPFR_EMAX_DEFAULT;
  1539. BOOST_STATIC_CONSTEXPR long max_exponent10 = (MPFR_EMAX_DEFAULT / 1000) * 301L;
  1540. BOOST_STATIC_CONSTEXPR bool has_infinity = true;
  1541. BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true;
  1542. BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
  1543. BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
  1544. BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
  1545. static number_type infinity()
  1546. {
  1547. initializer.do_nothing();
  1548. static std::pair<bool, number_type> value;
  1549. if (!value.first)
  1550. {
  1551. boost::multiprecision::mpfr_float_backend<Digits10> t;
  1552. mpfr_set_inf(t.data(), 1);
  1553. value.first = true;
  1554. mpfi_set_fr(value.second.backend().data(), t.data());
  1555. }
  1556. return value.second;
  1557. }
  1558. static number_type quiet_NaN()
  1559. {
  1560. initializer.do_nothing();
  1561. static std::pair<bool, number_type> value;
  1562. if (!value.first)
  1563. {
  1564. boost::multiprecision::mpfr_float_backend<Digits10> t;
  1565. mpfr_set_nan(t.data());
  1566. value.first = true;
  1567. mpfi_set_fr(value.second.backend().data(), t.data());
  1568. }
  1569. return value.second;
  1570. }
  1571. BOOST_STATIC_CONSTEXPR number_type signaling_NaN()
  1572. {
  1573. return number_type(0);
  1574. }
  1575. BOOST_STATIC_CONSTEXPR number_type denorm_min() { return number_type(0); }
  1576. BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
  1577. BOOST_STATIC_CONSTEXPR bool is_bounded = true;
  1578. BOOST_STATIC_CONSTEXPR bool is_modulo = false;
  1579. BOOST_STATIC_CONSTEXPR bool traps = true;
  1580. BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
  1581. BOOST_STATIC_CONSTEXPR float_round_style round_style = round_to_nearest;
  1582. private:
  1583. struct data_initializer
  1584. {
  1585. data_initializer()
  1586. {
  1587. std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<digits10> > >::epsilon();
  1588. std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<digits10> > >::round_error();
  1589. (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<digits10> > >::min)();
  1590. (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<digits10> > >::max)();
  1591. std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<digits10> > >::infinity();
  1592. std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<digits10> > >::quiet_NaN();
  1593. }
  1594. void do_nothing() const {}
  1595. };
  1596. static const data_initializer initializer;
  1597. };
  1598. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1599. const typename numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::data_initializer numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::initializer;
  1600. #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
  1601. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1602. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::digits;
  1603. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1604. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::digits10;
  1605. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1606. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::max_digits10;
  1607. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1608. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_signed;
  1609. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1610. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_integer;
  1611. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1612. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_exact;
  1613. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1614. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::radix;
  1615. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1616. BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::min_exponent;
  1617. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1618. BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::min_exponent10;
  1619. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1620. BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::max_exponent;
  1621. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1622. BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::max_exponent10;
  1623. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1624. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::has_infinity;
  1625. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1626. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::has_quiet_NaN;
  1627. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1628. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::has_signaling_NaN;
  1629. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1630. BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::has_denorm;
  1631. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1632. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::has_denorm_loss;
  1633. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1634. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_iec559;
  1635. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1636. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_bounded;
  1637. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1638. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_modulo;
  1639. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1640. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::traps;
  1641. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1642. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::tinyness_before;
  1643. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1644. BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::round_style;
  1645. #endif
  1646. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1647. class numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >
  1648. {
  1649. typedef boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> number_type;
  1650. public:
  1651. BOOST_STATIC_CONSTEXPR bool is_specialized = false;
  1652. static number_type(min)() { return number_type(0); }
  1653. static number_type(max)() { return number_type(0); }
  1654. static number_type lowest() { return number_type(0); }
  1655. BOOST_STATIC_CONSTEXPR int digits = 0;
  1656. BOOST_STATIC_CONSTEXPR int digits10 = 0;
  1657. BOOST_STATIC_CONSTEXPR int max_digits10 = 0;
  1658. BOOST_STATIC_CONSTEXPR bool is_signed = false;
  1659. BOOST_STATIC_CONSTEXPR bool is_integer = false;
  1660. BOOST_STATIC_CONSTEXPR bool is_exact = false;
  1661. BOOST_STATIC_CONSTEXPR int radix = 0;
  1662. static number_type epsilon() { return number_type(0); }
  1663. static number_type round_error() { return number_type(0); }
  1664. BOOST_STATIC_CONSTEXPR int min_exponent = 0;
  1665. BOOST_STATIC_CONSTEXPR int min_exponent10 = 0;
  1666. BOOST_STATIC_CONSTEXPR int max_exponent = 0;
  1667. BOOST_STATIC_CONSTEXPR int max_exponent10 = 0;
  1668. BOOST_STATIC_CONSTEXPR bool has_infinity = false;
  1669. BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false;
  1670. BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
  1671. BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
  1672. BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
  1673. static number_type infinity() { return number_type(0); }
  1674. static number_type quiet_NaN() { return number_type(0); }
  1675. static number_type signaling_NaN() { return number_type(0); }
  1676. static number_type denorm_min() { return number_type(0); }
  1677. BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
  1678. BOOST_STATIC_CONSTEXPR bool is_bounded = false;
  1679. BOOST_STATIC_CONSTEXPR bool is_modulo = false;
  1680. BOOST_STATIC_CONSTEXPR bool traps = false;
  1681. BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
  1682. BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero;
  1683. };
  1684. #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
  1685. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1686. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::digits;
  1687. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1688. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::digits10;
  1689. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1690. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::max_digits10;
  1691. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1692. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_signed;
  1693. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1694. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_integer;
  1695. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1696. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_exact;
  1697. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1698. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::radix;
  1699. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1700. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::min_exponent;
  1701. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1702. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::min_exponent10;
  1703. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1704. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::max_exponent;
  1705. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1706. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::max_exponent10;
  1707. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1708. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::has_infinity;
  1709. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1710. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::has_quiet_NaN;
  1711. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1712. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::has_signaling_NaN;
  1713. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1714. BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::has_denorm;
  1715. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1716. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::has_denorm_loss;
  1717. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1718. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_iec559;
  1719. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1720. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_bounded;
  1721. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1722. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_modulo;
  1723. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1724. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::traps;
  1725. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1726. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::tinyness_before;
  1727. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  1728. BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::round_style;
  1729. #endif
  1730. } // namespace std
  1731. #endif