float128.hpp 37 KB

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