arithmetic_backend.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. ///////////////////////////////////////////////////////////////
  2. // Copyright 2012 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_MATH_FLOAT_BACKEND_HPP
  6. #define BOOST_MATH_FLOAT_BACKEND_HPP
  7. #include <iostream>
  8. #include <iomanip>
  9. #include <sstream>
  10. #include <boost/cstdint.hpp>
  11. #include <boost/lexical_cast.hpp>
  12. #include <boost/math/concepts/real_concept.hpp>
  13. #include <boost/multiprecision/number.hpp>
  14. #include <boost/integer/common_factor_rt.hpp>
  15. #include <boost/type_traits/common_type.hpp>
  16. #include <boost/container_hash/hash.hpp>
  17. namespace boost {
  18. namespace multiprecision {
  19. namespace backends {
  20. #ifdef BOOST_MSVC
  21. #pragma warning(push)
  22. #pragma warning(disable : 4389 4244 4018 4244 4127)
  23. #endif
  24. template <class Arithmetic>
  25. struct arithmetic_backend
  26. {
  27. typedef mpl::list<short, int, long, long long> signed_types;
  28. typedef mpl::list<unsigned short, unsigned, unsigned long, unsigned long long> unsigned_types;
  29. typedef mpl::list<float, double, long double> float_types;
  30. typedef int exponent_type;
  31. BOOST_MP_CXX14_CONSTEXPR arithmetic_backend() : m_value(0) {}
  32. BOOST_MP_CXX14_CONSTEXPR arithmetic_backend(const arithmetic_backend& o) : m_value(o.m_value) {}
  33. template <class A>
  34. BOOST_MP_CXX14_CONSTEXPR arithmetic_backend(const A& o, const typename enable_if<is_arithmetic<A> >::type* = 0) : m_value(o) {}
  35. template <class A>
  36. BOOST_MP_CXX14_CONSTEXPR arithmetic_backend(const arithmetic_backend<A>& o) : m_value(o.data()) {}
  37. BOOST_MP_CXX14_CONSTEXPR arithmetic_backend& operator=(const arithmetic_backend& o)
  38. {
  39. m_value = o.m_value;
  40. return *this;
  41. }
  42. template <class A>
  43. BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A>, arithmetic_backend&>::type operator=(A i)
  44. {
  45. m_value = i;
  46. return *this;
  47. }
  48. template <class A>
  49. BOOST_MP_CXX14_CONSTEXPR arithmetic_backend& operator=(const arithmetic_backend<A>& i)
  50. {
  51. m_value = i.data();
  52. return *this;
  53. }
  54. arithmetic_backend& operator=(const char* s)
  55. {
  56. #ifndef BOOST_NO_EXCEPTIONS
  57. try
  58. {
  59. #endif
  60. m_value = boost::lexical_cast<Arithmetic>(s);
  61. #ifndef BOOST_NO_EXCEPTIONS
  62. }
  63. catch (const bad_lexical_cast&)
  64. {
  65. throw std::runtime_error(std::string("Unable to interpret the string provided: \"") + s + std::string("\" as a compatible number type."));
  66. }
  67. #endif
  68. return *this;
  69. }
  70. BOOST_MP_CXX14_CONSTEXPR void swap(arithmetic_backend& o)
  71. {
  72. std::swap(m_value, o.m_value);
  73. }
  74. std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
  75. {
  76. std::stringstream ss;
  77. ss.flags(f);
  78. ss << std::setprecision(digits ? digits : std::numeric_limits<Arithmetic>::digits10 + 4) << m_value;
  79. return ss.str();
  80. }
  81. BOOST_MP_CXX14_CONSTEXPR void do_negate(const mpl::true_&)
  82. {
  83. m_value = 1 + ~m_value;
  84. }
  85. BOOST_MP_CXX14_CONSTEXPR void do_negate(const mpl::false_&)
  86. {
  87. m_value = -m_value;
  88. }
  89. BOOST_MP_CXX14_CONSTEXPR void negate()
  90. {
  91. do_negate(mpl::bool_<is_unsigned<Arithmetic>::value>());
  92. }
  93. BOOST_MP_CXX14_CONSTEXPR int compare(const arithmetic_backend& o) const
  94. {
  95. return m_value > o.m_value ? 1 : (m_value < o.m_value ? -1 : 0);
  96. }
  97. template <class A>
  98. BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A>, int>::type compare(A i) const
  99. {
  100. return m_value > static_cast<Arithmetic>(i) ? 1 : (m_value < static_cast<Arithmetic>(i) ? -1 : 0);
  101. }
  102. BOOST_MP_CXX14_CONSTEXPR Arithmetic& data() { return m_value; }
  103. BOOST_MP_CXX14_CONSTEXPR const Arithmetic& data() const { return m_value; }
  104. private:
  105. Arithmetic m_value;
  106. };
  107. template <class R, class Arithmetic>
  108. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<boost::is_integral<R>::value>::type eval_convert_to(R* result, const arithmetic_backend<Arithmetic>& backend)
  109. {
  110. typedef typename boost::common_type<R, Arithmetic>::type c_type;
  111. BOOST_CONSTEXPR const c_type max = static_cast<c_type>((std::numeric_limits<R>::max)());
  112. BOOST_CONSTEXPR const c_type min = static_cast<c_type>((std::numeric_limits<R>::min)());
  113. c_type ct = static_cast<c_type>(backend.data());
  114. if ((backend.data() < 0) && !std::numeric_limits<R>::is_signed)
  115. BOOST_THROW_EXCEPTION(std::range_error("Attempt to convert negative number to unsigned type."));
  116. if (ct > max)
  117. *result = boost::is_signed<R>::value ? (std::numeric_limits<R>::max)() : backend.data();
  118. else if (std::numeric_limits<Arithmetic>::is_signed && (ct < min))
  119. *result = (std::numeric_limits<R>::min)();
  120. else
  121. *result = backend.data();
  122. }
  123. template <class R, class Arithmetic>
  124. inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<boost::is_integral<R>::value>::type eval_convert_to(R* result, const arithmetic_backend<Arithmetic>& backend)
  125. {
  126. *result = backend.data();
  127. }
  128. template <class Arithmetic>
  129. inline BOOST_MP_CXX14_CONSTEXPR bool eval_eq(const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
  130. {
  131. return a.data() == b.data();
  132. }
  133. template <class Arithmetic, class A2>
  134. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2>, bool>::type eval_eq(const arithmetic_backend<Arithmetic>& a, const A2& b)
  135. {
  136. return a.data() == static_cast<Arithmetic>(b);
  137. }
  138. template <class Arithmetic>
  139. inline BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
  140. {
  141. return a.data() < b.data();
  142. }
  143. template <class Arithmetic, class A2>
  144. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2>, bool>::type eval_lt(const arithmetic_backend<Arithmetic>& a, const A2& b)
  145. {
  146. return a.data() < static_cast<Arithmetic>(b);
  147. }
  148. template <class Arithmetic>
  149. inline BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
  150. {
  151. return a.data() > b.data();
  152. }
  153. template <class Arithmetic, class A2>
  154. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2>, bool>::type eval_gt(const arithmetic_backend<Arithmetic>& a, const A2& b)
  155. {
  156. return a.data() > static_cast<Arithmetic>(b);
  157. }
  158. template <class Arithmetic>
  159. inline BOOST_MP_CXX14_CONSTEXPR void eval_add(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  160. {
  161. result.data() += o.data();
  162. }
  163. template <class Arithmetic>
  164. inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  165. {
  166. result.data() -= o.data();
  167. }
  168. template <class Arithmetic>
  169. inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  170. {
  171. result.data() *= o.data();
  172. }
  173. template <class Arithmetic>
  174. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<std::numeric_limits<Arithmetic>::has_infinity>::type eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  175. {
  176. result.data() /= o.data();
  177. }
  178. template <class Arithmetic>
  179. inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<std::numeric_limits<Arithmetic>::has_infinity>::type eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  180. {
  181. if (!o.data())
  182. BOOST_THROW_EXCEPTION(std::overflow_error("Divide by zero"));
  183. result.data() /= o.data();
  184. }
  185. template <class Arithmetic, class A2>
  186. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_add(arithmetic_backend<Arithmetic>& result, const A2& o)
  187. {
  188. result.data() += o;
  189. }
  190. template <class Arithmetic, class A2>
  191. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_subtract(arithmetic_backend<Arithmetic>& result, const A2& o)
  192. {
  193. result.data() -= o;
  194. }
  195. template <class Arithmetic, class A2>
  196. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_multiply(arithmetic_backend<Arithmetic>& result, const A2& o)
  197. {
  198. result.data() *= o;
  199. }
  200. template <class Arithmetic, class A2>
  201. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(is_arithmetic<A2>::value && !std::numeric_limits<Arithmetic>::has_infinity)>::type
  202. eval_divide(arithmetic_backend<Arithmetic>& result, const A2& o)
  203. {
  204. if (!o)
  205. BOOST_THROW_EXCEPTION(std::overflow_error("Divide by zero"));
  206. result.data() /= o;
  207. }
  208. template <class Arithmetic, class A2>
  209. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(is_arithmetic<A2>::value && std::numeric_limits<Arithmetic>::has_infinity)>::type
  210. eval_divide(arithmetic_backend<Arithmetic>& result, const A2& o)
  211. {
  212. result.data() /= o;
  213. }
  214. template <class Arithmetic>
  215. inline BOOST_MP_CXX14_CONSTEXPR void eval_add(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
  216. {
  217. result.data() = a.data() + b.data();
  218. }
  219. template <class Arithmetic>
  220. inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
  221. {
  222. result.data() = a.data() - b.data();
  223. }
  224. template <class Arithmetic>
  225. inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
  226. {
  227. result.data() = a.data() * b.data();
  228. }
  229. template <class Arithmetic>
  230. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<std::numeric_limits<Arithmetic>::has_infinity>::type eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
  231. {
  232. result.data() = a.data() / b.data();
  233. }
  234. template <class Arithmetic>
  235. inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<std::numeric_limits<Arithmetic>::has_infinity>::type eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
  236. {
  237. if (!b.data())
  238. BOOST_THROW_EXCEPTION(std::overflow_error("Divide by zero"));
  239. result.data() = a.data() / b.data();
  240. }
  241. template <class Arithmetic, class A2>
  242. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_add(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const A2& b)
  243. {
  244. result.data() = a.data() + b;
  245. }
  246. template <class Arithmetic, class A2>
  247. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_subtract(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const A2& b)
  248. {
  249. result.data() = a.data() - b;
  250. }
  251. template <class Arithmetic, class A2>
  252. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_multiply(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const A2& b)
  253. {
  254. result.data() = a.data() * b;
  255. }
  256. template <class Arithmetic, class A2>
  257. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(is_arithmetic<A2>::value && !std::numeric_limits<Arithmetic>::has_infinity)>::type
  258. eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const A2& b)
  259. {
  260. if (!b)
  261. BOOST_THROW_EXCEPTION(std::overflow_error("Divide by zero"));
  262. result.data() = a.data() / b;
  263. }
  264. template <class Arithmetic, class A2>
  265. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(is_arithmetic<A2>::value && std::numeric_limits<Arithmetic>::has_infinity)>::type
  266. eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const A2& b)
  267. {
  268. result.data() = a.data() / b;
  269. }
  270. template <class Arithmetic>
  271. inline BOOST_MP_CXX14_CONSTEXPR bool eval_is_zero(const arithmetic_backend<Arithmetic>& val)
  272. {
  273. return val.data() == 0;
  274. }
  275. template <class Arithmetic>
  276. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
  277. (!std::numeric_limits<Arithmetic>::is_specialized || std::numeric_limits<Arithmetic>::is_signed), int>::type
  278. eval_get_sign(const arithmetic_backend<Arithmetic>& val)
  279. {
  280. return val.data() == 0 ? 0 : val.data() < 0 ? -1 : 1;
  281. }
  282. template <class Arithmetic>
  283. inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<
  284. (std::numeric_limits<Arithmetic>::is_specialized || std::numeric_limits<Arithmetic>::is_signed), int>::type
  285. eval_get_sign(const arithmetic_backend<Arithmetic>& val)
  286. {
  287. return val.data() == 0 ? 0 : 1;
  288. }
  289. template <class T>
  290. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_unsigned<T>, T>::type abs(T v) { return v; }
  291. template <class Arithmetic>
  292. inline BOOST_MP_CXX14_CONSTEXPR void eval_abs(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  293. {
  294. using boost::multiprecision::backends::abs;
  295. using std::abs;
  296. result.data() = abs(o.data());
  297. }
  298. template <class Arithmetic>
  299. inline BOOST_MP_CXX14_CONSTEXPR void eval_fabs(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  300. {
  301. result.data() = std::abs(o.data());
  302. }
  303. template <class Arithmetic>
  304. inline BOOST_MP_CXX14_CONSTEXPR void eval_floor(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  305. {
  306. BOOST_MATH_STD_USING
  307. result.data() = floor(o.data());
  308. }
  309. template <class Arithmetic>
  310. inline BOOST_MP_CXX14_CONSTEXPR void eval_ceil(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  311. {
  312. BOOST_MATH_STD_USING
  313. result.data() = ceil(o.data());
  314. }
  315. template <class Arithmetic>
  316. inline BOOST_MP_CXX14_CONSTEXPR void eval_sqrt(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  317. {
  318. BOOST_MATH_STD_USING
  319. result.data() = sqrt(o.data());
  320. }
  321. template <class Arithmetic>
  322. inline BOOST_MP_CXX14_CONSTEXPR int eval_fpclassify(const arithmetic_backend<Arithmetic>& o)
  323. {
  324. return (boost::math::fpclassify)(o.data());
  325. }
  326. template <class Arithmetic>
  327. inline BOOST_MP_CXX14_CONSTEXPR void eval_trunc(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  328. {
  329. BOOST_MATH_STD_USING
  330. result.data() = trunc(o.data());
  331. }
  332. template <class Arithmetic>
  333. inline BOOST_MP_CXX14_CONSTEXPR void eval_round(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  334. {
  335. BOOST_MATH_STD_USING
  336. result.data() = round(o.data());
  337. }
  338. template <class Arithmetic>
  339. inline BOOST_MP_CXX14_CONSTEXPR void eval_frexp(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, int* v)
  340. {
  341. BOOST_MATH_STD_USING
  342. result.data() = frexp(a.data(), v);
  343. }
  344. template <class Arithmetic>
  345. inline BOOST_MP_CXX14_CONSTEXPR void eval_ldexp(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, int v)
  346. {
  347. BOOST_MATH_STD_USING
  348. result.data() = ldexp(a.data(), v);
  349. }
  350. template <class Arithmetic>
  351. inline BOOST_MP_CXX14_CONSTEXPR void eval_exp(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  352. {
  353. BOOST_MATH_STD_USING
  354. result.data() = exp(o.data());
  355. }
  356. template <class Arithmetic>
  357. inline BOOST_MP_CXX14_CONSTEXPR void eval_log(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  358. {
  359. BOOST_MATH_STD_USING
  360. result.data() = log(o.data());
  361. }
  362. template <class Arithmetic>
  363. inline BOOST_MP_CXX14_CONSTEXPR void eval_log10(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  364. {
  365. BOOST_MATH_STD_USING
  366. result.data() = log10(o.data());
  367. }
  368. template <class Arithmetic>
  369. inline BOOST_MP_CXX14_CONSTEXPR void eval_sin(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  370. {
  371. BOOST_MATH_STD_USING
  372. result.data() = sin(o.data());
  373. }
  374. template <class Arithmetic>
  375. inline BOOST_MP_CXX14_CONSTEXPR void eval_cos(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  376. {
  377. BOOST_MATH_STD_USING
  378. result.data() = cos(o.data());
  379. }
  380. template <class Arithmetic>
  381. inline BOOST_MP_CXX14_CONSTEXPR void eval_tan(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  382. {
  383. BOOST_MATH_STD_USING
  384. result.data() = tan(o.data());
  385. }
  386. template <class Arithmetic>
  387. inline BOOST_MP_CXX14_CONSTEXPR void eval_acos(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  388. {
  389. BOOST_MATH_STD_USING
  390. result.data() = acos(o.data());
  391. }
  392. template <class Arithmetic>
  393. inline BOOST_MP_CXX14_CONSTEXPR void eval_asin(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  394. {
  395. BOOST_MATH_STD_USING
  396. result.data() = asin(o.data());
  397. }
  398. template <class Arithmetic>
  399. inline BOOST_MP_CXX14_CONSTEXPR void eval_atan(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  400. {
  401. BOOST_MATH_STD_USING
  402. result.data() = atan(o.data());
  403. }
  404. template <class Arithmetic>
  405. inline BOOST_MP_CXX14_CONSTEXPR void eval_sinh(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  406. {
  407. BOOST_MATH_STD_USING
  408. result.data() = sinh(o.data());
  409. }
  410. template <class Arithmetic>
  411. inline BOOST_MP_CXX14_CONSTEXPR void eval_cosh(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  412. {
  413. BOOST_MATH_STD_USING
  414. result.data() = cosh(o.data());
  415. }
  416. template <class Arithmetic>
  417. inline BOOST_MP_CXX14_CONSTEXPR void eval_tanh(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
  418. {
  419. BOOST_MATH_STD_USING
  420. result.data() = tanh(o.data());
  421. }
  422. template <class Arithmetic>
  423. inline BOOST_MP_CXX14_CONSTEXPR void eval_fmod(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
  424. {
  425. BOOST_MATH_STD_USING
  426. result.data() = fmod(a.data(), b.data());
  427. }
  428. template <class Arithmetic>
  429. inline BOOST_MP_CXX14_CONSTEXPR void eval_pow(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
  430. {
  431. BOOST_MATH_STD_USING
  432. result.data() = pow(a.data(), b.data());
  433. }
  434. template <class Arithmetic>
  435. inline BOOST_MP_CXX14_CONSTEXPR void eval_atan2(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
  436. {
  437. BOOST_MATH_STD_USING
  438. result.data() = atan2(a.data(), b.data());
  439. }
  440. template <class Arithmetic, class I>
  441. inline BOOST_MP_CXX14_CONSTEXPR void eval_left_shift(arithmetic_backend<Arithmetic>& result, I val)
  442. {
  443. result.data() <<= val;
  444. }
  445. template <class Arithmetic, class I>
  446. inline BOOST_MP_CXX14_CONSTEXPR void eval_right_shift(arithmetic_backend<Arithmetic>& result, I val)
  447. {
  448. result.data() >>= val;
  449. }
  450. template <class Arithmetic>
  451. inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a)
  452. {
  453. result.data() %= a.data();
  454. }
  455. template <class Arithmetic>
  456. inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a)
  457. {
  458. result.data() &= a.data();
  459. }
  460. template <class Arithmetic>
  461. inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a)
  462. {
  463. result.data() |= a.data();
  464. }
  465. template <class Arithmetic>
  466. inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a)
  467. {
  468. result.data() ^= a.data();
  469. }
  470. template <class Arithmetic>
  471. inline BOOST_MP_CXX14_CONSTEXPR void eval_complement(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a)
  472. {
  473. result.data() = ~a.data();
  474. }
  475. template <class Arithmetic>
  476. inline BOOST_MP_CXX14_CONSTEXPR void eval_gcd(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
  477. {
  478. result.data() = boost::integer::gcd(a.data(), b.data());
  479. }
  480. template <class Arithmetic>
  481. inline BOOST_MP_CXX14_CONSTEXPR void eval_lcm(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
  482. {
  483. result.data() = boost::integer::lcm(a.data(), b.data());
  484. }
  485. template <class Arithmetic>
  486. inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const arithmetic_backend<Arithmetic>& a)
  487. {
  488. boost::hash<Arithmetic> hasher;
  489. return hasher(a.data());
  490. }
  491. #ifdef BOOST_MSVC
  492. #pragma warning(pop)
  493. #endif
  494. } // namespace backends
  495. using boost::multiprecision::backends::arithmetic_backend;
  496. template <class Arithmetic>
  497. struct number_category<arithmetic_backend<Arithmetic> > : public mpl::int_<is_integral<Arithmetic>::value ? number_kind_integer : number_kind_floating_point>
  498. {};
  499. namespace detail {
  500. template <class Backend>
  501. struct double_precision_type;
  502. template <class Arithmetic, boost::multiprecision::expression_template_option ET>
  503. struct double_precision_type<number<arithmetic_backend<Arithmetic>, ET> >
  504. {
  505. typedef number<arithmetic_backend<typename double_precision_type<Arithmetic>::type>, ET> type;
  506. };
  507. template <>
  508. struct double_precision_type<arithmetic_backend<boost::int32_t> >
  509. {
  510. typedef arithmetic_backend<boost::int64_t> type;
  511. };
  512. } // namespace detail
  513. }} // namespace boost::multiprecision
  514. #if !(defined(__SGI_STL_PORT) || defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS))
  515. //
  516. // We shouldn't need these to get code to compile, however for the sake of
  517. // "level playing field" performance comparisons they avoid the very slow
  518. // lexical_cast's that would otherwise take place. Definition has to be guarded
  519. // by the inverse of pp-logic in real_concept.hpp which defines these as a workaround
  520. // for STLPort plus some other old/broken standartd libraries.
  521. //
  522. namespace boost { namespace math { namespace tools {
  523. template <>
  524. inline unsigned int real_cast<unsigned int, concepts::real_concept>(concepts::real_concept r)
  525. {
  526. return static_cast<unsigned int>(r.value());
  527. }
  528. template <>
  529. inline int real_cast<int, concepts::real_concept>(concepts::real_concept r)
  530. {
  531. return static_cast<int>(r.value());
  532. }
  533. template <>
  534. inline long real_cast<long, concepts::real_concept>(concepts::real_concept r)
  535. {
  536. return static_cast<long>(r.value());
  537. }
  538. // Converts from T to narrower floating-point types, float, double & long double.
  539. template <>
  540. inline float real_cast<float, concepts::real_concept>(concepts::real_concept r)
  541. {
  542. return static_cast<float>(r.value());
  543. }
  544. template <>
  545. inline double real_cast<double, concepts::real_concept>(concepts::real_concept r)
  546. {
  547. return static_cast<double>(r.value());
  548. }
  549. template <>
  550. inline long double real_cast<long double, concepts::real_concept>(concepts::real_concept r)
  551. {
  552. return r.value();
  553. }
  554. }}} // namespace boost::math::tools
  555. #endif
  556. namespace std {
  557. template <class Arithmetic, boost::multiprecision::expression_template_option ExpressionTemplates>
  558. class numeric_limits<boost::multiprecision::number<boost::multiprecision::arithmetic_backend<Arithmetic>, ExpressionTemplates> > : public std::numeric_limits<Arithmetic>
  559. {
  560. typedef std::numeric_limits<Arithmetic> base_type;
  561. typedef boost::multiprecision::number<boost::multiprecision::arithmetic_backend<Arithmetic>, ExpressionTemplates> number_type;
  562. public:
  563. BOOST_STATIC_CONSTEXPR number_type(min)() BOOST_NOEXCEPT { return (base_type::min)(); }
  564. BOOST_STATIC_CONSTEXPR number_type(max)() BOOST_NOEXCEPT { return (base_type::max)(); }
  565. BOOST_STATIC_CONSTEXPR number_type lowest() BOOST_NOEXCEPT { return -(max)(); }
  566. BOOST_STATIC_CONSTEXPR number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); }
  567. BOOST_STATIC_CONSTEXPR number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; }
  568. BOOST_STATIC_CONSTEXPR number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); }
  569. BOOST_STATIC_CONSTEXPR number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); }
  570. BOOST_STATIC_CONSTEXPR number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); }
  571. BOOST_STATIC_CONSTEXPR number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); }
  572. };
  573. template <>
  574. class numeric_limits<boost::math::concepts::real_concept> : public std::numeric_limits<long double>
  575. {
  576. typedef std::numeric_limits<long double> base_type;
  577. typedef boost::math::concepts::real_concept number_type;
  578. public:
  579. static const number_type(min)() BOOST_NOEXCEPT { return (base_type::min)(); }
  580. static const number_type(max)() BOOST_NOEXCEPT { return (base_type::max)(); }
  581. static const number_type lowest() BOOST_NOEXCEPT { return -(max)(); }
  582. static const number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); }
  583. static const number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; }
  584. static const number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); }
  585. static const number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); }
  586. static const number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); }
  587. static const number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); }
  588. };
  589. } // namespace std
  590. #include <boost/multiprecision/detail/integer_ops.hpp>
  591. #endif