debug_adaptor.hpp 15 KB

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