float128.hpp 35 KB

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