float128.hpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868
  1. ///////////////////////////////////////////////////////////////
  2. // Copyright 2013 John Maddock. Distributed under the Boost
  3. // Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
  5. #ifndef BOOST_MP_FLOAT128_HPP
  6. #define BOOST_MP_FLOAT128_HPP
  7. #include <boost/config.hpp>
  8. #include <boost/scoped_array.hpp>
  9. #include <boost/functional/hash.hpp>
  10. #include <boost/multiprecision/number.hpp>
  11. #if defined(BOOST_INTEL) && !defined(BOOST_MP_USE_FLOAT128) && !defined(BOOST_MP_USE_QUAD)
  12. #if defined(BOOST_INTEL_CXX_VERSION) && (BOOST_INTEL_CXX_VERSION >= 1310) && defined(__GNUC__)
  13. #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6))
  14. #define BOOST_MP_USE_FLOAT128
  15. #endif
  16. #endif
  17. #ifndef BOOST_MP_USE_FLOAT128
  18. #define BOOST_MP_USE_QUAD
  19. #endif
  20. #endif
  21. #if defined(__GNUC__) && !defined(BOOST_MP_USE_FLOAT128) && !defined(BOOST_MP_USE_QUAD)
  22. #define BOOST_MP_USE_FLOAT128
  23. #endif
  24. #if !defined(BOOST_MP_USE_FLOAT128) && !defined(BOOST_MP_USE_QUAD)
  25. #error "Sorry compiler is neither GCC, not Intel, don't know how to configure this header."
  26. #endif
  27. #if defined(BOOST_MP_USE_FLOAT128) && defined(BOOST_MP_USE_QUAD)
  28. #error "Oh dear, both BOOST_MP_USE_FLOAT128 and BOOST_MP_USE_QUAD are defined, which one should I be using?"
  29. #endif
  30. #if defined(BOOST_MP_USE_FLOAT128)
  31. extern "C" {
  32. #include <quadmath.h>
  33. }
  34. typedef __float128 float128_type;
  35. #elif defined(BOOST_MP_USE_QUAD)
  36. #include <boost/multiprecision/detail/float_string_cvt.hpp>
  37. typedef _Quad float128_type;
  38. extern "C" {
  39. _Quad __ldexpq(_Quad, int);
  40. _Quad __frexpq(_Quad, int*);
  41. _Quad __fabsq(_Quad);
  42. _Quad __floorq(_Quad);
  43. _Quad __ceilq(_Quad);
  44. _Quad __sqrtq(_Quad);
  45. _Quad __truncq(_Quad);
  46. _Quad __expq(_Quad);
  47. _Quad __powq(_Quad, _Quad);
  48. _Quad __logq(_Quad);
  49. _Quad __log10q(_Quad);
  50. _Quad __sinq(_Quad);
  51. _Quad __cosq(_Quad);
  52. _Quad __tanq(_Quad);
  53. _Quad __asinq(_Quad);
  54. _Quad __acosq(_Quad);
  55. _Quad __atanq(_Quad);
  56. _Quad __sinhq(_Quad);
  57. _Quad __coshq(_Quad);
  58. _Quad __tanhq(_Quad);
  59. _Quad __fmodq(_Quad, _Quad);
  60. _Quad __atan2q(_Quad, _Quad);
  61. #define ldexpq __ldexpq
  62. #define frexpq __frexpq
  63. #define fabsq __fabsq
  64. #define floorq __floorq
  65. #define ceilq __ceilq
  66. #define sqrtq __sqrtq
  67. #define truncq __truncq
  68. #define expq __expq
  69. #define powq __powq
  70. #define logq __logq
  71. #define log10q __log10q
  72. #define sinq __sinq
  73. #define cosq __cosq
  74. #define tanq __tanq
  75. #define asinq __asinq
  76. #define acosq __acosq
  77. #define atanq __atanq
  78. #define sinhq __sinhq
  79. #define coshq __coshq
  80. #define tanhq __tanhq
  81. #define fmodq __fmodq
  82. #define atan2q __atan2q
  83. }
  84. inline _Quad isnanq(_Quad v)
  85. {
  86. return v != v;
  87. }
  88. inline _Quad isinfq(_Quad v)
  89. {
  90. return __fabsq(v) > 1.18973149535723176508575932662800702e4932Q;
  91. }
  92. #endif
  93. namespace boost {
  94. namespace multiprecision {
  95. #ifndef BOOST_MP_BITS_OF_FLOAT128_DEFINED
  96. namespace detail {
  97. template <>
  98. struct bits_of<float128_type>
  99. {
  100. static const unsigned value = 113;
  101. };
  102. }
  103. #endif
  104. namespace backends {
  105. struct float128_backend;
  106. }
  107. using backends::float128_backend;
  108. template <>
  109. struct number_category<backends::float128_backend> : public mpl::int_<number_kind_floating_point>
  110. {};
  111. #if defined(BOOST_MP_USE_QUAD)
  112. template <>
  113. struct number_category<float128_type> : public mpl::int_<number_kind_floating_point>
  114. {};
  115. #endif
  116. typedef number<float128_backend, et_off> float128;
  117. #ifndef BOOST_NO_CXX11_CONSTEXPR
  118. namespace quad_constants {
  119. constexpr __float128 quad_min = static_cast<__float128>(1) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) / 1073741824;
  120. constexpr __float128 quad_denorm_min = static_cast<__float128>(1) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) / 5.5751862996326557854e+42;
  121. constexpr double dbl_mult = 8.9884656743115795386e+307; // This has one bit set only.
  122. constexpr __float128 quad_max = (static_cast<__float128>(1) - 9.62964972193617926527988971292463659e-35) // This now has all bits sets to 1
  123. * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * 65536;
  124. } // namespace quad_constants
  125. #define BOOST_MP_QUAD_MIN boost::multiprecision::quad_constants::quad_min
  126. #define BOOST_MP_QUAD_DENORM_MIN boost::multiprecision::quad_constants::quad_denorm_min
  127. #define BOOST_MP_QUAD_MAX boost::multiprecision::quad_constants::quad_max
  128. #else
  129. #define BOOST_MP_QUAD_MIN 3.36210314311209350626267781732175260e-4932Q
  130. #define BOOST_MP_QUAD_DENORM_MIN 6.475175119438025110924438958227646552e-4966Q
  131. #define BOOST_MP_QUAD_MAX 1.18973149535723176508575932662800702e4932Q
  132. #endif
  133. namespace backends {
  134. struct float128_backend
  135. {
  136. typedef mpl::list<signed char, short, int, long, boost::long_long_type> signed_types;
  137. typedef mpl::list<unsigned char, unsigned short,
  138. unsigned int, unsigned long, boost::ulong_long_type>
  139. unsigned_types;
  140. typedef mpl::list<float, double, long double> float_types;
  141. typedef int exponent_type;
  142. private:
  143. float128_type m_value;
  144. public:
  145. BOOST_CONSTEXPR float128_backend() BOOST_NOEXCEPT : m_value(0) {}
  146. BOOST_CONSTEXPR float128_backend(const float128_backend& o) BOOST_NOEXCEPT : m_value(o.m_value) {}
  147. BOOST_MP_CXX14_CONSTEXPR float128_backend& operator=(const float128_backend& o) BOOST_NOEXCEPT
  148. {
  149. m_value = o.m_value;
  150. return *this;
  151. }
  152. template <class T>
  153. BOOST_CONSTEXPR float128_backend(const T& i, const typename enable_if_c<is_convertible<T, float128_type>::value>::type* = 0) BOOST_NOEXCEPT_IF(noexcept(std::declval<float128_type&>() = std::declval<const T&>()))
  154. : m_value(i) {}
  155. template <class T>
  156. BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_arithmetic<T>::value || is_convertible<T, float128_type>::value, float128_backend&>::type operator=(const T& i) BOOST_NOEXCEPT_IF(noexcept(std::declval<float128_type&>() = std::declval<const T&>()))
  157. {
  158. m_value = i;
  159. return *this;
  160. }
  161. BOOST_MP_CXX14_CONSTEXPR float128_backend(long double const& f) : m_value(f)
  162. {
  163. if (::fabsl(f) > LDBL_MAX)
  164. m_value = (f < 0) ? -static_cast<__float128>(HUGE_VAL) : static_cast<__float128>(HUGE_VAL);
  165. }
  166. BOOST_MP_CXX14_CONSTEXPR float128_backend& operator=(long double const& f)
  167. {
  168. if (f > LDBL_MAX)
  169. m_value = static_cast<__float128>(HUGE_VAL);
  170. else if (-f > LDBL_MAX)
  171. m_value = -static_cast<__float128>(HUGE_VAL);
  172. else
  173. m_value = f;
  174. return *this;
  175. }
  176. float128_backend& operator=(const char* s)
  177. {
  178. #ifndef BOOST_MP_USE_QUAD
  179. char* p_end;
  180. m_value = strtoflt128(s, &p_end);
  181. if (p_end - s != (std::ptrdiff_t)std::strlen(s))
  182. {
  183. BOOST_THROW_EXCEPTION(std::runtime_error("Unable to interpret input string as a floating point value"));
  184. }
  185. #else
  186. boost::multiprecision::detail::convert_from_string(*this, s);
  187. #endif
  188. return *this;
  189. }
  190. BOOST_MP_CXX14_CONSTEXPR void swap(float128_backend& o) BOOST_NOEXCEPT
  191. {
  192. // We don't call std::swap here because it's no constexpr (yet):
  193. float128_type t(o.value());
  194. o.value() = m_value;
  195. m_value = t;
  196. }
  197. std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
  198. {
  199. #ifndef BOOST_MP_USE_QUAD
  200. char buf[128];
  201. std::string format = "%";
  202. if (f & std::ios_base::showpos)
  203. format += "+";
  204. if (f & std::ios_base::showpoint)
  205. format += "#";
  206. format += ".*";
  207. if (digits == 0)
  208. digits = 36;
  209. format += "Q";
  210. if (f & std::ios_base::scientific)
  211. format += "e";
  212. else if (f & std::ios_base::fixed)
  213. format += "f";
  214. else
  215. format += "g";
  216. int v;
  217. if ((f & std::ios_base::scientific) && (f & std::ios_base::fixed))
  218. {
  219. v = quadmath_snprintf(buf, sizeof buf, "%Qa", m_value);
  220. }
  221. else
  222. {
  223. v = quadmath_snprintf(buf, sizeof buf, format.c_str(), digits, m_value);
  224. }
  225. if ((v < 0) || (v >= 127))
  226. {
  227. int v_max = v;
  228. boost::scoped_array<char> buf2;
  229. buf2.reset(new char[v + 3]);
  230. v = quadmath_snprintf(&buf2[0], v_max + 3, format.c_str(), digits, m_value);
  231. if (v >= v_max + 3)
  232. {
  233. BOOST_THROW_EXCEPTION(std::runtime_error("Formatting of float128_type failed."));
  234. }
  235. return &buf2[0];
  236. }
  237. return buf;
  238. #else
  239. return boost::multiprecision::detail::convert_to_string(*this, digits ? digits : 37, f);
  240. #endif
  241. }
  242. BOOST_MP_CXX14_CONSTEXPR void negate() BOOST_NOEXCEPT
  243. {
  244. m_value = -m_value;
  245. }
  246. BOOST_MP_CXX14_CONSTEXPR int compare(const float128_backend& o) const
  247. {
  248. return m_value == o.m_value ? 0 : m_value < o.m_value ? -1 : 1;
  249. }
  250. template <class T>
  251. BOOST_MP_CXX14_CONSTEXPR int compare(const T& i) const
  252. {
  253. return m_value == i ? 0 : m_value < i ? -1 : 1;
  254. }
  255. BOOST_MP_CXX14_CONSTEXPR float128_type& value()
  256. {
  257. return m_value;
  258. }
  259. BOOST_MP_CXX14_CONSTEXPR const float128_type& value() const
  260. {
  261. return m_value;
  262. }
  263. };
  264. inline BOOST_MP_CXX14_CONSTEXPR void eval_add(float128_backend& result, const float128_backend& a)
  265. {
  266. result.value() += a.value();
  267. }
  268. template <class A>
  269. inline BOOST_MP_CXX14_CONSTEXPR void eval_add(float128_backend& result, const A& a)
  270. {
  271. result.value() += a;
  272. }
  273. inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const float128_backend& a)
  274. {
  275. result.value() -= a.value();
  276. }
  277. template <class A>
  278. inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const A& a)
  279. {
  280. result.value() -= a;
  281. }
  282. inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(float128_backend& result, const float128_backend& a)
  283. {
  284. result.value() *= a.value();
  285. }
  286. template <class A>
  287. inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(float128_backend& result, const A& a)
  288. {
  289. result.value() *= a;
  290. }
  291. inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(float128_backend& result, const float128_backend& a)
  292. {
  293. result.value() /= a.value();
  294. }
  295. template <class A>
  296. inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(float128_backend& result, const A& a)
  297. {
  298. result.value() /= a;
  299. }
  300. inline BOOST_MP_CXX14_CONSTEXPR void eval_add(float128_backend& result, const float128_backend& a, const float128_backend& b)
  301. {
  302. result.value() = a.value() + b.value();
  303. }
  304. template <class A>
  305. inline BOOST_MP_CXX14_CONSTEXPR void eval_add(float128_backend& result, const float128_backend& a, const A& b)
  306. {
  307. result.value() = a.value() + b;
  308. }
  309. inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const float128_backend& a, const float128_backend& b)
  310. {
  311. result.value() = a.value() - b.value();
  312. }
  313. template <class A>
  314. inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const float128_backend& a, const A& b)
  315. {
  316. result.value() = a.value() - b;
  317. }
  318. template <class A>
  319. inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const A& a, const float128_backend& b)
  320. {
  321. result.value() = a - b.value();
  322. }
  323. inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(float128_backend& result, const float128_backend& a, const float128_backend& b)
  324. {
  325. result.value() = a.value() * b.value();
  326. }
  327. template <class A>
  328. inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(float128_backend& result, const float128_backend& a, const A& b)
  329. {
  330. result.value() = a.value() * b;
  331. }
  332. inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(float128_backend& result, const float128_backend& a, const float128_backend& b)
  333. {
  334. result.value() = a.value() / b.value();
  335. }
  336. template <class R>
  337. inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(R* result, const float128_backend& val)
  338. {
  339. *result = static_cast<R>(val.value());
  340. }
  341. inline void eval_frexp(float128_backend& result, const float128_backend& arg, int* exp)
  342. {
  343. result.value() = frexpq(arg.value(), exp);
  344. }
  345. inline void eval_ldexp(float128_backend& result, const float128_backend& arg, int exp)
  346. {
  347. result.value() = ldexpq(arg.value(), exp);
  348. }
  349. inline void eval_floor(float128_backend& result, const float128_backend& arg)
  350. {
  351. result.value() = floorq(arg.value());
  352. }
  353. inline void eval_ceil(float128_backend& result, const float128_backend& arg)
  354. {
  355. result.value() = ceilq(arg.value());
  356. }
  357. inline void eval_sqrt(float128_backend& result, const float128_backend& arg)
  358. {
  359. result.value() = sqrtq(arg.value());
  360. }
  361. #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
  362. inline BOOST_MP_CXX14_CONSTEXPR
  363. #else
  364. inline
  365. #endif
  366. int eval_fpclassify(const float128_backend& arg)
  367. {
  368. float128_type v = arg.value();
  369. #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
  370. if (BOOST_MP_IS_CONST_EVALUATED(v))
  371. {
  372. if (v != v)
  373. return FP_NAN;
  374. if (v == 0)
  375. return FP_ZERO;
  376. float128_type t(v);
  377. if (t < 0)
  378. t = -t;
  379. if (t > BOOST_MP_QUAD_MAX)
  380. return FP_INFINITE;
  381. if (t < BOOST_MP_QUAD_MIN)
  382. return FP_SUBNORMAL;
  383. return FP_NORMAL;
  384. }
  385. else
  386. #endif
  387. {
  388. if (isnanq(v))
  389. return FP_NAN;
  390. else if (isinfq(v))
  391. return FP_INFINITE;
  392. else if (v == 0)
  393. return FP_ZERO;
  394. float128_backend t(arg);
  395. if (t.value() < 0)
  396. t.negate();
  397. if (t.value() < BOOST_MP_QUAD_MIN)
  398. return FP_SUBNORMAL;
  399. return FP_NORMAL;
  400. }
  401. }
  402. #if defined(BOOST_GCC) && (__GNUC__ == 9)
  403. // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91705
  404. inline BOOST_MP_CXX14_CONSTEXPR void eval_increment(float128_backend& arg)
  405. {
  406. arg.value() = 1 + arg.value();
  407. }
  408. inline BOOST_MP_CXX14_CONSTEXPR void eval_decrement(float128_backend& arg)
  409. {
  410. arg.value() = arg.value() - 1;
  411. }
  412. #else
  413. inline BOOST_MP_CXX14_CONSTEXPR void eval_increment(float128_backend& arg)
  414. {
  415. ++arg.value();
  416. }
  417. inline BOOST_MP_CXX14_CONSTEXPR void eval_decrement(float128_backend& arg)
  418. {
  419. --arg.value();
  420. }
  421. #endif
  422. /*********************************************************************
  423. *
  424. * abs/fabs:
  425. *
  426. *********************************************************************/
  427. #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
  428. inline BOOST_MP_CXX14_CONSTEXPR void eval_abs(float128_backend& result, const float128_backend& arg)
  429. #else
  430. inline void eval_abs(float128_backend& result, const float128_backend& arg)
  431. #endif
  432. {
  433. float128_type v(arg.value());
  434. #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
  435. if (BOOST_MP_IS_CONST_EVALUATED(v))
  436. {
  437. result.value() = v < 0 ? -v : v;
  438. }
  439. else
  440. #endif
  441. {
  442. result.value() = fabsq(arg.value());
  443. }
  444. }
  445. #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
  446. inline BOOST_MP_CXX14_CONSTEXPR void eval_fabs(float128_backend& result, const float128_backend& arg)
  447. #else
  448. inline void eval_fabs(float128_backend& result, const float128_backend& arg)
  449. #endif
  450. {
  451. float128_type v(arg.value());
  452. #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
  453. if (BOOST_MP_IS_CONST_EVALUATED(v))
  454. {
  455. result.value() = v < 0 ? -v : v;
  456. }
  457. else
  458. #endif
  459. {
  460. result.value() = fabsq(arg.value());
  461. }
  462. }
  463. /*********************************************************************
  464. *
  465. * Floating point functions:
  466. *
  467. *********************************************************************/
  468. inline void eval_trunc(float128_backend& result, const float128_backend& arg)
  469. {
  470. result.value() = truncq(arg.value());
  471. }
  472. /*
  473. //
  474. // This doesn't actually work... rely on our own default version instead.
  475. //
  476. inline void eval_round(float128_backend& result, const float128_backend& arg)
  477. {
  478. if(isnanq(arg.value()) || isinf(arg.value()))
  479. {
  480. result = boost::math::policies::raise_rounding_error(
  481. "boost::multiprecision::trunc<%1%>(%1%)", 0,
  482. number<float128_backend, et_off>(arg),
  483. number<float128_backend, et_off>(arg),
  484. boost::math::policies::policy<>()).backend();
  485. return;
  486. }
  487. result.value() = roundq(arg.value());
  488. }
  489. */
  490. inline void eval_exp(float128_backend& result, const float128_backend& arg)
  491. {
  492. result.value() = expq(arg.value());
  493. }
  494. inline void eval_log(float128_backend& result, const float128_backend& arg)
  495. {
  496. result.value() = logq(arg.value());
  497. }
  498. inline void eval_log10(float128_backend& result, const float128_backend& arg)
  499. {
  500. result.value() = log10q(arg.value());
  501. }
  502. inline void eval_sin(float128_backend& result, const float128_backend& arg)
  503. {
  504. result.value() = sinq(arg.value());
  505. }
  506. inline void eval_cos(float128_backend& result, const float128_backend& arg)
  507. {
  508. result.value() = cosq(arg.value());
  509. }
  510. inline void eval_tan(float128_backend& result, const float128_backend& arg)
  511. {
  512. result.value() = tanq(arg.value());
  513. }
  514. inline void eval_asin(float128_backend& result, const float128_backend& arg)
  515. {
  516. result.value() = asinq(arg.value());
  517. }
  518. inline void eval_acos(float128_backend& result, const float128_backend& arg)
  519. {
  520. result.value() = acosq(arg.value());
  521. }
  522. inline void eval_atan(float128_backend& result, const float128_backend& arg)
  523. {
  524. result.value() = atanq(arg.value());
  525. }
  526. inline void eval_sinh(float128_backend& result, const float128_backend& arg)
  527. {
  528. result.value() = sinhq(arg.value());
  529. }
  530. inline void eval_cosh(float128_backend& result, const float128_backend& arg)
  531. {
  532. result.value() = coshq(arg.value());
  533. }
  534. inline void eval_tanh(float128_backend& result, const float128_backend& arg)
  535. {
  536. result.value() = tanhq(arg.value());
  537. }
  538. inline void eval_fmod(float128_backend& result, const float128_backend& a, const float128_backend& b)
  539. {
  540. result.value() = fmodq(a.value(), b.value());
  541. }
  542. inline void eval_pow(float128_backend& result, const float128_backend& a, const float128_backend& b)
  543. {
  544. result.value() = powq(a.value(), b.value());
  545. }
  546. inline void eval_atan2(float128_backend& result, const float128_backend& a, const float128_backend& b)
  547. {
  548. result.value() = atan2q(a.value(), b.value());
  549. }
  550. #ifndef BOOST_MP_USE_QUAD
  551. inline void eval_multiply_add(float128_backend& result, const float128_backend& a, const float128_backend& b, const float128_backend& c)
  552. {
  553. result.value() = fmaq(a.value(), b.value(), c.value());
  554. }
  555. inline int eval_signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const float128_backend& arg)
  556. {
  557. return ::signbitq(arg.value());
  558. }
  559. #endif
  560. inline std::size_t hash_value(const float128_backend& val)
  561. {
  562. return boost::hash_value(static_cast<double>(val.value()));
  563. }
  564. } // namespace backends
  565. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  566. inline boost::multiprecision::number<float128_backend, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
  567. {
  568. return asinhq(arg.backend().value());
  569. }
  570. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  571. inline boost::multiprecision::number<float128_backend, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
  572. {
  573. return acoshq(arg.backend().value());
  574. }
  575. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  576. inline boost::multiprecision::number<float128_backend, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
  577. {
  578. return atanhq(arg.backend().value());
  579. }
  580. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  581. inline boost::multiprecision::number<float128_backend, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
  582. {
  583. return cbrtq(arg.backend().value());
  584. }
  585. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  586. inline boost::multiprecision::number<float128_backend, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
  587. {
  588. return erfq(arg.backend().value());
  589. }
  590. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  591. inline boost::multiprecision::number<float128_backend, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
  592. {
  593. return erfcq(arg.backend().value());
  594. }
  595. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  596. inline boost::multiprecision::number<float128_backend, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
  597. {
  598. return expm1q(arg.backend().value());
  599. }
  600. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  601. inline boost::multiprecision::number<float128_backend, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
  602. {
  603. return lgammaq(arg.backend().value());
  604. }
  605. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  606. inline boost::multiprecision::number<float128_backend, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
  607. {
  608. if(eval_signbit(arg.backend()) != 0)
  609. {
  610. const bool result_is_neg = ((static_cast<unsigned long long>(floorq(-arg.backend().value())) % 2U) == 0U);
  611. const boost::multiprecision::number<float128_backend, ExpressionTemplates> result_of_tgammaq = fabsq(tgammaq(arg.backend().value()));
  612. return ((result_is_neg == false) ? result_of_tgammaq : -result_of_tgammaq);
  613. }
  614. else
  615. {
  616. return tgammaq(arg.backend().value());
  617. }
  618. }
  619. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  620. inline boost::multiprecision::number<float128_backend, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
  621. {
  622. return log1pq(arg.backend().value());
  623. }
  624. #ifndef BOOST_MP_USE_QUAD
  625. template <multiprecision::expression_template_option ExpressionTemplates>
  626. inline boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>& a, const boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>& b)
  627. {
  628. return ::copysignq(a.backend().value(), b.backend().value());
  629. }
  630. inline void eval_remainder(float128_backend& result, const float128_backend& a, const float128_backend& b)
  631. {
  632. result.value() = remainderq(a.value(), b.value());
  633. }
  634. inline void eval_remainder(float128_backend& result, const float128_backend& a, const float128_backend& b, int* pi)
  635. {
  636. result.value() = remquoq(a.value(), b.value(), pi);
  637. }
  638. #endif
  639. } // namespace multiprecision
  640. namespace math {
  641. using boost::multiprecision::copysign;
  642. using boost::multiprecision::signbit;
  643. } // namespace math
  644. } // namespace boost
  645. namespace boost {
  646. namespace archive {
  647. class binary_oarchive;
  648. class binary_iarchive;
  649. } // namespace archive
  650. namespace serialization {
  651. namespace float128_detail {
  652. template <class Archive>
  653. void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const mpl::false_&, const mpl::false_&)
  654. {
  655. // saving
  656. // non-binary
  657. std::string s(val.str(0, std::ios_base::scientific));
  658. ar& boost::make_nvp("value", s);
  659. }
  660. template <class Archive>
  661. void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const mpl::true_&, const mpl::false_&)
  662. {
  663. // loading
  664. // non-binary
  665. std::string s;
  666. ar& boost::make_nvp("value", s);
  667. val = s.c_str();
  668. }
  669. template <class Archive>
  670. void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const mpl::false_&, const mpl::true_&)
  671. {
  672. // saving
  673. // binary
  674. ar.save_binary(&val, sizeof(val));
  675. }
  676. template <class Archive>
  677. void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const mpl::true_&, const mpl::true_&)
  678. {
  679. // loading
  680. // binary
  681. ar.load_binary(&val, sizeof(val));
  682. }
  683. } // namespace float128_detail
  684. template <class Archive>
  685. void serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, unsigned int /*version*/)
  686. {
  687. typedef typename Archive::is_loading load_tag;
  688. typedef typename mpl::bool_<boost::is_same<Archive, boost::archive::binary_oarchive>::value || boost::is_same<Archive, boost::archive::binary_iarchive>::value> binary_tag;
  689. float128_detail::do_serialize(ar, val, load_tag(), binary_tag());
  690. }
  691. } // namespace serialization
  692. } // namespace boost
  693. namespace std {
  694. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  695. class numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >
  696. {
  697. typedef boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> number_type;
  698. public:
  699. BOOST_STATIC_CONSTEXPR bool is_specialized = true;
  700. static BOOST_MP_CXX14_CONSTEXPR number_type(min)() BOOST_NOEXCEPT { return BOOST_MP_QUAD_MIN; }
  701. static BOOST_MP_CXX14_CONSTEXPR number_type(max)() BOOST_NOEXCEPT { return BOOST_MP_QUAD_MAX; }
  702. static BOOST_MP_CXX14_CONSTEXPR number_type lowest() BOOST_NOEXCEPT { return -(max)(); }
  703. BOOST_STATIC_CONSTEXPR int digits = 113;
  704. BOOST_STATIC_CONSTEXPR int digits10 = 33;
  705. BOOST_STATIC_CONSTEXPR int max_digits10 = 36;
  706. BOOST_STATIC_CONSTEXPR bool is_signed = true;
  707. BOOST_STATIC_CONSTEXPR bool is_integer = false;
  708. BOOST_STATIC_CONSTEXPR bool is_exact = false;
  709. BOOST_STATIC_CONSTEXPR int radix = 2;
  710. static BOOST_MP_CXX14_CONSTEXPR number_type epsilon() { return 1.92592994438723585305597794258492732e-34; /* this double value has only one bit set and so is exact */ }
  711. static BOOST_MP_CXX14_CONSTEXPR number_type round_error() { return 0.5; }
  712. BOOST_STATIC_CONSTEXPR int min_exponent = -16381;
  713. BOOST_STATIC_CONSTEXPR int min_exponent10 = min_exponent * 301L / 1000L;
  714. BOOST_STATIC_CONSTEXPR int max_exponent = 16384;
  715. BOOST_STATIC_CONSTEXPR int max_exponent10 = max_exponent * 301L / 1000L;
  716. BOOST_STATIC_CONSTEXPR bool has_infinity = true;
  717. BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true;
  718. BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
  719. BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_present;
  720. BOOST_STATIC_CONSTEXPR bool has_denorm_loss = true;
  721. static BOOST_MP_CXX14_CONSTEXPR number_type infinity() { return HUGE_VAL; /* conversion from double infinity OK */ }
  722. static BOOST_MP_CXX14_CONSTEXPR number_type quiet_NaN() { return number_type("nan"); }
  723. static BOOST_MP_CXX14_CONSTEXPR number_type signaling_NaN() { return 0; }
  724. static BOOST_MP_CXX14_CONSTEXPR number_type denorm_min() { return BOOST_MP_QUAD_DENORM_MIN; }
  725. BOOST_STATIC_CONSTEXPR bool is_iec559 = true;
  726. BOOST_STATIC_CONSTEXPR bool is_bounded = true;
  727. BOOST_STATIC_CONSTEXPR bool is_modulo = false;
  728. BOOST_STATIC_CONSTEXPR bool traps = false;
  729. BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
  730. BOOST_STATIC_CONSTEXPR float_round_style round_style = round_to_nearest;
  731. };
  732. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  733. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_specialized;
  734. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  735. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::digits;
  736. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  737. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::digits10;
  738. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  739. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::max_digits10;
  740. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  741. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_signed;
  742. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  743. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_integer;
  744. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  745. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_exact;
  746. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  747. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::radix;
  748. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  749. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::min_exponent;
  750. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  751. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::max_exponent;
  752. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  753. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::min_exponent10;
  754. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  755. BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::max_exponent10;
  756. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  757. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_infinity;
  758. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  759. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_quiet_NaN;
  760. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  761. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_signaling_NaN;
  762. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  763. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_denorm_loss;
  764. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  765. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_iec559;
  766. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  767. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_bounded;
  768. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  769. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_modulo;
  770. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  771. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::traps;
  772. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  773. BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::tinyness_before;
  774. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  775. BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::round_style;
  776. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  777. BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_denorm;
  778. } // namespace std
  779. #endif