mpfi.hpp 113 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright 2011 John Maddock. Distributed under the Boost
  3. // Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_MP_MPFI_HPP
  6. #define BOOST_MP_MPFI_HPP
  7. #include <algorithm>
  8. #include <cmath>
  9. #include <cstdint>
  10. #include <type_traits>
  11. #include <string>
  12. #include <boost/multiprecision/detail/standalone_config.hpp>
  13. #include <boost/multiprecision/detail/fpclassify.hpp>
  14. #include <boost/multiprecision/number.hpp>
  15. #include <boost/multiprecision/detail/digits.hpp>
  16. #include <boost/multiprecision/detail/precision.hpp>
  17. #include <boost/multiprecision/detail/atomic.hpp>
  18. #include <boost/multiprecision/traits/max_digits10.hpp>
  19. #include <boost/multiprecision/mpfr.hpp>
  20. #include <boost/multiprecision/logged_adaptor.hpp>
  21. #include <boost/multiprecision/detail/hash.hpp>
  22. #include <boost/multiprecision/detail/no_exceptions_support.hpp>
  23. #include <boost/multiprecision/detail/assert.hpp>
  24. #include <mpfi.h>
  25. #ifdef BOOST_MP_MATH_AVAILABLE
  26. #include <boost/math/constants/constants.hpp>
  27. #endif
  28. #ifndef BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION
  29. #define BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION 20
  30. #endif
  31. namespace boost {
  32. namespace multiprecision {
  33. template <unsigned digits10>
  34. struct number_category<backends::mpfi_float_backend<digits10> > : public std::integral_constant<int, number_kind_floating_point>
  35. {};
  36. struct interval_error : public std::runtime_error
  37. {
  38. interval_error(const std::string& s) : std::runtime_error(s) {}
  39. };
  40. namespace detail {
  41. template <>
  42. struct is_variable_precision<backends::mpfi_float_backend<0> > : public std::integral_constant<bool, true>
  43. {};
  44. } // namespace detail
  45. namespace backends {
  46. namespace detail {
  47. inline int mpfi_sgn(mpfi_srcptr p)
  48. {
  49. if (mpfi_is_zero(p))
  50. return 0;
  51. if (mpfi_is_strictly_pos(p))
  52. return 1;
  53. if (mpfi_is_strictly_neg(p))
  54. return -1;
  55. BOOST_MP_THROW_EXCEPTION(interval_error("Sign of interval is ambiguous."));
  56. }
  57. template <unsigned digits10>
  58. struct mpfi_float_imp;
  59. template <unsigned digits10>
  60. struct mpfi_float_imp
  61. {
  62. #ifdef BOOST_HAS_LONG_LONG
  63. using signed_types = std::tuple<long, long long> ;
  64. using unsigned_types = std::tuple<unsigned long, unsigned long long>;
  65. #else
  66. using signed_types = std::tuple<long> ;
  67. using unsigned_types = std::tuple<unsigned long>;
  68. #endif
  69. using float_types = std::tuple<double, long double>;
  70. using exponent_type = long ;
  71. mpfi_float_imp()
  72. {
  73. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
  74. mpfi_set_ui(m_data, 0u);
  75. }
  76. mpfi_float_imp(unsigned prec)
  77. {
  78. mpfi_init2(m_data, prec);
  79. mpfi_set_ui(m_data, 0u);
  80. }
  81. mpfi_float_imp(const mpfi_float_imp& o)
  82. {
  83. mpfi_init2(m_data, preserve_source_precision() ? mpfi_get_prec(o.data()) : boost::multiprecision::detail::digits10_2_2(get_default_precision()));
  84. if (o.m_data[0].left._mpfr_d)
  85. mpfi_set(m_data, o.m_data);
  86. }
  87. template <unsigned D, mpfr_allocation_type AllocationType>
  88. mpfi_float_imp(const mpfr_float_imp<D, AllocationType>& o)
  89. {
  90. mpfi_init2(m_data, (D == 0 ? preserve_component_precision() : preserve_related_precision()) ? mpfr_get_prec(o.data()) : boost::multiprecision::detail::digits10_2_2(get_default_precision()));
  91. if (o.data()[0]._mpfr_d)
  92. mpfi_set_fr(m_data, o.data());
  93. }
  94. // rvalue copy
  95. mpfi_float_imp(mpfi_float_imp&& o) noexcept
  96. {
  97. mpfr_prec_t binary_default_precision = boost::multiprecision::detail::digits10_2_2(get_default_precision());
  98. if ((this->get_default_options() != variable_precision_options::preserve_target_precision) || (mpfi_get_prec(o.data()) == binary_default_precision))
  99. {
  100. m_data[0] = o.m_data[0];
  101. o.m_data[0].left._mpfr_d = nullptr;
  102. }
  103. else
  104. {
  105. // NOTE: C allocation interface must not throw:
  106. mpfi_init2(m_data, binary_default_precision);
  107. mpfi_set(m_data, o.m_data);
  108. }
  109. }
  110. mpfi_float_imp& operator=(const mpfi_float_imp& o)
  111. {
  112. if (this != &o)
  113. {
  114. if (m_data[0].left._mpfr_d == nullptr)
  115. mpfi_init2(m_data, preserve_source_precision() ? mpfi_get_prec(o.m_data) : boost::multiprecision::detail::digits10_2_2(get_default_precision()));
  116. else if (preserve_source_precision() && (mpfi_get_prec(o.data()) != mpfi_get_prec(data())))
  117. {
  118. mpfi_set_prec(m_data, mpfi_get_prec(o.m_data));
  119. }
  120. mpfi_set(m_data, o.m_data);
  121. }
  122. return *this;
  123. }
  124. // rvalue assign
  125. mpfi_float_imp& operator=(mpfi_float_imp&& o) noexcept
  126. {
  127. if ((this->get_default_options() != variable_precision_options::preserve_target_precision) || (mpfi_get_prec(o.data()) == mpfi_get_prec(data())))
  128. mpfi_swap(m_data, o.m_data);
  129. else
  130. *this = static_cast<const mpfi_float_imp&>(o);
  131. return *this;
  132. }
  133. #ifdef BOOST_HAS_LONG_LONG
  134. #ifdef _MPFR_H_HAVE_INTMAX_T
  135. mpfi_float_imp& operator=(unsigned long long i)
  136. {
  137. if (m_data[0].left._mpfr_d == nullptr)
  138. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
  139. mpfr_set_uj(left_data(), i, GMP_RNDD);
  140. mpfr_set_uj(right_data(), i, GMP_RNDU);
  141. return *this;
  142. }
  143. mpfi_float_imp& operator=(long long i)
  144. {
  145. if (m_data[0].left._mpfr_d == nullptr)
  146. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
  147. mpfr_set_sj(left_data(), i, GMP_RNDD);
  148. mpfr_set_sj(right_data(), i, GMP_RNDU);
  149. return *this;
  150. }
  151. #else
  152. mpfi_float_imp& operator=(unsigned long long i)
  153. {
  154. if (m_data[0].left._mpfr_d == nullptr)
  155. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
  156. unsigned long long mask = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1u);
  157. unsigned shift = 0;
  158. mpfi_t t;
  159. mpfi_init2(t, (std::max)(static_cast<mpfr_prec_t>(std::numeric_limits<unsigned long long>::digits), static_cast<mpfr_prec_t>(multiprecision::detail::digits10_2_2(digits10))));
  160. mpfi_set_ui(m_data, 0);
  161. while (i)
  162. {
  163. mpfi_set_ui(t, static_cast<unsigned long>(i & mask));
  164. if (shift)
  165. mpfi_mul_2exp(t, t, shift);
  166. mpfi_add(m_data, m_data, t);
  167. shift += std::numeric_limits<unsigned long>::digits;
  168. i >>= std::numeric_limits<unsigned long>::digits;
  169. }
  170. mpfi_clear(t);
  171. return *this;
  172. }
  173. mpfi_float_imp& operator=(long long i)
  174. {
  175. if (m_data[0].left._mpfr_d == nullptr)
  176. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
  177. bool neg = i < 0;
  178. *this = boost::multiprecision::detail::unsigned_abs(i);
  179. if (neg)
  180. mpfi_neg(m_data, m_data);
  181. return *this;
  182. }
  183. #endif
  184. #endif
  185. #ifdef BOOST_HAS_INT128
  186. mpfi_float_imp& operator=(uint128_type i)
  187. {
  188. if (m_data[0].left._mpfr_d == nullptr)
  189. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
  190. constexpr uint128_type mask = ((((static_cast<uint128_type>(1u) << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1u);
  191. unsigned shift = 0;
  192. mpfi_t t;
  193. mpfi_init2(t, (std::max)(static_cast<mpfr_prec_t>(128), static_cast<mpfr_prec_t>(multiprecision::detail::digits10_2_2(digits10))));
  194. mpfi_set_ui(m_data, 0);
  195. while (i)
  196. {
  197. mpfi_set_ui(t, static_cast<unsigned long>(i & mask));
  198. if (shift)
  199. mpfi_mul_2exp(t, t, shift);
  200. mpfi_add(m_data, m_data, t);
  201. shift += std::numeric_limits<unsigned long>::digits;
  202. i >>= std::numeric_limits<unsigned long>::digits;
  203. }
  204. mpfi_clear(t);
  205. return *this;
  206. }
  207. mpfi_float_imp& operator=(int128_type i)
  208. {
  209. if (m_data[0].left._mpfr_d == nullptr)
  210. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
  211. bool neg = i < 0;
  212. *this = boost::multiprecision::detail::unsigned_abs(i);
  213. if (neg)
  214. mpfi_neg(m_data, m_data);
  215. return *this;
  216. }
  217. #endif
  218. mpfi_float_imp& operator=(unsigned long i)
  219. {
  220. if (m_data[0].left._mpfr_d == nullptr)
  221. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
  222. mpfi_set_ui(m_data, i);
  223. return *this;
  224. }
  225. mpfi_float_imp& operator=(long i)
  226. {
  227. if (m_data[0].left._mpfr_d == nullptr)
  228. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
  229. mpfi_set_si(m_data, i);
  230. return *this;
  231. }
  232. mpfi_float_imp& operator=(double d)
  233. {
  234. if (m_data[0].left._mpfr_d == nullptr)
  235. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
  236. mpfi_set_d(m_data, d);
  237. return *this;
  238. }
  239. mpfi_float_imp& operator=(long double a)
  240. {
  241. if (m_data[0].left._mpfr_d == nullptr)
  242. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
  243. mpfr_set_ld(left_data(), a, GMP_RNDD);
  244. mpfr_set_ld(right_data(), a, GMP_RNDU);
  245. return *this;
  246. }
  247. #ifdef BOOST_HAS_FLOAT128
  248. mpfi_float_imp& operator=(float128_type a)
  249. {
  250. BOOST_MP_FLOAT128_USING
  251. if (m_data[0].left._mpfr_d == nullptr)
  252. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
  253. if (a == 0)
  254. {
  255. mpfi_set_si(m_data, 0);
  256. return *this;
  257. }
  258. if (a == 1)
  259. {
  260. mpfi_set_si(m_data, 1);
  261. return *this;
  262. }
  263. BOOST_MP_ASSERT(!BOOST_MP_ISINF(a));
  264. BOOST_MP_ASSERT(!BOOST_MP_ISNAN(a));
  265. int e;
  266. float128_type f, term;
  267. mpfi_set_ui(m_data, 0u);
  268. f = frexp(a, &e);
  269. constexpr const int shift = std::numeric_limits<int>::digits - 1;
  270. while (f)
  271. {
  272. // extract int sized bits from f:
  273. f = ldexp(f, shift);
  274. term = floor(f);
  275. e -= shift;
  276. mpfi_mul_2exp(m_data, m_data, shift);
  277. if (term > 0)
  278. mpfi_add_ui(m_data, m_data, static_cast<unsigned>(term));
  279. else
  280. mpfi_sub_ui(m_data, m_data, static_cast<unsigned>(-term));
  281. f -= term;
  282. }
  283. if (e > 0)
  284. mpfi_mul_2exp(m_data, m_data, e);
  285. else if (e < 0)
  286. mpfi_div_2exp(m_data, m_data, -e);
  287. return *this;
  288. }
  289. #endif
  290. mpfi_float_imp& operator=(const char* s)
  291. {
  292. using default_ops::eval_fpclassify;
  293. if (m_data[0].left._mpfr_d == nullptr)
  294. mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
  295. if (s && (*s == '{'))
  296. {
  297. mpfr_float_backend<digits10> a, b;
  298. std::string part;
  299. const char* p = ++s;
  300. while (*p && (*p != ',') && (*p != '}'))
  301. ++p;
  302. part.assign(s, p);
  303. a = part.c_str();
  304. s = p;
  305. if (*p && (*p != '}'))
  306. {
  307. ++p;
  308. while (*p && (*p != ',') && (*p != '}'))
  309. ++p;
  310. part.assign(s + 1, p);
  311. }
  312. else
  313. part.erase();
  314. b = part.c_str();
  315. if (eval_fpclassify(a) == static_cast<int>(FP_NAN))
  316. {
  317. mpfi_set_fr(this->data(), a.data());
  318. }
  319. else if (eval_fpclassify(b) == static_cast<int>(FP_NAN))
  320. {
  321. mpfi_set_fr(this->data(), b.data());
  322. }
  323. else
  324. {
  325. if (a.compare(b) > 0)
  326. {
  327. BOOST_MP_THROW_EXCEPTION(std::runtime_error("Attempt to create interval with invalid range (start is greater than end)."));
  328. }
  329. mpfi_interv_fr(m_data, a.data(), b.data());
  330. }
  331. }
  332. else if (mpfi_set_str(m_data, s, 10) != 0)
  333. {
  334. BOOST_MP_THROW_EXCEPTION(std::runtime_error(std::string("Unable to parse string \"") + s + std::string("\"as a valid floating point number.")));
  335. }
  336. return *this;
  337. }
  338. void swap(mpfi_float_imp& o) noexcept
  339. {
  340. mpfi_swap(m_data, o.m_data);
  341. }
  342. std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
  343. {
  344. BOOST_MP_ASSERT(m_data[0].left._mpfr_d);
  345. mpfr_float_backend<digits10> a, b;
  346. mpfi_get_left(a.data(), m_data);
  347. mpfi_get_right(b.data(), m_data);
  348. if (a.compare(b) == 0)
  349. return a.str(digits, f);
  350. return "{" + a.str(digits, f) + "," + b.str(digits, f) + "}";
  351. }
  352. ~mpfi_float_imp() noexcept
  353. {
  354. if (m_data[0].left._mpfr_d)
  355. mpfi_clear(m_data);
  356. }
  357. void negate() noexcept
  358. {
  359. BOOST_MP_ASSERT(m_data[0].left._mpfr_d);
  360. mpfi_neg(m_data, m_data);
  361. }
  362. int compare(const mpfi_float_imp& o) const noexcept
  363. {
  364. BOOST_MP_ASSERT(m_data[0].left._mpfr_d && o.m_data[0].left._mpfr_d);
  365. if (mpfr_cmp(right_data(), o.left_data()) < 0)
  366. return -1;
  367. if (mpfr_cmp(left_data(), o.right_data()) > 0)
  368. return 1;
  369. if ((mpfr_cmp(left_data(), o.left_data()) == 0) && (mpfr_cmp(right_data(), o.right_data()) == 0))
  370. return 0;
  371. BOOST_MP_THROW_EXCEPTION(interval_error("Ambiguous comparison between two values."));
  372. return 0;
  373. }
  374. template <class V>
  375. int compare(V v) const noexcept
  376. {
  377. mpfi_float_imp d;
  378. d = v;
  379. return compare(d);
  380. }
  381. mpfi_t& data() noexcept
  382. {
  383. BOOST_MP_ASSERT(m_data[0].left._mpfr_d);
  384. return m_data;
  385. }
  386. const mpfi_t& data() const noexcept
  387. {
  388. BOOST_MP_ASSERT(m_data[0].left._mpfr_d);
  389. return m_data;
  390. }
  391. mpfr_ptr left_data() noexcept
  392. {
  393. BOOST_MP_ASSERT(m_data[0].left._mpfr_d);
  394. return &(m_data[0].left);
  395. }
  396. mpfr_srcptr left_data() const noexcept
  397. {
  398. BOOST_MP_ASSERT(m_data[0].left._mpfr_d);
  399. return &(m_data[0].left);
  400. }
  401. mpfr_ptr right_data() noexcept
  402. {
  403. BOOST_MP_ASSERT(m_data[0].left._mpfr_d);
  404. return &(m_data[0].right);
  405. }
  406. mpfr_srcptr right_data() const noexcept
  407. {
  408. BOOST_MP_ASSERT(m_data[0].left._mpfr_d);
  409. return &(m_data[0].right);
  410. }
  411. protected:
  412. mpfi_t m_data;
  413. static boost::multiprecision::detail::precision_type& get_global_default_precision() noexcept
  414. {
  415. static boost::multiprecision::detail::precision_type val(BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION);
  416. return val;
  417. }
  418. static unsigned& get_default_precision() noexcept
  419. {
  420. static BOOST_MP_THREAD_LOCAL unsigned val(get_global_default_precision());
  421. return val;
  422. }
  423. #ifndef BOOST_MT_NO_ATOMIC_INT
  424. static std::atomic<variable_precision_options>& get_global_default_options() noexcept
  425. #else
  426. static variable_precision_options& get_global_default_options() noexcept
  427. #endif
  428. {
  429. #ifndef BOOST_MT_NO_ATOMIC_INT
  430. static std::atomic<variable_precision_options> val{variable_precision_options::preserve_related_precision};
  431. #else
  432. static variable_precision_optionss val{variable_precision_options::preserve_related_precision};
  433. #endif
  434. return val;
  435. }
  436. static variable_precision_options& get_default_options() noexcept
  437. {
  438. static BOOST_MP_THREAD_LOCAL variable_precision_options val(get_global_default_options());
  439. return val;
  440. }
  441. static bool preserve_source_precision() noexcept
  442. {
  443. return get_default_options() >= variable_precision_options::preserve_source_precision;
  444. }
  445. static bool preserve_component_precision() noexcept
  446. {
  447. return get_default_options() >= variable_precision_options::preserve_component_precision;
  448. }
  449. static bool preserve_related_precision() noexcept
  450. {
  451. return get_default_options() >= variable_precision_options::preserve_related_precision;
  452. }
  453. static bool preserve_all_precision() noexcept
  454. {
  455. return get_default_options() >= variable_precision_options::preserve_all_precision;
  456. }
  457. };
  458. } // namespace detail
  459. template <unsigned digits10>
  460. struct mpfi_float_backend : public detail::mpfi_float_imp<digits10>
  461. {
  462. mpfi_float_backend() : detail::mpfi_float_imp<digits10>() {}
  463. mpfi_float_backend(const mpfi_float_backend& o) : detail::mpfi_float_imp<digits10>(o) {}
  464. // rvalue copy
  465. mpfi_float_backend(mpfi_float_backend&& o) : detail::mpfi_float_imp<digits10>(static_cast<detail::mpfi_float_imp<digits10>&&>(o))
  466. {}
  467. template <unsigned D>
  468. mpfi_float_backend(const mpfi_float_backend<D>& val, typename std::enable_if<D <= digits10>::type* = nullptr)
  469. : detail::mpfi_float_imp<digits10>()
  470. {
  471. mpfi_set(this->m_data, val.data());
  472. }
  473. template <unsigned D, mpfr_allocation_type AllocationType>
  474. mpfi_float_backend(const mpfr_float_backend<D, AllocationType>& val, typename std::enable_if<D <= digits10>::type* = nullptr)
  475. : detail::mpfi_float_imp<digits10>(val) {}
  476. template <unsigned D>
  477. explicit mpfi_float_backend(const mpfi_float_backend<D>& val, typename std::enable_if<!(D <= digits10)>::type* = nullptr)
  478. : detail::mpfi_float_imp<digits10>()
  479. {
  480. mpfi_set(this->m_data, val.data());
  481. }
  482. mpfi_float_backend(const mpfi_t val)
  483. : detail::mpfi_float_imp<digits10>()
  484. {
  485. mpfi_set(this->m_data, val);
  486. }
  487. mpfi_float_backend& operator=(const mpfi_float_backend& o)
  488. {
  489. *static_cast<detail::mpfi_float_imp<digits10>*>(this) = static_cast<detail::mpfi_float_imp<digits10> const&>(o);
  490. return *this;
  491. }
  492. template <unsigned D>
  493. mpfi_float_backend(const mpfr_float_backend<D>& val, typename std::enable_if<D <= digits10>::type* = nullptr)
  494. : detail::mpfi_float_imp<digits10>()
  495. {
  496. mpfi_set_fr(this->m_data, val.data());
  497. }
  498. template <unsigned D>
  499. mpfi_float_backend& operator=(const mpfr_float_backend<D>& val)
  500. {
  501. mpfi_set_fr(this->m_data, val.data());
  502. return *this;
  503. }
  504. template <unsigned D>
  505. explicit mpfi_float_backend(const mpfr_float_backend<D>& val, typename std::enable_if<!(D <= digits10)>::type* = nullptr)
  506. : detail::mpfi_float_imp<digits10>()
  507. {
  508. mpfi_set_fr(this->m_data, val.data());
  509. }
  510. // rvalue copy
  511. mpfi_float_backend& operator=(mpfi_float_backend&& o) noexcept
  512. {
  513. *static_cast<detail::mpfi_float_imp<digits10>*>(this) = static_cast<detail::mpfi_float_imp<digits10>&&>(o);
  514. return *this;
  515. }
  516. template <class V>
  517. typename std::enable_if<std::is_assignable<detail::mpfi_float_imp<digits10>, V>::value, mpfi_float_backend&>::type operator=(const V& v)
  518. {
  519. *static_cast<detail::mpfi_float_imp<digits10>*>(this) = v;
  520. return *this;
  521. }
  522. mpfi_float_backend& operator=(const mpfi_t val)
  523. {
  524. mpfi_set(this->m_data, val);
  525. return *this;
  526. }
  527. // We don't change our precision here, this is a fixed precision type:
  528. template <unsigned D>
  529. mpfi_float_backend& operator=(const mpfi_float_backend<D>& val)
  530. {
  531. mpfi_set(this->m_data, val.data());
  532. return *this;
  533. }
  534. };
  535. template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType>
  536. void assign_components(mpfi_float_backend<D1>& result, const mpfr_float_backend<D2, AllocationType>& a, const mpfr_float_backend<D2, AllocationType>& b);
  537. template <unsigned Digits10, class V>
  538. typename std::enable_if<std::is_constructible<number<mpfr_float_backend<Digits10, allocate_dynamic>, et_on>, V>::value || std::is_convertible<V, const char*>::value>::type
  539. assign_components(mpfi_float_backend<Digits10>& result, const V& a, const V& b);
  540. template <>
  541. struct mpfi_float_backend<0> : public detail::mpfi_float_imp<0>
  542. {
  543. mpfi_float_backend() : detail::mpfi_float_imp<0>() {}
  544. mpfi_float_backend(const mpfi_t val)
  545. : detail::mpfi_float_imp<0>(mpfi_get_prec(val))
  546. {
  547. mpfi_set(this->m_data, val);
  548. }
  549. mpfi_float_backend(const mpfi_float_backend& o) : detail::mpfi_float_imp<0>(o) {}
  550. template <unsigned D, mpfr_allocation_type AllocationType>
  551. mpfi_float_backend(const mpfr_float_backend<D, AllocationType>& val)
  552. : detail::mpfi_float_imp<0>(val) {}
  553. // rvalue copy
  554. mpfi_float_backend(mpfi_float_backend&& o) noexcept : detail::mpfi_float_imp<0>(static_cast<detail::mpfi_float_imp<0>&&>(o))
  555. {}
  556. mpfi_float_backend(const mpfi_float_backend& o, unsigned digits10)
  557. : detail::mpfi_float_imp<0>(multiprecision::detail::digits10_2_2(digits10))
  558. {
  559. mpfi_set(this->m_data, o.data());
  560. }
  561. template <class V>
  562. mpfi_float_backend(const V& a, const V& b, unsigned digits10)
  563. : detail::mpfi_float_imp<0>(multiprecision::detail::digits10_2_2(digits10))
  564. {
  565. boost::multiprecision::detail::scoped_target_precision<mpfi_float_backend<0> > opts;
  566. assign_components(*this, a, b);
  567. }
  568. template <unsigned D>
  569. mpfi_float_backend(const mpfi_float_backend<D>& val)
  570. : detail::mpfi_float_imp<0>(mpfi_get_prec(val.data()))
  571. {
  572. mpfi_set(this->m_data, val.data());
  573. }
  574. mpfi_float_backend& operator=(const mpfi_float_backend& o) = default;
  575. // rvalue assign
  576. mpfi_float_backend& operator=(mpfi_float_backend&& o) noexcept = default;
  577. template <class V>
  578. mpfi_float_backend& operator=(const V& v)
  579. {
  580. constexpr unsigned d10 = std::is_floating_point<V>::value ?
  581. std::numeric_limits<V>::digits10 :
  582. std::numeric_limits<V>::digits10 ? 1 + std::numeric_limits<V>::digits10 :
  583. 1 + boost::multiprecision::detail::digits2_2_10(std::numeric_limits<V>::digits);
  584. if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
  585. {
  586. BOOST_IF_CONSTEXPR(std::is_floating_point<V>::value)
  587. {
  588. if (std::numeric_limits<V>::digits > mpfi_get_prec(this->data()))
  589. mpfi_set_prec(this->data(), std::numeric_limits<V>::digits);
  590. }
  591. else
  592. {
  593. if (precision() < d10)
  594. this->precision(d10);
  595. }
  596. }
  597. *static_cast<detail::mpfi_float_imp<0>*>(this) = v;
  598. return *this;
  599. }
  600. mpfi_float_backend& operator=(const mpfi_t val)
  601. {
  602. mpfi_set_prec(this->m_data, mpfi_get_prec(val));
  603. mpfi_set(this->m_data, val);
  604. return *this;
  605. }
  606. template <unsigned D>
  607. mpfi_float_backend& operator=(const mpfi_float_backend<D>& val)
  608. {
  609. mpfi_set_prec(this->m_data, mpfi_get_prec(val.data()));
  610. mpfi_set(this->m_data, val.data());
  611. return *this;
  612. }
  613. static unsigned thread_default_precision() noexcept
  614. {
  615. return get_default_precision();
  616. }
  617. static void thread_default_precision(unsigned v) noexcept
  618. {
  619. get_default_precision() = v;
  620. }
  621. static unsigned default_precision() noexcept
  622. {
  623. return get_global_default_precision();
  624. }
  625. static void default_precision(unsigned v) noexcept
  626. {
  627. get_global_default_precision() = v;
  628. }
  629. unsigned precision() const noexcept
  630. {
  631. return multiprecision::detail::digits2_2_10(mpfi_get_prec(this->m_data));
  632. }
  633. void precision(unsigned digits10) noexcept
  634. {
  635. mpfi_float_backend t(*this, digits10);
  636. this->swap(t);
  637. }
  638. //
  639. // Variable precision options:
  640. //
  641. static variable_precision_options default_variable_precision_options() noexcept
  642. {
  643. return get_global_default_options();
  644. }
  645. static variable_precision_options thread_default_variable_precision_options() noexcept
  646. {
  647. return get_default_options();
  648. }
  649. static void default_variable_precision_options(variable_precision_options opts)
  650. {
  651. get_global_default_options() = opts;
  652. }
  653. static void thread_default_variable_precision_options(variable_precision_options opts)
  654. {
  655. get_default_options() = opts;
  656. }
  657. };
  658. template <unsigned digits10, class T>
  659. inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_eq(const mpfi_float_backend<digits10>& a, const T& b) noexcept
  660. {
  661. return a.compare(b) == 0;
  662. }
  663. template <unsigned digits10, class T>
  664. inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_lt(const mpfi_float_backend<digits10>& a, const T& b) noexcept
  665. {
  666. return a.compare(b) < 0;
  667. }
  668. template <unsigned digits10, class T>
  669. inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_gt(const mpfi_float_backend<digits10>& a, const T& b) noexcept
  670. {
  671. return a.compare(b) > 0;
  672. }
  673. template <unsigned D1, unsigned D2>
  674. inline void eval_add(mpfi_float_backend<D1>& result, const mpfi_float_backend<D2>& o)
  675. {
  676. mpfi_add(result.data(), result.data(), o.data());
  677. }
  678. template <unsigned D1, unsigned D2>
  679. inline void eval_subtract(mpfi_float_backend<D1>& result, const mpfi_float_backend<D2>& o)
  680. {
  681. mpfi_sub(result.data(), result.data(), o.data());
  682. }
  683. template <unsigned D1, unsigned D2>
  684. inline void eval_multiply(mpfi_float_backend<D1>& result, const mpfi_float_backend<D2>& o)
  685. {
  686. if ((void*)&result == (void*)&o)
  687. mpfi_sqr(result.data(), o.data());
  688. else
  689. mpfi_mul(result.data(), result.data(), o.data());
  690. }
  691. template <unsigned D1, unsigned D2>
  692. inline void eval_divide(mpfi_float_backend<D1>& result, const mpfi_float_backend<D2>& o)
  693. {
  694. mpfi_div(result.data(), result.data(), o.data());
  695. }
  696. template <unsigned digits10>
  697. inline void eval_add(mpfi_float_backend<digits10>& result, unsigned long i)
  698. {
  699. mpfi_add_ui(result.data(), result.data(), i);
  700. }
  701. template <unsigned digits10>
  702. inline void eval_subtract(mpfi_float_backend<digits10>& result, unsigned long i)
  703. {
  704. mpfi_sub_ui(result.data(), result.data(), i);
  705. }
  706. template <unsigned digits10>
  707. inline void eval_multiply(mpfi_float_backend<digits10>& result, unsigned long i)
  708. {
  709. mpfi_mul_ui(result.data(), result.data(), i);
  710. }
  711. template <unsigned digits10>
  712. inline void eval_divide(mpfi_float_backend<digits10>& result, unsigned long i)
  713. {
  714. mpfi_div_ui(result.data(), result.data(), i);
  715. }
  716. template <unsigned digits10>
  717. inline void eval_add(mpfi_float_backend<digits10>& result, long i)
  718. {
  719. if (i > 0)
  720. mpfi_add_ui(result.data(), result.data(), i);
  721. else
  722. mpfi_sub_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
  723. }
  724. template <unsigned digits10>
  725. inline void eval_subtract(mpfi_float_backend<digits10>& result, long i)
  726. {
  727. if (i > 0)
  728. mpfi_sub_ui(result.data(), result.data(), i);
  729. else
  730. mpfi_add_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
  731. }
  732. template <unsigned digits10>
  733. inline void eval_multiply(mpfi_float_backend<digits10>& result, long i)
  734. {
  735. mpfi_mul_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
  736. if (i < 0)
  737. mpfi_neg(result.data(), result.data());
  738. }
  739. template <unsigned digits10>
  740. inline void eval_divide(mpfi_float_backend<digits10>& result, long i)
  741. {
  742. mpfi_div_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
  743. if (i < 0)
  744. mpfi_neg(result.data(), result.data());
  745. }
  746. //
  747. // Specialised 3 arg versions of the basic operators:
  748. //
  749. template <unsigned D1, unsigned D2, unsigned D3>
  750. inline void eval_add(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, const mpfi_float_backend<D3>& y)
  751. {
  752. mpfi_add(a.data(), x.data(), y.data());
  753. }
  754. template <unsigned D1, unsigned D2>
  755. inline void eval_add(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, unsigned long y)
  756. {
  757. mpfi_add_ui(a.data(), x.data(), y);
  758. }
  759. template <unsigned D1, unsigned D2>
  760. inline void eval_add(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, long y)
  761. {
  762. if (y < 0)
  763. mpfi_sub_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
  764. else
  765. mpfi_add_ui(a.data(), x.data(), y);
  766. }
  767. template <unsigned D1, unsigned D2>
  768. inline void eval_add(mpfi_float_backend<D1>& a, unsigned long x, const mpfi_float_backend<D2>& y)
  769. {
  770. mpfi_add_ui(a.data(), y.data(), x);
  771. }
  772. template <unsigned D1, unsigned D2>
  773. inline void eval_add(mpfi_float_backend<D1>& a, long x, const mpfi_float_backend<D2>& y)
  774. {
  775. if (x < 0)
  776. {
  777. mpfi_ui_sub(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data());
  778. mpfi_neg(a.data(), a.data());
  779. }
  780. else
  781. mpfi_add_ui(a.data(), y.data(), x);
  782. }
  783. template <unsigned D1, unsigned D2, unsigned D3>
  784. inline void eval_subtract(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, const mpfi_float_backend<D3>& y)
  785. {
  786. mpfi_sub(a.data(), x.data(), y.data());
  787. }
  788. template <unsigned D1, unsigned D2>
  789. inline void eval_subtract(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, unsigned long y)
  790. {
  791. mpfi_sub_ui(a.data(), x.data(), y);
  792. }
  793. template <unsigned D1, unsigned D2>
  794. inline void eval_subtract(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, long y)
  795. {
  796. if (y < 0)
  797. mpfi_add_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
  798. else
  799. mpfi_sub_ui(a.data(), x.data(), y);
  800. }
  801. template <unsigned D1, unsigned D2>
  802. inline void eval_subtract(mpfi_float_backend<D1>& a, unsigned long x, const mpfi_float_backend<D2>& y)
  803. {
  804. mpfi_ui_sub(a.data(), x, y.data());
  805. }
  806. template <unsigned D1, unsigned D2>
  807. inline void eval_subtract(mpfi_float_backend<D1>& a, long x, const mpfi_float_backend<D2>& y)
  808. {
  809. if (x < 0)
  810. {
  811. mpfi_add_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x));
  812. mpfi_neg(a.data(), a.data());
  813. }
  814. else
  815. mpfi_ui_sub(a.data(), x, y.data());
  816. }
  817. template <unsigned D1, unsigned D2, unsigned D3>
  818. inline void eval_multiply(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, const mpfi_float_backend<D3>& y)
  819. {
  820. if ((void*)&x == (void*)&y)
  821. mpfi_sqr(a.data(), x.data());
  822. else
  823. mpfi_mul(a.data(), x.data(), y.data());
  824. }
  825. template <unsigned D1, unsigned D2>
  826. inline void eval_multiply(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, unsigned long y)
  827. {
  828. mpfi_mul_ui(a.data(), x.data(), y);
  829. }
  830. template <unsigned D1, unsigned D2>
  831. inline void eval_multiply(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, long y)
  832. {
  833. if (y < 0)
  834. {
  835. mpfi_mul_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
  836. a.negate();
  837. }
  838. else
  839. mpfi_mul_ui(a.data(), x.data(), y);
  840. }
  841. template <unsigned D1, unsigned D2>
  842. inline void eval_multiply(mpfi_float_backend<D1>& a, unsigned long x, const mpfi_float_backend<D2>& y)
  843. {
  844. mpfi_mul_ui(a.data(), y.data(), x);
  845. }
  846. template <unsigned D1, unsigned D2>
  847. inline void eval_multiply(mpfi_float_backend<D1>& a, long x, const mpfi_float_backend<D2>& y)
  848. {
  849. if (x < 0)
  850. {
  851. mpfi_mul_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x));
  852. mpfi_neg(a.data(), a.data());
  853. }
  854. else
  855. mpfi_mul_ui(a.data(), y.data(), x);
  856. }
  857. template <unsigned D1, unsigned D2, unsigned D3>
  858. inline void eval_divide(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, const mpfi_float_backend<D3>& y)
  859. {
  860. mpfi_div(a.data(), x.data(), y.data());
  861. }
  862. template <unsigned D1, unsigned D2>
  863. inline void eval_divide(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, unsigned long y)
  864. {
  865. mpfi_div_ui(a.data(), x.data(), y);
  866. }
  867. template <unsigned D1, unsigned D2>
  868. inline void eval_divide(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, long y)
  869. {
  870. if (y < 0)
  871. {
  872. mpfi_div_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
  873. a.negate();
  874. }
  875. else
  876. mpfi_div_ui(a.data(), x.data(), y);
  877. }
  878. template <unsigned D1, unsigned D2>
  879. inline void eval_divide(mpfi_float_backend<D1>& a, unsigned long x, const mpfi_float_backend<D2>& y)
  880. {
  881. mpfi_ui_div(a.data(), x, y.data());
  882. }
  883. template <unsigned D1, unsigned D2>
  884. inline void eval_divide(mpfi_float_backend<D1>& a, long x, const mpfi_float_backend<D2>& y)
  885. {
  886. if (x < 0)
  887. {
  888. mpfi_ui_div(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data());
  889. mpfi_neg(a.data(), a.data());
  890. }
  891. else
  892. mpfi_ui_div(a.data(), x, y.data());
  893. }
  894. template <unsigned digits10>
  895. inline bool eval_is_zero(const mpfi_float_backend<digits10>& val) noexcept
  896. {
  897. return 0 != mpfi_is_zero(val.data());
  898. }
  899. template <unsigned digits10>
  900. inline int eval_get_sign(const mpfi_float_backend<digits10>& val)
  901. {
  902. return detail::mpfi_sgn(val.data());
  903. }
  904. template <unsigned digits10>
  905. inline void eval_convert_to(unsigned long* result, const mpfi_float_backend<digits10>& val)
  906. {
  907. mpfr_float_backend<digits10> t;
  908. mpfi_mid(t.data(), val.data());
  909. eval_convert_to(result, t);
  910. }
  911. template <unsigned digits10>
  912. inline void eval_convert_to(long* result, const mpfi_float_backend<digits10>& val)
  913. {
  914. mpfr_float_backend<digits10> t;
  915. mpfi_mid(t.data(), val.data());
  916. eval_convert_to(result, t);
  917. }
  918. #ifdef _MPFR_H_HAVE_INTMAX_T
  919. template <unsigned digits10>
  920. inline void eval_convert_to(unsigned long long* result, const mpfi_float_backend<digits10>& val)
  921. {
  922. mpfr_float_backend<digits10> t;
  923. mpfi_mid(t.data(), val.data());
  924. eval_convert_to(result, t);
  925. }
  926. template <unsigned digits10>
  927. inline void eval_convert_to(long long* result, const mpfi_float_backend<digits10>& val)
  928. {
  929. mpfr_float_backend<digits10> t;
  930. mpfi_mid(t.data(), val.data());
  931. eval_convert_to(result, t);
  932. }
  933. #endif
  934. #ifdef BOOST_HAS_INT128
  935. template <unsigned digits10>
  936. inline void eval_convert_to(uint128_type* result, const mpfi_float_backend<digits10>& val)
  937. {
  938. mpfr_float_backend<digits10> t;
  939. mpfi_mid(t.data(), val.data());
  940. eval_convert_to(result, t);
  941. }
  942. template <unsigned digits10>
  943. inline void eval_convert_to(int128_type* result, const mpfi_float_backend<digits10>& val)
  944. {
  945. mpfr_float_backend<digits10> t;
  946. mpfi_mid(t.data(), val.data());
  947. eval_convert_to(result, t);
  948. }
  949. #endif
  950. template <unsigned digits10>
  951. inline void eval_convert_to(double* result, const mpfi_float_backend<digits10>& val) noexcept
  952. {
  953. *result = mpfi_get_d(val.data());
  954. }
  955. template <unsigned digits10>
  956. inline void eval_convert_to(long double* result, const mpfi_float_backend<digits10>& val) noexcept
  957. {
  958. mpfr_float_backend<digits10> t;
  959. mpfi_mid(t.data(), val.data());
  960. eval_convert_to(result, t);
  961. }
  962. #ifdef BOOST_HAS_FLOAT128
  963. template <unsigned digits10>
  964. inline void eval_convert_to(float128_type* result, const mpfi_float_backend<digits10>& val)
  965. {
  966. mpfr_float_backend<digits10> t;
  967. mpfi_mid(t.data(), val.data());
  968. eval_convert_to(result, t);
  969. }
  970. #endif
  971. template <mpfr_allocation_type AllocationType>
  972. inline void assign_components_set_precision(mpfi_float_backend<0>& result, const mpfr_float_backend<0, AllocationType>& a, const mpfr_float_backend<0, AllocationType>& b)
  973. {
  974. if (result.thread_default_variable_precision_options() >= variable_precision_options::preserve_component_precision)
  975. {
  976. unsigned long prec = (std::max)(mpfr_get_prec(a.data()), mpfr_get_prec(b.data()));
  977. mpfi_set_prec(result.data(), prec);
  978. }
  979. }
  980. template <unsigned D2, mpfr_allocation_type AllocationType>
  981. inline void assign_components_set_precision(mpfi_float_backend<0>& result, const mpfr_float_backend<D2, AllocationType>& a, const mpfr_float_backend<D2, AllocationType>& b)
  982. {
  983. if (result.thread_default_variable_precision_options() >= variable_precision_options::preserve_related_precision)
  984. {
  985. unsigned long prec = (std::max)(mpfr_get_prec(a.data()), mpfr_get_prec(b.data()));
  986. mpfi_set_prec(result.data(), prec);
  987. }
  988. }
  989. template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType>
  990. inline void assign_components_set_precision(mpfi_float_backend<D1>&, const mpfr_float_backend<D2, AllocationType>&, const mpfr_float_backend<D2, AllocationType>&)
  991. {
  992. }
  993. template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType>
  994. inline void assign_components(mpfi_float_backend<D1>& result, const mpfr_float_backend<D2, AllocationType>& a, const mpfr_float_backend<D2, AllocationType>& b)
  995. {
  996. //
  997. // This is called from class number's constructors, so if we have variable
  998. // precision, then copy the precision of the source variables.
  999. //
  1000. assign_components_set_precision(result, a, b);
  1001. using default_ops::eval_fpclassify;
  1002. if (eval_fpclassify(a) == static_cast<int>(FP_NAN))
  1003. {
  1004. mpfi_set_fr(result.data(), a.data());
  1005. }
  1006. else if (eval_fpclassify(b) == static_cast<int>(FP_NAN))
  1007. {
  1008. mpfi_set_fr(result.data(), b.data());
  1009. }
  1010. else
  1011. {
  1012. if (a.compare(b) > 0)
  1013. {
  1014. BOOST_MP_THROW_EXCEPTION(std::runtime_error("Attempt to create interval with invalid range (start is greater than end)."));
  1015. }
  1016. mpfi_interv_fr(result.data(), a.data(), b.data());
  1017. }
  1018. }
  1019. template <unsigned Digits10, class V>
  1020. inline typename std::enable_if<std::is_constructible<number<mpfr_float_backend<Digits10, allocate_dynamic>, et_on>, V>::value || std::is_convertible<V, const char*>::value>::type
  1021. assign_components(mpfi_float_backend<Digits10>& result, const V& a, const V& b)
  1022. {
  1023. number<mpfr_float_backend<Digits10, allocate_dynamic>, et_on> x(a), y(b);
  1024. assign_components(result, x.backend(), y.backend());
  1025. }
  1026. //
  1027. // Native non-member operations:
  1028. //
  1029. template <unsigned Digits10>
  1030. inline void eval_sqrt(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val)
  1031. {
  1032. mpfi_sqrt(result.data(), val.data());
  1033. }
  1034. template <unsigned Digits10>
  1035. inline void eval_abs(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val)
  1036. {
  1037. mpfi_abs(result.data(), val.data());
  1038. }
  1039. template <unsigned Digits10>
  1040. inline void eval_fabs(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val)
  1041. {
  1042. mpfi_abs(result.data(), val.data());
  1043. }
  1044. template <unsigned Digits10>
  1045. inline void eval_ceil(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val)
  1046. {
  1047. mpfr_float_backend<Digits10> a, b;
  1048. mpfr_set(a.data(), val.left_data(), GMP_RNDN);
  1049. mpfr_set(b.data(), val.right_data(), GMP_RNDN);
  1050. eval_ceil(a, a);
  1051. eval_ceil(b, b);
  1052. if (a.compare(b) != 0)
  1053. {
  1054. BOOST_MP_THROW_EXCEPTION(interval_error("Attempt to take the ceil of a value that straddles an integer boundary."));
  1055. }
  1056. mpfi_set_fr(result.data(), a.data());
  1057. }
  1058. template <unsigned Digits10>
  1059. inline void eval_floor(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val)
  1060. {
  1061. mpfr_float_backend<Digits10> a, b;
  1062. mpfr_set(a.data(), val.left_data(), GMP_RNDN);
  1063. mpfr_set(b.data(), val.right_data(), GMP_RNDN);
  1064. eval_floor(a, a);
  1065. eval_floor(b, b);
  1066. if (a.compare(b) != 0)
  1067. {
  1068. BOOST_MP_THROW_EXCEPTION(interval_error("Attempt to take the floor of a value that straddles an integer boundary."));
  1069. }
  1070. mpfi_set_fr(result.data(), a.data());
  1071. }
  1072. template <unsigned Digits10>
  1073. inline void eval_ldexp(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val, long e)
  1074. {
  1075. if (e > 0)
  1076. mpfi_mul_2exp(result.data(), val.data(), e);
  1077. else if (e < 0)
  1078. mpfi_div_2exp(result.data(), val.data(), -e);
  1079. else
  1080. result = val;
  1081. }
  1082. template <unsigned Digits10>
  1083. inline void eval_frexp(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val, int* e)
  1084. {
  1085. mpfr_float_backend<Digits10> t, rt;
  1086. mpfi_mid(t.data(), val.data());
  1087. eval_frexp(rt, t, e);
  1088. eval_ldexp(result, val, -*e);
  1089. }
  1090. template <unsigned Digits10>
  1091. inline void eval_frexp(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val, long* e)
  1092. {
  1093. mpfr_float_backend<Digits10> t, rt;
  1094. mpfi_mid(t.data(), val.data());
  1095. eval_frexp(rt, t, e);
  1096. eval_ldexp(result, val, -*e);
  1097. }
  1098. template <unsigned Digits10>
  1099. inline int eval_fpclassify(const mpfi_float_backend<Digits10>& val) noexcept
  1100. {
  1101. return mpfi_inf_p(val.data()) ? FP_INFINITE : mpfi_nan_p(val.data()) ? FP_NAN : mpfi_is_zero(val.data()) ? FP_ZERO : FP_NORMAL;
  1102. }
  1103. template <unsigned Digits10>
  1104. inline void eval_pow(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& b, const mpfi_float_backend<Digits10>& e)
  1105. {
  1106. using ui_type = typename boost::multiprecision::detail::canonical<unsigned, mpfi_float_backend<Digits10> >::type;
  1107. using default_ops::eval_get_sign;
  1108. int s = eval_get_sign(b);
  1109. if (s == 0)
  1110. {
  1111. if (eval_get_sign(e) == 0)
  1112. {
  1113. result = ui_type(1);
  1114. }
  1115. else
  1116. {
  1117. result = ui_type(0);
  1118. }
  1119. return;
  1120. }
  1121. if (s < 0)
  1122. {
  1123. if (eval_get_sign(e) < 0)
  1124. {
  1125. mpfi_float_backend<Digits10> t1, t2;
  1126. t1 = e;
  1127. t1.negate();
  1128. eval_pow(t2, b, t1);
  1129. t1 = ui_type(1);
  1130. eval_divide(result, t1, t2);
  1131. return;
  1132. }
  1133. typename boost::multiprecision::detail::canonical<std::uintmax_t, mpfi_float_backend<Digits10> >::type an;
  1134. #ifndef BOOST_NO_EXCEPTIONS
  1135. try
  1136. {
  1137. #endif
  1138. using default_ops::eval_convert_to;
  1139. eval_convert_to(&an, e);
  1140. if (e.compare(an) == 0)
  1141. {
  1142. mpfi_float_backend<Digits10> pb(b);
  1143. pb.negate();
  1144. eval_pow(result, pb, e);
  1145. if (an & 1u)
  1146. result.negate();
  1147. return;
  1148. }
  1149. #ifndef BOOST_NO_EXCEPTIONS
  1150. }
  1151. catch (const std::exception&)
  1152. {
  1153. // conversion failed, just fall through, value is not an integer.
  1154. }
  1155. #endif
  1156. result = std::numeric_limits<number<mpfi_float_backend<Digits10>, et_on> >::quiet_NaN().backend();
  1157. return;
  1158. }
  1159. mpfi_log(result.data(), b.data());
  1160. mpfi_mul(result.data(), result.data(), e.data());
  1161. mpfi_exp(result.data(), result.data());
  1162. }
  1163. template <unsigned Digits10>
  1164. inline void eval_exp(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  1165. {
  1166. mpfi_exp(result.data(), arg.data());
  1167. }
  1168. template <unsigned Digits10>
  1169. inline void eval_exp2(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  1170. {
  1171. mpfi_exp2(result.data(), arg.data());
  1172. }
  1173. template <unsigned Digits10>
  1174. inline void eval_log(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  1175. {
  1176. mpfi_log(result.data(), arg.data());
  1177. }
  1178. template <unsigned Digits10>
  1179. inline void eval_log10(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  1180. {
  1181. mpfi_log10(result.data(), arg.data());
  1182. }
  1183. template <unsigned Digits10>
  1184. inline void eval_sin(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  1185. {
  1186. mpfi_sin(result.data(), arg.data());
  1187. }
  1188. template <unsigned Digits10>
  1189. inline void eval_cos(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  1190. {
  1191. mpfi_cos(result.data(), arg.data());
  1192. }
  1193. template <unsigned Digits10>
  1194. inline void eval_tan(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  1195. {
  1196. mpfi_tan(result.data(), arg.data());
  1197. }
  1198. template <unsigned Digits10>
  1199. inline void eval_asin(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  1200. {
  1201. mpfi_asin(result.data(), arg.data());
  1202. }
  1203. template <unsigned Digits10>
  1204. inline void eval_acos(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  1205. {
  1206. mpfi_acos(result.data(), arg.data());
  1207. }
  1208. template <unsigned Digits10>
  1209. inline void eval_atan(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  1210. {
  1211. mpfi_atan(result.data(), arg.data());
  1212. }
  1213. template <unsigned Digits10>
  1214. inline void eval_atan2(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg1, const mpfi_float_backend<Digits10>& arg2)
  1215. {
  1216. mpfi_atan2(result.data(), arg1.data(), arg2.data());
  1217. }
  1218. template <unsigned Digits10>
  1219. inline void eval_sinh(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  1220. {
  1221. mpfi_sinh(result.data(), arg.data());
  1222. }
  1223. template <unsigned Digits10>
  1224. inline void eval_cosh(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  1225. {
  1226. mpfi_cosh(result.data(), arg.data());
  1227. }
  1228. template <unsigned Digits10>
  1229. inline void eval_tanh(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  1230. {
  1231. mpfi_tanh(result.data(), arg.data());
  1232. }
  1233. template <unsigned Digits10>
  1234. inline void eval_log2(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
  1235. {
  1236. mpfi_log2(result.data(), arg.data());
  1237. }
  1238. template <unsigned Digits10>
  1239. inline std::size_t hash_value(const mpfi_float_backend<Digits10>& val)
  1240. {
  1241. std::size_t result = 0;
  1242. std::size_t len = val.left_data()[0]._mpfr_prec / mp_bits_per_limb;
  1243. if (val.left_data()[0]._mpfr_prec % mp_bits_per_limb)
  1244. ++len;
  1245. for (std::size_t i = 0; i < len; ++i)
  1246. boost::multiprecision::detail::hash_combine(result, val.left_data()[0]._mpfr_d[i]);
  1247. boost::multiprecision::detail::hash_combine(result, val.left_data()[0]._mpfr_exp, val.left_data()[0]._mpfr_sign);
  1248. len = val.right_data()[0]._mpfr_prec / mp_bits_per_limb;
  1249. if (val.right_data()[0]._mpfr_prec % mp_bits_per_limb)
  1250. ++len;
  1251. for (std::size_t i = 0; i < len; ++i)
  1252. boost::multiprecision::detail::hash_combine(result, val.right_data()[0]._mpfr_d[i]);
  1253. boost::multiprecision::detail::hash_combine(result, val.right_data()[0]._mpfr_exp, val.right_data()[0]._mpfr_sign);
  1254. return result;
  1255. }
  1256. template <class To, unsigned D>
  1257. void generic_interconvert(To& to, const mpfi_float_backend<D>& from, const std::integral_constant<int, number_kind_integer>& to_type, const std::integral_constant<int, number_kind_floating_point>& from_type)
  1258. {
  1259. using boost::multiprecision::detail::generic_interconvert;
  1260. boost::multiprecision::detail::scoped_precision_options<number<mpfr_float_backend<D>>> scoped(from);
  1261. mpfr_float_backend<D> t;
  1262. mpfi_mid(t.data(), from.data());
  1263. generic_interconvert(to, t, to_type, from_type);
  1264. }
  1265. template <class To, unsigned D>
  1266. void generic_interconvert(To& to, const mpfi_float_backend<D>& from, const std::integral_constant<int, number_kind_rational>& to_type, const std::integral_constant<int, number_kind_floating_point>& from_type)
  1267. {
  1268. using boost::multiprecision::detail::generic_interconvert;
  1269. boost::multiprecision::detail::scoped_precision_options<number<mpfr_float_backend<D>>> scoped(from);
  1270. mpfr_float_backend<D> t;
  1271. mpfi_mid(t.data(), from.data());
  1272. generic_interconvert(to, t, to_type, from_type);
  1273. }
  1274. template <class To, unsigned D>
  1275. void generic_interconvert(To& to, const mpfi_float_backend<D>& from, const std::integral_constant<int, number_kind_floating_point>& to_type, const std::integral_constant<int, number_kind_floating_point>& from_type)
  1276. {
  1277. using boost::multiprecision::detail::generic_interconvert;
  1278. boost::multiprecision::detail::scoped_precision_options<number<mpfr_float_backend<D>>> scoped(from);
  1279. mpfr_float_backend<D> t;
  1280. mpfi_mid(t.data(), from.data());
  1281. generic_interconvert(to, t, to_type, from_type);
  1282. }
  1283. } // namespace backends
  1284. template <>
  1285. struct number_category<detail::canonical<mpfi_t, backends::mpfi_float_backend<0> >::type> : public std::integral_constant<int, number_kind_floating_point>
  1286. {};
  1287. template <unsigned Digits10>
  1288. struct is_interval_number<backends::mpfi_float_backend<Digits10> > : public std::integral_constant<bool, true>
  1289. {};
  1290. //
  1291. // Special interval specific functions:
  1292. //
  1293. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1294. inline number<mpfr_float_backend<Digits10>, ExpressionTemplates> lower(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val)
  1295. {
  1296. boost::multiprecision::detail::scoped_precision_options<number<mpfr_float_backend<Digits10>, ExpressionTemplates> > precision_guard(val);
  1297. number<mpfr_float_backend<Digits10> > result;
  1298. mpfr_set(result.backend().data(), val.backend().left_data(), GMP_RNDN);
  1299. return result;
  1300. }
  1301. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1302. inline number<mpfr_float_backend<Digits10>, ExpressionTemplates> upper(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val)
  1303. {
  1304. boost::multiprecision::detail::scoped_precision_options<number<mpfr_float_backend<Digits10>, ExpressionTemplates> > precision_guard(val);
  1305. number<mpfr_float_backend<Digits10> > result;
  1306. mpfr_set(result.backend().data(), val.backend().right_data(), GMP_RNDN);
  1307. return result;
  1308. }
  1309. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1310. inline number<mpfr_float_backend<Digits10>, ExpressionTemplates> median(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val)
  1311. {
  1312. boost::multiprecision::detail::scoped_precision_options<number<mpfr_float_backend<Digits10>, ExpressionTemplates> > precision_guard(val);
  1313. number<mpfr_float_backend<Digits10> > result;
  1314. mpfi_mid(result.backend().data(), val.backend().data());
  1315. return result;
  1316. }
  1317. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1318. inline number<mpfr_float_backend<Digits10>, ExpressionTemplates> width(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val)
  1319. {
  1320. boost::multiprecision::detail::scoped_precision_options<number<mpfr_float_backend<Digits10>, ExpressionTemplates> > precision_guard(val);
  1321. number<mpfr_float_backend<Digits10> > result;
  1322. mpfi_diam_abs(result.backend().data(), val.backend().data());
  1323. return result;
  1324. }
  1325. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1326. inline number<mpfi_float_backend<Digits10>, ExpressionTemplates> intersect(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b)
  1327. {
  1328. boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(a, b);
  1329. number<mpfi_float_backend<Digits10>, ExpressionTemplates> result;
  1330. mpfi_intersect(result.backend().data(), a.backend().data(), b.backend().data());
  1331. return result;
  1332. }
  1333. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1334. inline number<mpfi_float_backend<Digits10>, ExpressionTemplates> hull(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b)
  1335. {
  1336. boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(a, b);
  1337. number<mpfi_float_backend<Digits10>, ExpressionTemplates> result;
  1338. mpfi_union(result.backend().data(), a.backend().data(), b.backend().data());
  1339. return result;
  1340. }
  1341. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1342. inline bool overlap(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b)
  1343. {
  1344. return (lower(a) <= lower(b) && lower(b) <= upper(a)) ||
  1345. (lower(b) <= lower(a) && lower(a) <= upper(b));
  1346. }
  1347. template <unsigned Digits10, expression_template_option ExpressionTemplates1, expression_template_option ExpressionTemplates2>
  1348. inline bool in(const number<mpfr_float_backend<Digits10>, ExpressionTemplates1>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates2>& b)
  1349. {
  1350. return mpfi_is_inside_fr(a.backend().data(), b.backend().data()) != 0;
  1351. }
  1352. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1353. inline bool zero_in(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a)
  1354. {
  1355. return mpfi_has_zero(a.backend().data()) != 0;
  1356. }
  1357. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1358. inline bool subset(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b)
  1359. {
  1360. return mpfi_is_inside(a.backend().data(), b.backend().data()) != 0;
  1361. }
  1362. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1363. inline bool proper_subset(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b)
  1364. {
  1365. return mpfi_is_strictly_inside(a.backend().data(), b.backend().data()) != 0;
  1366. }
  1367. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1368. inline bool empty(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a)
  1369. {
  1370. return mpfi_is_empty(a.backend().data()) != 0;
  1371. }
  1372. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1373. inline bool singleton(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a)
  1374. {
  1375. return mpfr_cmp(a.backend().left_data(), a.backend().right_data()) == 0;
  1376. }
  1377. //
  1378. // Again with debug_adaptor:
  1379. //
  1380. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1381. inline number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> lower(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& val)
  1382. {
  1383. boost::multiprecision::detail::scoped_default_precision<number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(val);
  1384. number<debug_adaptor<mpfr_float_backend<Digits10> > > result;
  1385. mpfr_set(result.backend().value().data(), val.backend().value().left_data(), GMP_RNDN);
  1386. return result;
  1387. }
  1388. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1389. inline number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> upper(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& val)
  1390. {
  1391. boost::multiprecision::detail::scoped_default_precision<number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(val);
  1392. number<debug_adaptor<mpfr_float_backend<Digits10> > > result;
  1393. mpfr_set(result.backend().value().data(), val.backend().value().right_data(), GMP_RNDN);
  1394. return result;
  1395. }
  1396. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1397. inline number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> median(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& val)
  1398. {
  1399. boost::multiprecision::detail::scoped_default_precision<number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(val);
  1400. number<debug_adaptor<mpfr_float_backend<Digits10> > > result;
  1401. mpfi_mid(result.backend().value().data(), val.backend().value().data());
  1402. return result;
  1403. }
  1404. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1405. inline number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> width(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& val)
  1406. {
  1407. boost::multiprecision::detail::scoped_default_precision<number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(val);
  1408. number<debug_adaptor<mpfr_float_backend<Digits10> > > result;
  1409. mpfi_diam_abs(result.backend().value().data(), val.backend().value().data());
  1410. return result;
  1411. }
  1412. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1413. inline number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> intersect(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
  1414. {
  1415. boost::multiprecision::detail::scoped_default_precision<number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(a, b);
  1416. number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
  1417. mpfi_intersect(result.backend().value().data(), a.backend().value().data(), b.backend().value().data());
  1418. return result;
  1419. }
  1420. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1421. inline number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> hull(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
  1422. {
  1423. boost::multiprecision::detail::scoped_default_precision<number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(a, b);
  1424. number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
  1425. mpfi_union(result.backend().value().data(), a.backend().value().data(), b.backend().value().data());
  1426. return result;
  1427. }
  1428. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1429. inline bool overlap(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
  1430. {
  1431. return (lower(a) <= lower(b) && lower(b) <= upper(a)) ||
  1432. (lower(b) <= lower(a) && lower(a) <= upper(b));
  1433. }
  1434. template <unsigned Digits10, expression_template_option ExpressionTemplates1, expression_template_option ExpressionTemplates2>
  1435. inline bool in(const number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates1>& a, const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates2>& b)
  1436. {
  1437. return mpfi_is_inside_fr(a.backend().value().data(), b.backend().value().data()) != 0;
  1438. }
  1439. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1440. inline bool zero_in(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a)
  1441. {
  1442. return mpfi_has_zero(a.backend().value().data()) != 0;
  1443. }
  1444. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1445. inline bool subset(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
  1446. {
  1447. return mpfi_is_inside(a.backend().value().data(), b.backend().value().data()) != 0;
  1448. }
  1449. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1450. inline bool proper_subset(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
  1451. {
  1452. return mpfi_is_strictly_inside(a.backend().value().data(), b.backend().value().data()) != 0;
  1453. }
  1454. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1455. inline bool empty(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a)
  1456. {
  1457. return mpfi_is_empty(a.backend().value().data()) != 0;
  1458. }
  1459. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1460. inline bool singleton(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a)
  1461. {
  1462. return mpfr_cmp(a.backend().value().left_data(), a.backend().value().right_data()) == 0;
  1463. }
  1464. //
  1465. // Again with logged_adaptor:
  1466. //
  1467. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1468. inline number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> lower(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& val)
  1469. {
  1470. boost::multiprecision::detail::scoped_default_precision<number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(val);
  1471. number<logged_adaptor<mpfr_float_backend<Digits10> > > result;
  1472. mpfr_set(result.backend().value().data(), val.backend().value().left_data(), GMP_RNDN);
  1473. return result;
  1474. }
  1475. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1476. inline number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> upper(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& val)
  1477. {
  1478. boost::multiprecision::detail::scoped_default_precision<number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(val);
  1479. number<logged_adaptor<mpfr_float_backend<Digits10> > > result;
  1480. mpfr_set(result.backend().value().data(), val.backend().value().right_data(), GMP_RNDN);
  1481. return result;
  1482. }
  1483. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1484. inline number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> median(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& val)
  1485. {
  1486. boost::multiprecision::detail::scoped_default_precision<number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(val);
  1487. number<logged_adaptor<mpfr_float_backend<Digits10> > > result;
  1488. mpfi_mid(result.backend().value().data(), val.backend().value().data());
  1489. return result;
  1490. }
  1491. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1492. inline number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> width(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& val)
  1493. {
  1494. boost::multiprecision::detail::scoped_default_precision<number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(val);
  1495. number<logged_adaptor<mpfr_float_backend<Digits10> > > result;
  1496. mpfi_diam_abs(result.backend().value().data(), val.backend().value().data());
  1497. return result;
  1498. }
  1499. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1500. inline number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> intersect(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
  1501. {
  1502. boost::multiprecision::detail::scoped_default_precision<number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(a, b);
  1503. number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
  1504. mpfi_intersect(result.backend().value().data(), a.backend().value().data(), b.backend().value().data());
  1505. return result;
  1506. }
  1507. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1508. inline number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> hull(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
  1509. {
  1510. boost::multiprecision::detail::scoped_default_precision<number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(a, b);
  1511. number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
  1512. mpfi_union(result.backend().value().data(), a.backend().value().data(), b.backend().value().data());
  1513. return result;
  1514. }
  1515. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1516. inline bool overlap(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
  1517. {
  1518. return (lower(a) <= lower(b) && lower(b) <= upper(a)) ||
  1519. (lower(b) <= lower(a) && lower(a) <= upper(b));
  1520. }
  1521. template <unsigned Digits10, expression_template_option ExpressionTemplates1, expression_template_option ExpressionTemplates2>
  1522. inline bool in(const number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates1>& a, const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates2>& b)
  1523. {
  1524. return mpfi_is_inside_fr(a.backend().value().data(), b.backend().value().data()) != 0;
  1525. }
  1526. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1527. inline bool zero_in(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a)
  1528. {
  1529. return mpfi_has_zero(a.backend().value().data()) != 0;
  1530. }
  1531. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1532. inline bool subset(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
  1533. {
  1534. return mpfi_is_inside(a.backend().value().data(), b.backend().value().data()) != 0;
  1535. }
  1536. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1537. inline bool proper_subset(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
  1538. {
  1539. return mpfi_is_strictly_inside(a.backend().value().data(), b.backend().value().data()) != 0;
  1540. }
  1541. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1542. inline bool empty(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a)
  1543. {
  1544. return mpfi_is_empty(a.backend().value().data()) != 0;
  1545. }
  1546. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1547. inline bool singleton(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a)
  1548. {
  1549. return mpfr_cmp(a.backend().value().left_data(), a.backend().value().right_data()) == 0;
  1550. }
  1551. //
  1552. // component_type specialization:
  1553. //
  1554. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1555. struct component_type<number<mpfi_float_backend<Digits10>, ExpressionTemplates> >
  1556. {
  1557. using type = number<mpfr_float_backend<Digits10>, ExpressionTemplates>;
  1558. };
  1559. //
  1560. // Overloaded special functions which call native mpfr routines:
  1561. //
  1562. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1563. 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)
  1564. {
  1565. boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
  1566. boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
  1567. mpfi_asinh(result.backend().data(), arg.backend().data());
  1568. return result;
  1569. }
  1570. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1571. 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)
  1572. {
  1573. boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
  1574. boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
  1575. mpfi_acosh(result.backend().data(), arg.backend().data());
  1576. return result;
  1577. }
  1578. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1579. 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)
  1580. {
  1581. boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
  1582. boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
  1583. mpfi_atanh(result.backend().data(), arg.backend().data());
  1584. return result;
  1585. }
  1586. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1587. 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)
  1588. {
  1589. boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
  1590. boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
  1591. mpfi_cbrt(result.backend().data(), arg.backend().data());
  1592. return result;
  1593. }
  1594. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1595. 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)
  1596. {
  1597. boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
  1598. boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
  1599. mpfi_expm1(result.backend().data(), arg.backend().data());
  1600. return result;
  1601. }
  1602. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1603. 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)
  1604. {
  1605. boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
  1606. boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
  1607. mpfi_log1p(result.backend().data(), arg.backend().data());
  1608. return result;
  1609. }
  1610. //
  1611. // And again with debug_adaptor:
  1612. //
  1613. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1614. inline boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
  1615. {
  1616. boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
  1617. boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
  1618. mpfi_asinh(result.backend().value().data(), arg.backend().value().data());
  1619. return result;
  1620. }
  1621. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1622. inline boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
  1623. {
  1624. boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
  1625. boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
  1626. mpfi_acosh(result.backend().value().data(), arg.backend().value().data());
  1627. return result;
  1628. }
  1629. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1630. inline boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
  1631. {
  1632. boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
  1633. boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
  1634. mpfi_atanh(result.backend().value().data(), arg.backend().value().data());
  1635. return result;
  1636. }
  1637. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1638. inline boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
  1639. {
  1640. boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
  1641. boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
  1642. mpfi_cbrt(result.backend().value().data(), arg.backend().value().data());
  1643. return result;
  1644. }
  1645. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1646. inline boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
  1647. {
  1648. boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
  1649. boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
  1650. mpfi_expm1(result.backend().value().data(), arg.backend().value().data());
  1651. return result;
  1652. }
  1653. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1654. inline boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
  1655. {
  1656. boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
  1657. boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
  1658. mpfi_log1p(result.backend().value().data(), arg.backend().value().data());
  1659. return result;
  1660. }
  1661. //
  1662. // And again with logged_adaptor:
  1663. //
  1664. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1665. inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
  1666. {
  1667. boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
  1668. boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
  1669. mpfi_asinh(result.backend().value().data(), arg.backend().value().data());
  1670. return result;
  1671. }
  1672. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1673. inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
  1674. {
  1675. boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
  1676. boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
  1677. mpfi_acosh(result.backend().value().data(), arg.backend().value().data());
  1678. return result;
  1679. }
  1680. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1681. inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
  1682. {
  1683. boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
  1684. boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
  1685. mpfi_atanh(result.backend().value().data(), arg.backend().value().data());
  1686. return result;
  1687. }
  1688. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1689. inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
  1690. {
  1691. boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
  1692. boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
  1693. mpfi_cbrt(result.backend().value().data(), arg.backend().value().data());
  1694. return result;
  1695. }
  1696. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1697. inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
  1698. {
  1699. boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
  1700. boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
  1701. mpfi_expm1(result.backend().value().data(), arg.backend().value().data());
  1702. return result;
  1703. }
  1704. template <unsigned Digits10, expression_template_option ExpressionTemplates>
  1705. inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
  1706. {
  1707. boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
  1708. boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
  1709. mpfi_log1p(result.backend().value().data(), arg.backend().value().data());
  1710. return result;
  1711. }
  1712. } // namespace multiprecision
  1713. namespace math {
  1714. namespace tools {
  1715. inline void set_output_precision(const boost::multiprecision::mpfi_float& val, std::ostream& os)
  1716. {
  1717. os << std::setprecision(val.precision());
  1718. }
  1719. template <>
  1720. inline int digits<boost::multiprecision::mpfi_float>()
  1721. #ifdef BOOST_MATH_NOEXCEPT
  1722. noexcept
  1723. #endif
  1724. {
  1725. return multiprecision::detail::digits10_2_2(boost::multiprecision::mpfi_float::thread_default_precision());
  1726. }
  1727. template <>
  1728. inline int digits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> >()
  1729. #ifdef BOOST_MATH_NOEXCEPT
  1730. noexcept
  1731. #endif
  1732. {
  1733. return multiprecision::detail::digits10_2_2(boost::multiprecision::mpfi_float::thread_default_precision());
  1734. }
  1735. template <>
  1736. inline boost::multiprecision::mpfi_float
  1737. max_value<boost::multiprecision::mpfi_float>()
  1738. {
  1739. boost::multiprecision::mpfi_float result(0.5);
  1740. mpfi_mul_2exp(result.backend().data(), result.backend().data(), mpfr_get_emax());
  1741. //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
  1742. return result;
  1743. }
  1744. template <>
  1745. inline boost::multiprecision::mpfi_float
  1746. min_value<boost::multiprecision::mpfi_float>()
  1747. {
  1748. boost::multiprecision::mpfi_float result(0.5);
  1749. mpfi_div_2exp(result.backend().data(), result.backend().data(), -mpfr_get_emin());
  1750. //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
  1751. return result;
  1752. }
  1753. template <>
  1754. inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off>
  1755. max_value<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> >()
  1756. {
  1757. boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> result(0.5);
  1758. mpfi_mul_2exp(result.backend().data(), result.backend().data(), mpfr_get_emax());
  1759. //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
  1760. return result;
  1761. }
  1762. template <>
  1763. inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off>
  1764. min_value<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> >()
  1765. {
  1766. boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> result(0.5);
  1767. mpfi_div_2exp(result.backend().data(), result.backend().data(), -mpfr_get_emin());
  1768. //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
  1769. return result;
  1770. }
  1771. // mpfi gets used with logged_adaptor fairly often, so specialize for that use case as well:
  1772. using logged_type1 = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float::backend_type>, boost::multiprecision::et_on> ;
  1773. using logged_type2 = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float::backend_type>, boost::multiprecision::et_off>;
  1774. template <>
  1775. inline int digits<logged_type1>()
  1776. #ifdef BOOST_MATH_NOEXCEPT
  1777. noexcept
  1778. #endif
  1779. {
  1780. return multiprecision::detail::digits10_2_2(logged_type1::thread_default_precision());
  1781. }
  1782. template <>
  1783. inline int digits<logged_type2>()
  1784. #ifdef BOOST_MATH_NOEXCEPT
  1785. noexcept
  1786. #endif
  1787. {
  1788. return multiprecision::detail::digits10_2_2(logged_type1::thread_default_precision());
  1789. }
  1790. template <>
  1791. inline logged_type1
  1792. max_value<logged_type1>()
  1793. {
  1794. logged_type1 result(0.5);
  1795. mpfi_mul_2exp(result.backend().value().data(), result.backend().value().data(), mpfr_get_emax());
  1796. //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
  1797. return result;
  1798. }
  1799. template <>
  1800. inline logged_type1
  1801. min_value<logged_type1>()
  1802. {
  1803. logged_type1 result(0.5);
  1804. mpfi_div_2exp(result.backend().value().data(), result.backend().value().data(), -mpfr_get_emin());
  1805. //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
  1806. return result;
  1807. }
  1808. template <>
  1809. inline logged_type2
  1810. max_value<logged_type2>()
  1811. {
  1812. logged_type2 result(0.5);
  1813. mpfi_mul_2exp(result.backend().value().data(), result.backend().value().data(), mpfr_get_emax());
  1814. //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
  1815. return result;
  1816. }
  1817. template <>
  1818. inline logged_type2
  1819. min_value<logged_type2>()
  1820. {
  1821. logged_type2 result(0.5);
  1822. mpfi_div_2exp(result.backend().value().data(), result.backend().value().data(), -mpfr_get_emin());
  1823. //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
  1824. return result;
  1825. }
  1826. // mpfi gets used with debug_adaptor fairly often, so specialize for that use case as well:
  1827. using debug_type1 = boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float::backend_type>, boost::multiprecision::et_on> ;
  1828. using debug_type2 = boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float::backend_type>, boost::multiprecision::et_off>;
  1829. template <>
  1830. inline int digits<debug_type1>()
  1831. #ifdef BOOST_MATH_NOEXCEPT
  1832. noexcept
  1833. #endif
  1834. {
  1835. return multiprecision::detail::digits10_2_2(debug_type1::default_precision());
  1836. }
  1837. template <>
  1838. inline int digits<debug_type2>()
  1839. #ifdef BOOST_MATH_NOEXCEPT
  1840. noexcept
  1841. #endif
  1842. {
  1843. return multiprecision::detail::digits10_2_2(debug_type1::default_precision());
  1844. }
  1845. template <>
  1846. inline debug_type1
  1847. max_value<debug_type1>()
  1848. {
  1849. debug_type1 result(0.5);
  1850. mpfi_mul_2exp(result.backend().value().data(), result.backend().value().data(), mpfr_get_emax());
  1851. //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
  1852. result.backend().update_view();
  1853. return result;
  1854. }
  1855. template <>
  1856. inline debug_type1
  1857. min_value<debug_type1>()
  1858. {
  1859. debug_type1 result(0.5);
  1860. mpfi_div_2exp(result.backend().value().data(), result.backend().value().data(), -mpfr_get_emin());
  1861. //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
  1862. result.backend().update_view();
  1863. return result;
  1864. }
  1865. template <>
  1866. inline debug_type2
  1867. max_value<debug_type2>()
  1868. {
  1869. debug_type2 result(0.5);
  1870. mpfi_mul_2exp(result.backend().value().data(), result.backend().value().data(), mpfr_get_emax());
  1871. //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
  1872. result.backend().update_view();
  1873. return result;
  1874. }
  1875. template <>
  1876. inline debug_type2
  1877. min_value<debug_type2>()
  1878. {
  1879. debug_type2 result(0.5);
  1880. mpfi_div_2exp(result.backend().value().data(), result.backend().value().data(), -mpfr_get_emin());
  1881. //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
  1882. result.backend().update_view();
  1883. return result;
  1884. }
  1885. } // namespace tools
  1886. namespace constants { namespace detail {
  1887. template <class T>
  1888. struct constant_pi;
  1889. template <class T>
  1890. struct constant_ln_two;
  1891. template <class T>
  1892. struct constant_euler;
  1893. template <class T>
  1894. struct constant_catalan;
  1895. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1896. struct constant_pi<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
  1897. {
  1898. using result_type = boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>;
  1899. template <int N>
  1900. static inline const result_type& get(const std::integral_constant<int, N>&)
  1901. {
  1902. // Rely on C++11 thread safe initialization:
  1903. static result_type result{get(std::integral_constant<int, 0>())};
  1904. return result;
  1905. }
  1906. static inline result_type get(const std::integral_constant<int, 0>&)
  1907. {
  1908. result_type result;
  1909. mpfi_const_pi(result.backend().data());
  1910. return result;
  1911. }
  1912. };
  1913. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1914. struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
  1915. {
  1916. using result_type = boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>;
  1917. template <int N>
  1918. static inline const result_type& get(const std::integral_constant<int, N>&)
  1919. {
  1920. // Rely on C++11 thread safe initialization:
  1921. static result_type result{get(std::integral_constant<int, 0>())};
  1922. return result;
  1923. }
  1924. static inline result_type get(const std::integral_constant<int, 0>&)
  1925. {
  1926. result_type result;
  1927. mpfi_const_log2(result.backend().data());
  1928. return result;
  1929. }
  1930. };
  1931. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1932. struct constant_euler<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
  1933. {
  1934. using result_type = boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>;
  1935. template <int N>
  1936. static inline const result_type& get(const std::integral_constant<int, N>&)
  1937. {
  1938. // Rely on C++11 thread safe initialization:
  1939. static result_type result{get(std::integral_constant<int, 0>())};
  1940. return result;
  1941. }
  1942. static inline result_type get(const std::integral_constant<int, 0>&)
  1943. {
  1944. result_type result;
  1945. mpfi_const_euler(result.backend().data());
  1946. return result;
  1947. }
  1948. };
  1949. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1950. struct constant_catalan<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
  1951. {
  1952. using result_type = boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>;
  1953. template <int N>
  1954. static inline const result_type& get(const std::integral_constant<int, N>&)
  1955. {
  1956. // Rely on C++11 thread safe initialization:
  1957. static result_type result{get(std::integral_constant<int, 0>())};
  1958. return result;
  1959. }
  1960. static inline result_type get(const std::integral_constant<int, 0>&)
  1961. {
  1962. result_type result;
  1963. mpfi_const_catalan(result.backend().data());
  1964. return result;
  1965. }
  1966. };
  1967. //
  1968. // And again with debug_adaptor:
  1969. //
  1970. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1971. struct constant_pi<boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> >
  1972. {
  1973. using result_type = boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>;
  1974. template <int N>
  1975. static inline const result_type& get(const std::integral_constant<int, N>&)
  1976. {
  1977. // C++11 thread safe static initialization:
  1978. static result_type result{get(std::integral_constant<int, 0>())};
  1979. return result;
  1980. }
  1981. static inline result_type get(const std::integral_constant<int, 0>&)
  1982. {
  1983. result_type result;
  1984. mpfi_const_pi(result.backend().value().data());
  1985. result.backend().update_view();
  1986. return result;
  1987. }
  1988. };
  1989. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  1990. struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> >
  1991. {
  1992. using result_type = boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>;
  1993. template <int N>
  1994. static inline const result_type& get(const std::integral_constant<int, N>&)
  1995. {
  1996. // C++11 thread safe static initialization:
  1997. static result_type result{get(std::integral_constant<int, 0>())};
  1998. return result;
  1999. }
  2000. static inline result_type get(const std::integral_constant<int, 0>&)
  2001. {
  2002. result_type result;
  2003. mpfi_const_log2(result.backend().value().data());
  2004. result.backend().update_view();
  2005. return result;
  2006. }
  2007. };
  2008. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2009. struct constant_euler<boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> >
  2010. {
  2011. using result_type = boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>;
  2012. template <int N>
  2013. static inline const result_type& get(const std::integral_constant<int, N>&)
  2014. {
  2015. // C++11 thread safe static initialization:
  2016. static result_type result{get(std::integral_constant<int, 0>())};
  2017. return result;
  2018. }
  2019. static inline result_type get(const std::integral_constant<int, 0>&)
  2020. {
  2021. result_type result;
  2022. mpfi_const_euler(result.backend().value().data());
  2023. result.backend().update_view();
  2024. return result;
  2025. }
  2026. };
  2027. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2028. struct constant_catalan<boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> >
  2029. {
  2030. using result_type = boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>;
  2031. template <int N>
  2032. static inline const result_type& get(const std::integral_constant<int, N>&)
  2033. {
  2034. // C++11 thread safe static initialization:
  2035. static result_type result{get(std::integral_constant<int, 0>())};
  2036. return result;
  2037. }
  2038. static inline result_type get(const std::integral_constant<int, 0>&)
  2039. {
  2040. result_type result;
  2041. mpfi_const_catalan(result.backend().value().data());
  2042. result.backend().update_view();
  2043. return result;
  2044. }
  2045. };
  2046. //
  2047. // And again with logged_adaptor:
  2048. //
  2049. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2050. struct constant_pi<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> >
  2051. {
  2052. using result_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>;
  2053. template <int N>
  2054. static inline const result_type& get(const std::integral_constant<int, N>&)
  2055. {
  2056. // C++11 thread safe static initialization:
  2057. static result_type result{get(std::integral_constant<int, 0>())};
  2058. return result;
  2059. }
  2060. static inline result_type get(const std::integral_constant<int, 0>&)
  2061. {
  2062. result_type result;
  2063. mpfi_const_pi(result.backend().value().data());
  2064. return result;
  2065. }
  2066. };
  2067. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2068. struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> >
  2069. {
  2070. using result_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>;
  2071. template <int N>
  2072. static inline const result_type& get(const std::integral_constant<int, N>&)
  2073. {
  2074. // C++11 thread safe static initialization:
  2075. static result_type result{get(std::integral_constant<int, 0>())};
  2076. return result;
  2077. }
  2078. static inline result_type get(const std::integral_constant<int, 0>&)
  2079. {
  2080. result_type result;
  2081. mpfi_const_log2(result.backend().value().data());
  2082. return result;
  2083. }
  2084. };
  2085. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2086. struct constant_euler<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> >
  2087. {
  2088. using result_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>;
  2089. template <int N>
  2090. static inline const result_type& get(const std::integral_constant<int, N>&)
  2091. {
  2092. // C++11 thread safe static initialization:
  2093. static result_type result{get(std::integral_constant<int, 0>())};
  2094. return result;
  2095. }
  2096. static inline result_type get(const std::integral_constant<int, 0>&)
  2097. {
  2098. result_type result;
  2099. mpfi_const_euler(result.backend().value().data());
  2100. return result;
  2101. }
  2102. };
  2103. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2104. struct constant_catalan<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> >
  2105. {
  2106. using result_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>;
  2107. template <int N>
  2108. static inline const result_type& get(const std::integral_constant<int, N>&)
  2109. {
  2110. // C++11 thread safe static initialization:
  2111. static result_type result{get(std::integral_constant<int, 0>())};
  2112. return result;
  2113. }
  2114. static inline result_type get(const std::integral_constant<int, 0>&)
  2115. {
  2116. result_type result;
  2117. mpfi_const_catalan(result.backend().value().data());
  2118. return result;
  2119. }
  2120. };
  2121. }} // namespace constants::detail
  2122. } // namespace math
  2123. } // namespace boost
  2124. namespace std {
  2125. //
  2126. // numeric_limits [partial] specializations for the types declared in this header:
  2127. //
  2128. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2129. class numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
  2130. {
  2131. using number_type = boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>;
  2132. static number_type get_min()
  2133. {
  2134. number_type value(0.5);
  2135. mpfi_div_2exp(value.backend().data(), value.backend().data(), -mpfr_get_emin());
  2136. return value;
  2137. }
  2138. static number_type get_max()
  2139. {
  2140. number_type value(0.5);
  2141. mpfi_mul_2exp(value.backend().data(), value.backend().data(), mpfr_get_emax());
  2142. return value;
  2143. }
  2144. static number_type get_epsilon()
  2145. {
  2146. number_type value(1);
  2147. mpfi_div_2exp(value.backend().data(), value.backend().data(), std::numeric_limits<number_type>::digits - 1);
  2148. return value;
  2149. }
  2150. static number_type get_infinity()
  2151. {
  2152. number_type value;
  2153. boost::multiprecision::mpfr_float_backend<Digits10> t;
  2154. mpfr_set_inf(t.data(), 1);
  2155. mpfi_set_fr(value.backend().data(), t.data());
  2156. return value;
  2157. }
  2158. static number_type get_quiet_NaN()
  2159. {
  2160. number_type value;
  2161. boost::multiprecision::mpfr_float_backend<Digits10> t;
  2162. mpfr_set_nan(t.data());
  2163. mpfi_set_fr(value.backend().data(), t.data());
  2164. return value;
  2165. }
  2166. public:
  2167. static constexpr bool is_specialized = true;
  2168. static number_type(min)()
  2169. {
  2170. static number_type value{get_min()};
  2171. return value;
  2172. }
  2173. static number_type(max)()
  2174. {
  2175. static number_type value{get_max()};
  2176. return value;
  2177. }
  2178. static constexpr number_type lowest()
  2179. {
  2180. return -(max)();
  2181. }
  2182. static constexpr int digits = static_cast<int>((Digits10 * 1000L) / 301L + ((Digits10 * 1000L) % 301 ? 2 : 1));
  2183. static constexpr int digits10 = Digits10;
  2184. // Is this really correct???
  2185. static constexpr int max_digits10 = boost::multiprecision::detail::calc_max_digits10<digits>::value;
  2186. static constexpr bool is_signed = true;
  2187. static constexpr bool is_integer = false;
  2188. static constexpr bool is_exact = false;
  2189. static constexpr int radix = 2;
  2190. static number_type epsilon()
  2191. {
  2192. static number_type value{get_epsilon()};
  2193. return value;
  2194. }
  2195. // What value should this be????
  2196. static number_type round_error()
  2197. {
  2198. return 0.5;
  2199. }
  2200. static constexpr long min_exponent = MPFR_EMIN_DEFAULT;
  2201. static constexpr long min_exponent10 = (MPFR_EMIN_DEFAULT / 1000) * 301L;
  2202. static constexpr long max_exponent = MPFR_EMAX_DEFAULT;
  2203. static constexpr long max_exponent10 = (MPFR_EMAX_DEFAULT / 1000) * 301L;
  2204. static constexpr bool has_infinity = true;
  2205. static constexpr bool has_quiet_NaN = true;
  2206. static constexpr bool has_signaling_NaN = false;
  2207. #ifdef _MSC_VER
  2208. #pragma warning(push)
  2209. #pragma warning(disable : 4996)
  2210. #endif
  2211. static constexpr float_denorm_style has_denorm = denorm_absent;
  2212. #ifdef _MSC_VER
  2213. #pragma warning(pop)
  2214. #endif
  2215. static constexpr bool has_denorm_loss = false;
  2216. static number_type infinity()
  2217. {
  2218. static number_type value{get_infinity()};
  2219. return value;
  2220. }
  2221. static number_type quiet_NaN()
  2222. {
  2223. static number_type value{get_quiet_NaN()};
  2224. return value;
  2225. }
  2226. static constexpr number_type signaling_NaN()
  2227. {
  2228. return number_type(0);
  2229. }
  2230. static constexpr number_type denorm_min() { return (min)(); }
  2231. static constexpr bool is_iec559 = false;
  2232. static constexpr bool is_bounded = true;
  2233. static constexpr bool is_modulo = false;
  2234. static constexpr bool traps = true;
  2235. static constexpr bool tinyness_before = false;
  2236. static constexpr float_round_style round_style = round_to_nearest;
  2237. };
  2238. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2239. constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::digits;
  2240. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2241. constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::digits10;
  2242. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2243. constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::max_digits10;
  2244. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2245. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_signed;
  2246. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2247. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_integer;
  2248. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2249. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_exact;
  2250. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2251. constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::radix;
  2252. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2253. constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::min_exponent;
  2254. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2255. constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::min_exponent10;
  2256. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2257. constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::max_exponent;
  2258. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2259. constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::max_exponent10;
  2260. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2261. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::has_infinity;
  2262. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2263. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::has_quiet_NaN;
  2264. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2265. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::has_signaling_NaN;
  2266. #ifdef _MSC_VER
  2267. #pragma warning(push)
  2268. #pragma warning(disable : 4996)
  2269. #endif
  2270. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2271. constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::has_denorm;
  2272. #ifdef _MSC_VER
  2273. #pragma warning(pop)
  2274. #endif
  2275. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2276. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::has_denorm_loss;
  2277. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2278. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_iec559;
  2279. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2280. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_bounded;
  2281. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2282. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_modulo;
  2283. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2284. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::traps;
  2285. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2286. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::tinyness_before;
  2287. template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
  2288. constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::round_style;
  2289. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2290. class numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >
  2291. {
  2292. using number_type = boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates>;
  2293. public:
  2294. static constexpr bool is_specialized = false;
  2295. static number_type(min)() { return number_type(0); }
  2296. static number_type(max)() { return number_type(0); }
  2297. static number_type lowest() { return number_type(0); }
  2298. static constexpr int digits = 0;
  2299. static constexpr int digits10 = 0;
  2300. static constexpr int max_digits10 = 0;
  2301. static constexpr bool is_signed = false;
  2302. static constexpr bool is_integer = false;
  2303. static constexpr bool is_exact = false;
  2304. static constexpr int radix = 0;
  2305. static number_type epsilon() { return number_type(0); }
  2306. static number_type round_error() { return number_type(0); }
  2307. static constexpr int min_exponent = 0;
  2308. static constexpr int min_exponent10 = 0;
  2309. static constexpr int max_exponent = 0;
  2310. static constexpr int max_exponent10 = 0;
  2311. static constexpr bool has_infinity = false;
  2312. static constexpr bool has_quiet_NaN = false;
  2313. static constexpr bool has_signaling_NaN = false;
  2314. #ifdef _MSC_VER
  2315. #pragma warning(push)
  2316. #pragma warning(disable : 4996)
  2317. #endif
  2318. static constexpr float_denorm_style has_denorm = denorm_absent;
  2319. #ifdef _MSC_VER
  2320. #pragma warning(pop)
  2321. #endif
  2322. static constexpr bool has_denorm_loss = false;
  2323. static number_type infinity() { return number_type(0); }
  2324. static number_type quiet_NaN() { return number_type(0); }
  2325. static number_type signaling_NaN() { return number_type(0); }
  2326. static number_type denorm_min() { return number_type(0); }
  2327. static constexpr bool is_iec559 = false;
  2328. static constexpr bool is_bounded = false;
  2329. static constexpr bool is_modulo = false;
  2330. static constexpr bool traps = false;
  2331. static constexpr bool tinyness_before = false;
  2332. static constexpr float_round_style round_style = round_toward_zero;
  2333. };
  2334. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2335. constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::digits;
  2336. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2337. constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::digits10;
  2338. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2339. constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::max_digits10;
  2340. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2341. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_signed;
  2342. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2343. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_integer;
  2344. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2345. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_exact;
  2346. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2347. constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::radix;
  2348. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2349. constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::min_exponent;
  2350. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2351. constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::min_exponent10;
  2352. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2353. constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::max_exponent;
  2354. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2355. constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::max_exponent10;
  2356. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2357. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::has_infinity;
  2358. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2359. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::has_quiet_NaN;
  2360. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2361. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::has_signaling_NaN;
  2362. #ifdef _MSC_VER
  2363. #pragma warning(push)
  2364. #pragma warning(disable : 4996)
  2365. #endif
  2366. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2367. constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::has_denorm;
  2368. #ifdef _MSC_VER
  2369. #pragma warning(pop)
  2370. #endif
  2371. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2372. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::has_denorm_loss;
  2373. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2374. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_iec559;
  2375. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2376. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_bounded;
  2377. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2378. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_modulo;
  2379. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2380. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::traps;
  2381. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2382. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::tinyness_before;
  2383. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  2384. constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::round_style;
  2385. } // namespace std
  2386. #endif