debug_adaptor.hpp 16 KB

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