debug_adaptor.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  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 http://www.boost.org/LICENSE_1_
  5. #ifndef BOOST_MATH_DEBUG_ADAPTER_HPP
  6. #define BOOST_MATH_DEBUG_ADAPTER_HPP
  7. #include <boost/multiprecision/traits/extract_exponent_type.hpp>
  8. #include <boost/multiprecision/detail/integer_ops.hpp>
  9. namespace boost{
  10. namespace multiprecision{
  11. namespace backends{
  12. template <class Backend>
  13. struct debug_adaptor
  14. {
  15. typedef typename Backend::signed_types signed_types;
  16. typedef typename Backend::unsigned_types unsigned_types;
  17. typedef typename Backend::float_types float_types;
  18. typedef typename extract_exponent_type<
  19. Backend, number_category<Backend>::value>::type exponent_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 enable_if_c<is_convertible<T, Backend>::value>::type* = 0)
  56. : m_value(i)
  57. {
  58. update_view();
  59. }
  60. template <class T>
  61. debug_adaptor(const T& i, const T& j)
  62. : m_value(i, j)
  63. {
  64. update_view();
  65. }
  66. template <class T>
  67. typename enable_if_c<is_arithmetic<T>::value || is_convertible<T, Backend>::value, debug_adaptor&>::type operator = (const T& i)
  68. {
  69. m_value = i;
  70. update_view();
  71. return *this;
  72. }
  73. debug_adaptor& operator = (const char* s)
  74. {
  75. m_value = s;
  76. update_view();
  77. return *this;
  78. }
  79. void swap(debug_adaptor& o)
  80. {
  81. std::swap(m_value, o.value());
  82. std::swap(debug_value, o.debug_value);
  83. }
  84. std::string str(std::streamsize digits, std::ios_base::fmtflags f)const
  85. {
  86. return m_value.str(digits, f);
  87. }
  88. void negate()
  89. {
  90. m_value.negate();
  91. update_view();
  92. }
  93. int compare(const debug_adaptor& o)const
  94. {
  95. return m_value.compare(o.value());
  96. }
  97. template <class T>
  98. int compare(const T& i)const
  99. {
  100. return m_value.compare(i);
  101. }
  102. Backend& value()
  103. {
  104. return m_value;
  105. }
  106. const Backend& value()const
  107. {
  108. return m_value;
  109. }
  110. template <class Archive>
  111. void serialize(Archive& ar, const unsigned int /*version*/)
  112. {
  113. ar & m_value;
  114. typedef typename Archive::is_loading tag;
  115. if(tag::value)
  116. update_view();
  117. }
  118. };
  119. template <class Backend>
  120. inline Backend const& unwrap_debug_type(debug_adaptor<Backend> const& val)
  121. {
  122. return val.value();
  123. }
  124. template <class T>
  125. inline const T& unwrap_debug_type(const T& val)
  126. {
  127. return val;
  128. }
  129. #define NON_MEMBER_OP1(name, str) \
  130. template <class Backend>\
  131. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result)\
  132. {\
  133. using default_ops::BOOST_JOIN(eval_, name);\
  134. BOOST_JOIN(eval_, name)(result.value());\
  135. result.update_view();\
  136. }
  137. #define NON_MEMBER_OP2(name, str) \
  138. template <class Backend, class T>\
  139. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const T& a)\
  140. {\
  141. using default_ops::BOOST_JOIN(eval_, name);\
  142. BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a));\
  143. result.update_view();\
  144. }\
  145. template <class Backend>\
  146. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a)\
  147. {\
  148. using default_ops::BOOST_JOIN(eval_, name);\
  149. BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a));\
  150. result.update_view();\
  151. }
  152. #define NON_MEMBER_OP3(name, str) \
  153. template <class Backend, class T, class U>\
  154. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const T& a, const U& b)\
  155. {\
  156. using default_ops::BOOST_JOIN(eval_, name);\
  157. BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\
  158. result.update_view();\
  159. }\
  160. template <class Backend, class T>\
  161. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a, const T& b)\
  162. {\
  163. using default_ops::BOOST_JOIN(eval_, name);\
  164. BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\
  165. result.update_view();\
  166. }\
  167. template <class Backend, class T>\
  168. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const T& a, const debug_adaptor<Backend>& b)\
  169. {\
  170. using default_ops::BOOST_JOIN(eval_, name);\
  171. BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\
  172. result.update_view();\
  173. }\
  174. template <class Backend>\
  175. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a, const debug_adaptor<Backend>& b)\
  176. {\
  177. using default_ops::BOOST_JOIN(eval_, name);\
  178. BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\
  179. result.update_view();\
  180. }
  181. #define NON_MEMBER_OP4(name, str) \
  182. template <class Backend, class T, class U, class V>\
  183. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const T& a, const U& b, const V& c)\
  184. {\
  185. using default_ops::BOOST_JOIN(eval_, name);\
  186. BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
  187. result.update_view();\
  188. }\
  189. template <class Backend, class T>\
  190. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a, const debug_adaptor<Backend>& b, const T& c)\
  191. {\
  192. using default_ops::BOOST_JOIN(eval_, name);\
  193. BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
  194. result.update_view();\
  195. }\
  196. template <class Backend, class T>\
  197. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a, const T& b, const debug_adaptor<Backend>& c)\
  198. {\
  199. using default_ops::BOOST_JOIN(eval_, name);\
  200. BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
  201. result.update_view();\
  202. }\
  203. template <class Backend, class T>\
  204. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const T& a, const debug_adaptor<Backend>& b, const debug_adaptor<Backend>& c)\
  205. {\
  206. using default_ops::BOOST_JOIN(eval_, name);\
  207. BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
  208. result.update_view();\
  209. }\
  210. template <class Backend>\
  211. 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)\
  212. {\
  213. using default_ops::BOOST_JOIN(eval_, name);\
  214. BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
  215. result.update_view();\
  216. }\
  217. template <class Backend, class T, class U>\
  218. inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a, const T& b, const U& c)\
  219. {\
  220. using default_ops::BOOST_JOIN(eval_, name);\
  221. BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
  222. result.update_view();\
  223. }\
  224. NON_MEMBER_OP2(add, "+=");
  225. NON_MEMBER_OP2(subtract, "-=");
  226. NON_MEMBER_OP2(multiply, "*=");
  227. NON_MEMBER_OP2(divide, "/=");
  228. template <class Backend, class R>
  229. inline void eval_convert_to(R* result, const debug_adaptor<Backend>& val)
  230. {
  231. using default_ops::eval_convert_to;
  232. eval_convert_to(result, val.value());
  233. }
  234. template <class Backend, class Exp>
  235. inline void eval_frexp(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& arg, Exp* exp)
  236. {
  237. eval_frexp(result.value(), arg.value(), exp);
  238. result.update_view();
  239. }
  240. template <class Backend, class Exp>
  241. inline void eval_ldexp(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& arg, Exp exp)
  242. {
  243. eval_ldexp(result.value(), arg.value(), exp);
  244. result.update_view();
  245. }
  246. template <class Backend, class Exp>
  247. inline void eval_scalbn(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& arg, Exp exp)
  248. {
  249. eval_scalbn(result.value(), arg.value(), exp);
  250. result.update_view();
  251. }
  252. template <class Backend>
  253. inline typename Backend::exponent_type eval_ilogb(const debug_adaptor<Backend>& arg)
  254. {
  255. return eval_ilogb(arg.value());
  256. }
  257. NON_MEMBER_OP2(floor, "floor");
  258. NON_MEMBER_OP2(ceil, "ceil");
  259. NON_MEMBER_OP2(sqrt, "sqrt");
  260. NON_MEMBER_OP2(logb, "logb");
  261. template <class Backend>
  262. inline int eval_fpclassify(const debug_adaptor<Backend>& arg)
  263. {
  264. using default_ops::eval_fpclassify;
  265. return eval_fpclassify(arg.value());
  266. }
  267. /*********************************************************************
  268. *
  269. * Optional arithmetic operations come next:
  270. *
  271. *********************************************************************/
  272. NON_MEMBER_OP3(add, "+");
  273. NON_MEMBER_OP3(subtract, "-");
  274. NON_MEMBER_OP3(multiply, "*");
  275. NON_MEMBER_OP3(divide, "/");
  276. NON_MEMBER_OP3(multiply_add, "fused-multiply-add");
  277. NON_MEMBER_OP3(multiply_subtract, "fused-multiply-subtract");
  278. NON_MEMBER_OP4(multiply_add, "fused-multiply-add");
  279. NON_MEMBER_OP4(multiply_subtract, "fused-multiply-subtract");
  280. NON_MEMBER_OP1(increment, "increment");
  281. NON_MEMBER_OP1(decrement, "decrement");
  282. /*********************************************************************
  283. *
  284. * Optional integer operations come next:
  285. *
  286. *********************************************************************/
  287. NON_MEMBER_OP2(modulus, "%=");
  288. NON_MEMBER_OP3(modulus, "%");
  289. NON_MEMBER_OP2(bitwise_or, "|=");
  290. NON_MEMBER_OP3(bitwise_or, "|");
  291. NON_MEMBER_OP2(bitwise_and, "&=");
  292. NON_MEMBER_OP3(bitwise_and, "&");
  293. NON_MEMBER_OP2(bitwise_xor, "^=");
  294. NON_MEMBER_OP3(bitwise_xor, "^");
  295. NON_MEMBER_OP4(qr, "quotient-and-remainder");
  296. NON_MEMBER_OP2(complement, "~");
  297. template <class Backend>
  298. inline void eval_left_shift(debug_adaptor<Backend>& arg, unsigned a)
  299. {
  300. using default_ops::eval_left_shift;
  301. eval_left_shift(arg.value(), a);
  302. arg.update_view();\
  303. }
  304. template <class Backend>
  305. inline void eval_left_shift(debug_adaptor<Backend>& arg, const debug_adaptor<Backend>& a, unsigned b)
  306. {
  307. using default_ops::eval_left_shift;
  308. eval_left_shift(arg.value(), a.value(), b);
  309. arg.update_view();\
  310. }
  311. template <class Backend>
  312. inline void eval_right_shift(debug_adaptor<Backend>& arg, unsigned a)
  313. {
  314. using default_ops::eval_right_shift;
  315. eval_right_shift(arg.value(), a);
  316. arg.update_view();\
  317. }
  318. template <class Backend>
  319. inline void eval_right_shift(debug_adaptor<Backend>& arg, const debug_adaptor<Backend>& a, unsigned b)
  320. {
  321. using default_ops::eval_right_shift;
  322. eval_right_shift(arg.value(), a.value(), b);
  323. arg.update_view();\
  324. }
  325. template <class Backend, class T>
  326. inline unsigned eval_integer_modulus(const debug_adaptor<Backend>& arg, const T& a)
  327. {
  328. using default_ops::eval_integer_modulus;
  329. return eval_integer_modulus(arg.value(), a);
  330. }
  331. template <class Backend>
  332. inline unsigned eval_lsb(const debug_adaptor<Backend>& arg)
  333. {
  334. using default_ops::eval_lsb;
  335. return eval_lsb(arg.value());
  336. }
  337. template <class Backend>
  338. inline unsigned eval_msb(const debug_adaptor<Backend>& arg)
  339. {
  340. using default_ops::eval_msb;
  341. return eval_msb(arg.value());
  342. }
  343. template <class Backend>
  344. inline bool eval_bit_test(const debug_adaptor<Backend>& arg, unsigned a)
  345. {
  346. using default_ops::eval_bit_test;
  347. return eval_bit_test(arg.value(), a);
  348. }
  349. template <class Backend>
  350. inline void eval_bit_set(const debug_adaptor<Backend>& arg, unsigned a)
  351. {
  352. using default_ops::eval_bit_set;
  353. eval_bit_set(arg.value(), a);
  354. arg.update_view();\
  355. }
  356. template <class Backend>
  357. inline void eval_bit_unset(const debug_adaptor<Backend>& arg, unsigned a)
  358. {
  359. using default_ops::eval_bit_unset;
  360. eval_bit_unset(arg.value(), a);
  361. arg.update_view();\
  362. }
  363. template <class Backend>
  364. inline void eval_bit_flip(const debug_adaptor<Backend>& arg, unsigned a)
  365. {
  366. using default_ops::eval_bit_flip;
  367. eval_bit_flip(arg.value(), a);
  368. arg.update_view();\
  369. }
  370. NON_MEMBER_OP3(gcd, "gcd");
  371. NON_MEMBER_OP3(lcm, "lcm");
  372. NON_MEMBER_OP4(powm, "powm");
  373. /*********************************************************************
  374. *
  375. * abs/fabs:
  376. *
  377. *********************************************************************/
  378. NON_MEMBER_OP2(abs, "abs");
  379. NON_MEMBER_OP2(fabs, "fabs");
  380. /*********************************************************************
  381. *
  382. * Floating point functions:
  383. *
  384. *********************************************************************/
  385. NON_MEMBER_OP2(trunc, "trunc");
  386. NON_MEMBER_OP2(round, "round");
  387. NON_MEMBER_OP2(exp, "exp");
  388. NON_MEMBER_OP2(log, "log");
  389. NON_MEMBER_OP2(log10, "log10");
  390. NON_MEMBER_OP2(sin, "sin");
  391. NON_MEMBER_OP2(cos, "cos");
  392. NON_MEMBER_OP2(tan, "tan");
  393. NON_MEMBER_OP2(asin, "asin");
  394. NON_MEMBER_OP2(acos, "acos");
  395. NON_MEMBER_OP2(atan, "atan");
  396. NON_MEMBER_OP2(sinh, "sinh");
  397. NON_MEMBER_OP2(cosh, "cosh");
  398. NON_MEMBER_OP2(tanh, "tanh");
  399. NON_MEMBER_OP3(fmod, "fmod");
  400. NON_MEMBER_OP3(pow, "pow");
  401. NON_MEMBER_OP3(atan2, "atan2");
  402. } // namespace backends
  403. using backends::debug_adaptor;
  404. template<class Backend>
  405. struct number_category<backends::debug_adaptor<Backend> > : public number_category<Backend> {};
  406. }} // namespaces
  407. namespace std{
  408. template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
  409. class numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<Backend>, ExpressionTemplates> >
  410. : public std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> >
  411. {
  412. typedef std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> > base_type;
  413. typedef boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<Backend>, ExpressionTemplates> number_type;
  414. public:
  415. static number_type (min)() BOOST_NOEXCEPT { return (base_type::min)(); }
  416. static number_type (max)() BOOST_NOEXCEPT { return (base_type::max)(); }
  417. static number_type lowest() BOOST_NOEXCEPT { return -(max)(); }
  418. static number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); }
  419. static number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; }
  420. static number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); }
  421. static number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); }
  422. static number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); }
  423. static number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); }
  424. };
  425. } // namespace std
  426. namespace boost{ namespace math{
  427. namespace policies{
  428. template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
  429. struct precision< boost::multiprecision::number<boost::multiprecision::debug_adaptor<Backend>, ExpressionTemplates>, Policy>
  430. : public precision<boost::multiprecision::number<Backend, ExpressionTemplates>, Policy>
  431. {};
  432. #undef NON_MEMBER_OP1
  433. #undef NON_MEMBER_OP2
  434. #undef NON_MEMBER_OP3
  435. #undef NON_MEMBER_OP4
  436. } // namespace policies
  437. }} // namespaces boost::math
  438. #endif