debug_adaptor.hpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  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_MP_DEBUG_ADAPTOR_HPP
  6. #define BOOST_MP_DEBUG_ADAPTOR_HPP
  7. #include <boost/multiprecision/detail/standalone_config.hpp>
  8. #include <boost/multiprecision/traits/extract_exponent_type.hpp>
  9. #include <boost/multiprecision/detail/integer_ops.hpp>
  10. namespace boost {
  11. namespace multiprecision {
  12. namespace backends {
  13. template <class Backend>
  14. struct debug_adaptor
  15. {
  16. using signed_types = typename Backend::signed_types ;
  17. using unsigned_types = typename Backend::unsigned_types;
  18. using float_types = typename Backend::float_types ;
  19. using exponent_type = typename extract_exponent_type<Backend, number_category<Backend>::value>::type;
  20. private:
  21. std::string debug_value;
  22. Backend m_value;
  23. public:
  24. void update_view()
  25. {
  26. #ifndef BOOST_NO_EXCEPTIONS
  27. try
  28. {
  29. #endif
  30. debug_value = m_value.str(0, static_cast<std::ios_base::fmtflags>(0));
  31. #ifndef BOOST_NO_EXCEPTIONS
  32. }
  33. catch (const std::exception& e)
  34. {
  35. debug_value = "String conversion failed with message: \"";
  36. debug_value += e.what();
  37. debug_value += "\"";
  38. }
  39. #endif
  40. }
  41. debug_adaptor()
  42. {
  43. update_view();
  44. }
  45. debug_adaptor(const debug_adaptor& o) : debug_value(o.debug_value), m_value(o.m_value)
  46. {
  47. }
  48. debug_adaptor& operator=(const debug_adaptor& o)
  49. {
  50. debug_value = o.debug_value;
  51. m_value = o.m_value;
  52. return *this;
  53. }
  54. template <class T>
  55. debug_adaptor(const T& i, const typename std::enable_if<std::is_convertible<T, Backend>::value>::type* = nullptr)
  56. : m_value(i)
  57. {
  58. update_view();
  59. }
  60. template <class T>
  61. debug_adaptor(const debug_adaptor<T>& i, const typename std::enable_if<std::is_convertible<T, Backend>::value>::type* = nullptr)
  62. : m_value(i.value())
  63. {
  64. update_view();
  65. }
  66. template <class T, class U>
  67. debug_adaptor(const T& i, const U& j, typename std::enable_if<std::is_constructible<Backend, const T&, const U&>::value>::type* = nullptr)
  68. : m_value(i, j)
  69. {
  70. update_view();
  71. }
  72. template <class B2>
  73. debug_adaptor(const B2& i, unsigned digits10, typename std::enable_if<std::is_same<B2, Backend>::value && std::is_constructible<Backend, const Backend&, unsigned>::value>::type* = nullptr)
  74. : m_value(i, digits10)
  75. {
  76. update_view();
  77. }
  78. template <class T>
  79. typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value || std::is_assignable<Backend, T>::value, debug_adaptor&>::type operator=(const T& i)
  80. {
  81. m_value = i;
  82. update_view();
  83. return *this;
  84. }
  85. debug_adaptor& operator=(const char* s)
  86. {
  87. m_value = s;
  88. update_view();
  89. return *this;
  90. }
  91. void swap(debug_adaptor& o)
  92. {
  93. std::swap(m_value, o.value());
  94. std::swap(debug_value, o.debug_value);
  95. }
  96. std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
  97. {
  98. return m_value.str(digits, f);
  99. }
  100. void negate()
  101. {
  102. m_value.negate();
  103. update_view();
  104. }
  105. int compare(const debug_adaptor& o) const
  106. {
  107. return m_value.compare(o.value());
  108. }
  109. template <class T>
  110. int compare(const T& i) const
  111. {
  112. return m_value.compare(i);
  113. }
  114. Backend& value()
  115. {
  116. return m_value;
  117. }
  118. const Backend& value() const
  119. {
  120. return m_value;
  121. }
  122. #ifndef BOOST_MP_STANDALONE
  123. template <class Archive>
  124. void serialize(Archive& ar, const unsigned int /*version*/)
  125. {
  126. ar & boost::make_nvp("value", m_value);
  127. using tag = typename Archive::is_loading;
  128. if (tag::value)
  129. update_view();
  130. }
  131. #endif
  132. static unsigned default_precision() noexcept
  133. {
  134. return Backend::default_precision();
  135. }
  136. static void default_precision(unsigned v) noexcept
  137. {
  138. Backend::default_precision(v);
  139. }
  140. static unsigned thread_default_precision() noexcept
  141. {
  142. return Backend::thread_default_precision();
  143. }
  144. static void thread_default_precision(unsigned v) noexcept
  145. {
  146. Backend::thread_default_precision(v);
  147. }
  148. unsigned precision() const noexcept
  149. {
  150. return value().precision();
  151. }
  152. void precision(unsigned digits10) noexcept
  153. {
  154. value().precision(digits10);
  155. }
  156. //
  157. // Variable precision options:
  158. //
  159. static constexpr variable_precision_options default_variable_precision_options()noexcept
  160. {
  161. return Backend::default_variable_precision_options();
  162. }
  163. static constexpr variable_precision_options thread_default_variable_precision_options()noexcept
  164. {
  165. return Backend::thread_default_variable_precision_options();
  166. }
  167. static BOOST_MP_CXX14_CONSTEXPR void default_variable_precision_options(variable_precision_options opts)
  168. {
  169. Backend::default_variable_precision_options(opts);
  170. }
  171. static BOOST_MP_CXX14_CONSTEXPR void thread_default_variable_precision_options(variable_precision_options opts)
  172. {
  173. Backend::thread_default_variable_precision_options(opts);
  174. }
  175. };
  176. template <class Backend>
  177. inline Backend const& unwrap_debug_type(debug_adaptor<Backend> const& val)
  178. {
  179. return val.value();
  180. }
  181. template <class T>
  182. inline const T& unwrap_debug_type(const T& val)
  183. {
  184. return val;
  185. }
  186. template <class Backend, class V, class U>
  187. inline BOOST_MP_CXX14_CONSTEXPR void assign_components(debug_adaptor<Backend>& result, const V& v1, const U& v2)
  188. {
  189. using default_ops::assign_components;
  190. assign_components(result.value(), unwrap_debug_type(v1), unwrap_debug_type(v2));
  191. result.update_view();
  192. }
  193. #define NON_MEMBER_OP1(name, str) \
  194. template <class Backend> \
  195. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result) \
  196. { \
  197. using default_ops::BOOST_JOIN(eval_, name); \
  198. BOOST_JOIN(eval_, name) \
  199. (result.value()); \
  200. result.update_view(); \
  201. }
  202. #define NON_MEMBER_OP2(name, str) \
  203. template <class Backend, class T> \
  204. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const T& a) \
  205. { \
  206. using default_ops::BOOST_JOIN(eval_, name); \
  207. BOOST_JOIN(eval_, name) \
  208. (result.value(), unwrap_debug_type(a)); \
  209. result.update_view(); \
  210. } \
  211. template <class Backend> \
  212. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const debug_adaptor<Backend>& a) \
  213. { \
  214. using default_ops::BOOST_JOIN(eval_, name); \
  215. BOOST_JOIN(eval_, name) \
  216. (result.value(), unwrap_debug_type(a)); \
  217. result.update_view(); \
  218. }
  219. #define NON_MEMBER_OP3(name, str) \
  220. template <class Backend, class T, class U> \
  221. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const T& a, const U& b) \
  222. { \
  223. using default_ops::BOOST_JOIN(eval_, name); \
  224. BOOST_JOIN(eval_, name) \
  225. (result.value(), unwrap_debug_type(a), unwrap_debug_type(b)); \
  226. result.update_view(); \
  227. } \
  228. template <class Backend, class T> \
  229. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const debug_adaptor<Backend>& a, const T& b) \
  230. { \
  231. using default_ops::BOOST_JOIN(eval_, name); \
  232. BOOST_JOIN(eval_, name) \
  233. (result.value(), unwrap_debug_type(a), unwrap_debug_type(b)); \
  234. result.update_view(); \
  235. } \
  236. template <class Backend, class T> \
  237. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const T& a, const debug_adaptor<Backend>& b) \
  238. { \
  239. using default_ops::BOOST_JOIN(eval_, name); \
  240. BOOST_JOIN(eval_, name) \
  241. (result.value(), unwrap_debug_type(a), unwrap_debug_type(b)); \
  242. result.update_view(); \
  243. } \
  244. template <class Backend> \
  245. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const debug_adaptor<Backend>& a, const debug_adaptor<Backend>& b) \
  246. { \
  247. using default_ops::BOOST_JOIN(eval_, name); \
  248. BOOST_JOIN(eval_, name) \
  249. (result.value(), unwrap_debug_type(a), unwrap_debug_type(b)); \
  250. result.update_view(); \
  251. }
  252. #define NON_MEMBER_OP4(name, str) \
  253. template <class Backend, class T, class U, class V> \
  254. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const T& a, const U& b, const V& c) \
  255. { \
  256. using default_ops::BOOST_JOIN(eval_, name); \
  257. BOOST_JOIN(eval_, name) \
  258. (result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c)); \
  259. result.update_view(); \
  260. } \
  261. template <class Backend, class T> \
  262. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const debug_adaptor<Backend>& a, const debug_adaptor<Backend>& b, const T& c) \
  263. { \
  264. using default_ops::BOOST_JOIN(eval_, name); \
  265. BOOST_JOIN(eval_, name) \
  266. (result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c)); \
  267. result.update_view(); \
  268. } \
  269. template <class Backend, class T> \
  270. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const debug_adaptor<Backend>& a, const T& b, const debug_adaptor<Backend>& c) \
  271. { \
  272. using default_ops::BOOST_JOIN(eval_, name); \
  273. BOOST_JOIN(eval_, name) \
  274. (result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c)); \
  275. result.update_view(); \
  276. } \
  277. template <class Backend, class T> \
  278. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const T& a, const debug_adaptor<Backend>& b, const debug_adaptor<Backend>& c) \
  279. { \
  280. using default_ops::BOOST_JOIN(eval_, name); \
  281. BOOST_JOIN(eval_, name) \
  282. (result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c)); \
  283. result.update_view(); \
  284. } \
  285. template <class Backend> \
  286. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const debug_adaptor<Backend>& a, const debug_adaptor<Backend>& b, const debug_adaptor<Backend>& c) \
  287. { \
  288. using default_ops::BOOST_JOIN(eval_, name); \
  289. BOOST_JOIN(eval_, name) \
  290. (result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c)); \
  291. result.update_view(); \
  292. } \
  293. template <class Backend, class T, class U> \
  294. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const debug_adaptor<Backend>& a, const T& b, const U& c) \
  295. { \
  296. using default_ops::BOOST_JOIN(eval_, name); \
  297. BOOST_JOIN(eval_, name) \
  298. (result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c)); \
  299. result.update_view(); \
  300. }
  301. NON_MEMBER_OP2(add, "+=")
  302. NON_MEMBER_OP2(subtract, "-=")
  303. NON_MEMBER_OP2(multiply, "*=")
  304. NON_MEMBER_OP2(divide, "/=")
  305. template <class Backend, class R>
  306. inline void eval_convert_to(R* result, const debug_adaptor<Backend>& val)
  307. {
  308. using default_ops::eval_convert_to;
  309. eval_convert_to(result, val.value());
  310. }
  311. template <class Backend, class R>
  312. inline void eval_convert_to(debug_adaptor<R>* result, const debug_adaptor<Backend>& val)
  313. {
  314. using default_ops::eval_convert_to;
  315. eval_convert_to(&result->value(), val.value());
  316. }
  317. template <class Backend, class R>
  318. inline void eval_convert_to(debug_adaptor<R>* result, const Backend& val)
  319. {
  320. using default_ops::eval_convert_to;
  321. eval_convert_to(&result->value(), val);
  322. }
  323. template <class Backend>
  324. inline void eval_convert_to(std::complex<float>* result, const debug_adaptor<Backend>& val)
  325. {
  326. using default_ops::eval_convert_to;
  327. eval_convert_to(result, val.value());
  328. }
  329. template <class Backend>
  330. inline void eval_convert_to(std::complex<double>* result, const debug_adaptor<Backend>& val)
  331. {
  332. using default_ops::eval_convert_to;
  333. eval_convert_to(result, val.value());
  334. }
  335. template <class Backend>
  336. inline void eval_convert_to(std::complex<long double>* result, const debug_adaptor<Backend>& val)
  337. {
  338. using default_ops::eval_convert_to;
  339. eval_convert_to(result, val.value());
  340. }
  341. template <class Backend, class Exp>
  342. inline void eval_frexp(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& arg, Exp* exp)
  343. {
  344. eval_frexp(result.value(), arg.value(), exp);
  345. result.update_view();
  346. }
  347. template <class Backend, class Exp>
  348. inline void eval_ldexp(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& arg, Exp exp)
  349. {
  350. eval_ldexp(result.value(), arg.value(), exp);
  351. result.update_view();
  352. }
  353. template <class Backend, class Exp>
  354. inline void eval_scalbn(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& arg, Exp exp)
  355. {
  356. using default_ops::eval_scalbn;
  357. eval_scalbn(result.value(), arg.value(), exp);
  358. result.update_view();
  359. }
  360. template <class Backend>
  361. inline typename Backend::exponent_type eval_ilogb(const debug_adaptor<Backend>& arg)
  362. {
  363. using default_ops::eval_ilogb;
  364. return eval_ilogb(arg.value());
  365. }
  366. NON_MEMBER_OP2(floor, "floor")
  367. NON_MEMBER_OP2(ceil, "ceil")
  368. NON_MEMBER_OP2(sqrt, "sqrt")
  369. NON_MEMBER_OP2(logb, "logb")
  370. template <class Backend>
  371. inline int eval_fpclassify(const debug_adaptor<Backend>& arg)
  372. {
  373. using default_ops::eval_fpclassify;
  374. return eval_fpclassify(arg.value());
  375. }
  376. /*********************************************************************
  377. *
  378. * Optional arithmetic operations come next:
  379. *
  380. *********************************************************************/
  381. NON_MEMBER_OP3(add, "+")
  382. NON_MEMBER_OP3(subtract, "-")
  383. NON_MEMBER_OP3(multiply, "*")
  384. NON_MEMBER_OP3(divide, "/")
  385. NON_MEMBER_OP3(multiply_add, "fused-multiply-add")
  386. NON_MEMBER_OP3(multiply_subtract, "fused-multiply-subtract")
  387. NON_MEMBER_OP4(multiply_add, "fused-multiply-add")
  388. NON_MEMBER_OP4(multiply_subtract, "fused-multiply-subtract")
  389. NON_MEMBER_OP1(increment, "increment")
  390. NON_MEMBER_OP1(decrement, "decrement")
  391. /*********************************************************************
  392. *
  393. * Optional integer operations come next:
  394. *
  395. *********************************************************************/
  396. NON_MEMBER_OP2(modulus, "%=")
  397. NON_MEMBER_OP3(modulus, "%")
  398. NON_MEMBER_OP2(bitwise_or, "|=")
  399. NON_MEMBER_OP3(bitwise_or, "|")
  400. NON_MEMBER_OP2(bitwise_and, "&=")
  401. NON_MEMBER_OP3(bitwise_and, "&")
  402. NON_MEMBER_OP2(bitwise_xor, "^=")
  403. NON_MEMBER_OP3(bitwise_xor, "^")
  404. NON_MEMBER_OP4(qr, "quotient-and-remainder")
  405. NON_MEMBER_OP2(complement, "~")
  406. template <class Backend>
  407. inline void eval_left_shift(debug_adaptor<Backend>& arg, std::size_t a)
  408. {
  409. using default_ops::eval_left_shift;
  410. eval_left_shift(arg.value(), a);
  411. arg.update_view();
  412. }
  413. template <class Backend>
  414. inline void eval_left_shift(debug_adaptor<Backend>& arg, const debug_adaptor<Backend>& a, std::size_t b)
  415. {
  416. using default_ops::eval_left_shift;
  417. eval_left_shift(arg.value(), a.value(), b);
  418. arg.update_view();
  419. }
  420. template <class Backend>
  421. inline void eval_right_shift(debug_adaptor<Backend>& arg, std::size_t a)
  422. {
  423. using default_ops::eval_right_shift;
  424. eval_right_shift(arg.value(), a);
  425. arg.update_view();
  426. }
  427. template <class Backend>
  428. inline void eval_right_shift(debug_adaptor<Backend>& arg, const debug_adaptor<Backend>& a, std::size_t b)
  429. {
  430. using default_ops::eval_right_shift;
  431. eval_right_shift(arg.value(), a.value(), b);
  432. arg.update_view();
  433. }
  434. template <class Backend, class T>
  435. inline T eval_integer_modulus(const debug_adaptor<Backend>& arg, const T& a)
  436. {
  437. using default_ops::eval_integer_modulus;
  438. return eval_integer_modulus(arg.value(), a);
  439. }
  440. template <class Backend>
  441. inline std::size_t eval_lsb(const debug_adaptor<Backend>& arg)
  442. {
  443. using default_ops::eval_lsb;
  444. return eval_lsb(arg.value());
  445. }
  446. template <class Backend>
  447. inline std::size_t eval_msb(const debug_adaptor<Backend>& arg)
  448. {
  449. using default_ops::eval_msb;
  450. return eval_msb(arg.value());
  451. }
  452. template <class Backend>
  453. inline bool eval_bit_test(const debug_adaptor<Backend>& arg, std::size_t a)
  454. {
  455. using default_ops::eval_bit_test;
  456. return eval_bit_test(arg.value(), a);
  457. }
  458. template <class Backend>
  459. inline void eval_bit_set(const debug_adaptor<Backend>& arg, std::size_t a)
  460. {
  461. using default_ops::eval_bit_set;
  462. eval_bit_set(arg.value(), a);
  463. arg.update_view();
  464. }
  465. template <class Backend>
  466. inline void eval_bit_unset(const debug_adaptor<Backend>& arg, std::size_t a)
  467. {
  468. using default_ops::eval_bit_unset;
  469. eval_bit_unset(arg.value(), a);
  470. arg.update_view();
  471. }
  472. template <class Backend>
  473. inline void eval_bit_flip(const debug_adaptor<Backend>& arg, std::size_t a)
  474. {
  475. using default_ops::eval_bit_flip;
  476. eval_bit_flip(arg.value(), a);
  477. arg.update_view();
  478. }
  479. NON_MEMBER_OP3(gcd, "gcd")
  480. NON_MEMBER_OP3(lcm, "lcm")
  481. NON_MEMBER_OP4(powm, "powm")
  482. /*********************************************************************
  483. *
  484. * abs/fabs:
  485. *
  486. *********************************************************************/
  487. NON_MEMBER_OP2(abs, "abs")
  488. NON_MEMBER_OP2(fabs, "fabs")
  489. /*********************************************************************
  490. *
  491. * Floating point functions:
  492. *
  493. *********************************************************************/
  494. NON_MEMBER_OP2(trunc, "trunc")
  495. NON_MEMBER_OP2(round, "round")
  496. NON_MEMBER_OP2(exp, "exp")
  497. NON_MEMBER_OP2(log, "log")
  498. NON_MEMBER_OP2(log10, "log10")
  499. NON_MEMBER_OP2(sin, "sin")
  500. NON_MEMBER_OP2(cos, "cos")
  501. NON_MEMBER_OP2(tan, "tan")
  502. NON_MEMBER_OP2(asin, "asin")
  503. NON_MEMBER_OP2(acos, "acos")
  504. NON_MEMBER_OP2(atan, "atan")
  505. NON_MEMBER_OP2(sinh, "sinh")
  506. NON_MEMBER_OP2(cosh, "cosh")
  507. NON_MEMBER_OP2(tanh, "tanh")
  508. NON_MEMBER_OP2(asinh, "asinh")
  509. NON_MEMBER_OP2(acosh, "acosh")
  510. NON_MEMBER_OP2(atanh, "atanh")
  511. NON_MEMBER_OP3(fmod, "fmod")
  512. NON_MEMBER_OP3(pow, "pow")
  513. NON_MEMBER_OP3(atan2, "atan2")
  514. NON_MEMBER_OP2(conj, "conj")
  515. template <class Backend>
  516. int eval_signbit(const debug_adaptor<Backend>& val)
  517. {
  518. using default_ops::eval_signbit;
  519. return eval_signbit(val.value());
  520. }
  521. template <class Backend>
  522. std::size_t hash_value(const debug_adaptor<Backend>& val)
  523. {
  524. return hash_value(val.value());
  525. }
  526. template <class Backend, expression_template_option ExpressionTemplates>
  527. inline typename std::enable_if<number_category<Backend>::value == number_kind_rational, typename number<debug_adaptor<Backend>, ExpressionTemplates>::value_type>::type
  528. numerator(const number<debug_adaptor<Backend>, ExpressionTemplates>& arg)
  529. {
  530. number<Backend, ExpressionTemplates> t(arg.backend().value());
  531. return numerator(t).backend();
  532. }
  533. template <class Backend, expression_template_option ExpressionTemplates>
  534. inline typename std::enable_if<number_category<Backend>::value == number_kind_rational, typename number<debug_adaptor<Backend>, ExpressionTemplates>::value_type>::type
  535. denominator(const number<debug_adaptor<Backend>, ExpressionTemplates>& arg)
  536. {
  537. number<Backend, ExpressionTemplates> t(arg.backend().value());
  538. return denominator(t).backend();
  539. }
  540. template <class To, class From>
  541. inline BOOST_MP_CXX14_CONSTEXPR void eval_real(To& to, const debug_adaptor<From>& from)
  542. {
  543. using default_ops::eval_real;
  544. eval_real(to, from.value());
  545. }
  546. template <class To, class From>
  547. inline BOOST_MP_CXX14_CONSTEXPR void eval_real(debug_adaptor<To>& to, const debug_adaptor<From>& from)
  548. {
  549. using default_ops::eval_real;
  550. eval_real(to.value(), from.value());
  551. to.update_view();
  552. }
  553. template <class To, class From>
  554. inline BOOST_MP_CXX14_CONSTEXPR void eval_real(debug_adaptor<To>& to, const From& from)
  555. {
  556. using default_ops::eval_real;
  557. eval_real(to.value(), from);
  558. to.update_view();
  559. }
  560. template <class To, class From>
  561. inline BOOST_MP_CXX14_CONSTEXPR void eval_imag(To& to, const debug_adaptor<From>& from)
  562. {
  563. using default_ops::eval_imag;
  564. eval_imag(to, from.value());
  565. }
  566. template <class To, class From>
  567. inline BOOST_MP_CXX14_CONSTEXPR void eval_imag(debug_adaptor<To>& to, const debug_adaptor<From>& from)
  568. {
  569. using default_ops::eval_imag;
  570. eval_imag(to.value(), from.value());
  571. to.update_view();
  572. }
  573. template <class To, class From>
  574. inline BOOST_MP_CXX14_CONSTEXPR void eval_imag(debug_adaptor<To>& to, const From& from)
  575. {
  576. using default_ops::eval_imag;
  577. eval_imag(to.value(), from);
  578. to.update_view();
  579. }
  580. template <class To, class From>
  581. inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(To& to, const debug_adaptor<From>& from)
  582. {
  583. using default_ops::eval_set_real;
  584. eval_set_real(to, from.value());
  585. }
  586. template <class To, class From>
  587. inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(debug_adaptor<To>& to, const debug_adaptor<From>& from)
  588. {
  589. using default_ops::eval_set_real;
  590. eval_set_real(to.value(), from.value());
  591. to.update_view();
  592. }
  593. template <class To, class From>
  594. inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(debug_adaptor<To>& to, const From& from)
  595. {
  596. using default_ops::eval_set_real;
  597. eval_set_real(to.value(), from);
  598. to.update_view();
  599. }
  600. template <class To, class From>
  601. inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(To& to, const debug_adaptor<From>& from)
  602. {
  603. using default_ops::eval_set_imag;
  604. eval_set_imag(to, from.value());
  605. }
  606. template <class To, class From>
  607. inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(debug_adaptor<To>& to, const debug_adaptor<From>& from)
  608. {
  609. using default_ops::eval_set_imag;
  610. eval_set_imag(to.value(), from.value());
  611. to.update_view();
  612. }
  613. template <class To, class From>
  614. inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(debug_adaptor<To>& to, const From& from)
  615. {
  616. using default_ops::eval_set_imag;
  617. eval_set_imag(to.value(), from);
  618. to.update_view();
  619. }
  620. } // namespace backends
  621. namespace detail {
  622. template <class Backend>
  623. struct is_variable_precision<debug_adaptor<Backend> > : public is_variable_precision<Backend>
  624. {};
  625. #ifdef BOOST_HAS_INT128
  626. template <class Backend>
  627. struct is_convertible_arithmetic<int128_type, debug_adaptor<Backend> > : public is_convertible_arithmetic<int128_type, Backend>
  628. {};
  629. template <class Backend>
  630. struct is_convertible_arithmetic<uint128_type, debug_adaptor<Backend> > : public is_convertible_arithmetic<uint128_type, Backend>
  631. {};
  632. #endif
  633. #ifdef BOOST_HAS_FLOAT128
  634. template <class Backend>
  635. struct is_convertible_arithmetic<float128_type, debug_adaptor<Backend> > : public is_convertible_arithmetic<float128_type, Backend>
  636. {};
  637. #endif
  638. } // namespace detail
  639. template <class Backend>
  640. struct number_category<backends::debug_adaptor<Backend> > : public number_category<Backend>
  641. {};
  642. template <class Backend, expression_template_option ExpressionTemplates>
  643. struct component_type<number<debug_adaptor<Backend>, ExpressionTemplates>>
  644. {
  645. //
  646. // We'll make the component_type also a debug_adaptor:
  647. //
  648. using base_component_type = typename component_type<number<Backend, ExpressionTemplates>>::type;
  649. using base_component_backend = typename base_component_type::backend_type;
  650. using type = number<debug_adaptor<base_component_backend>, ExpressionTemplates>;
  651. };
  652. template <class Backend>
  653. struct is_interval_number<backends::debug_adaptor<Backend> > : public is_interval_number<Backend> {};
  654. }} // namespace boost::multiprecision
  655. namespace std {
  656. template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
  657. class numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<Backend>, ExpressionTemplates> >
  658. : public std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> >
  659. {
  660. using base_type = std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> > ;
  661. using number_type = boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<Backend>, ExpressionTemplates>;
  662. public:
  663. static number_type(min)() noexcept { return (base_type::min)(); }
  664. static number_type(max)() noexcept { return (base_type::max)(); }
  665. static number_type lowest() noexcept { return -(max)(); }
  666. static number_type epsilon() noexcept { return base_type::epsilon(); }
  667. static number_type round_error() noexcept { return epsilon() / 2; }
  668. static number_type infinity() noexcept { return base_type::infinity(); }
  669. static number_type quiet_NaN() noexcept { return base_type::quiet_NaN(); }
  670. static number_type signaling_NaN() noexcept { return base_type::signaling_NaN(); }
  671. static number_type denorm_min() noexcept { return base_type::denorm_min(); }
  672. };
  673. } // namespace std
  674. #ifdef BOOST_MP_MATH_AVAILABLE
  675. namespace boost {
  676. namespace math {
  677. namespace policies {
  678. template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
  679. struct precision<boost::multiprecision::number<boost::multiprecision::debug_adaptor<Backend>, ExpressionTemplates>, Policy>
  680. : public precision<boost::multiprecision::number<Backend, ExpressionTemplates>, Policy>
  681. {};
  682. #undef NON_MEMBER_OP1
  683. #undef NON_MEMBER_OP2
  684. #undef NON_MEMBER_OP3
  685. #undef NON_MEMBER_OP4
  686. }
  687. }} // namespace boost::math::policies
  688. #else
  689. #undef NON_MEMBER_OP1
  690. #undef NON_MEMBER_OP2
  691. #undef NON_MEMBER_OP3
  692. #undef NON_MEMBER_OP4
  693. #endif // BOOST_MP_MATH_AVAILABLE
  694. #endif