logged_adaptor.hpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  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_LOGGED_ADAPTER_HPP
  6. #define BOOST_MATH_LOGGED_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. template <class Backend>
  12. inline void log_postfix_event(const Backend&, const char* /*event_description*/)
  13. {
  14. }
  15. template <class Backend, class T>
  16. inline void log_postfix_event(const Backend&, const T&, const char* /*event_description*/)
  17. {
  18. }
  19. template <class Backend>
  20. inline void log_prefix_event(const Backend&, const char* /*event_description*/)
  21. {
  22. }
  23. template <class Backend, class T>
  24. inline void log_prefix_event(const Backend&, const T&, const char* /*event_description*/)
  25. {
  26. }
  27. template <class Backend, class T, class U>
  28. inline void log_prefix_event(const Backend&, const T&, const U&, const char* /*event_description*/)
  29. {
  30. }
  31. template <class Backend, class T, class U, class V>
  32. inline void log_prefix_event(const Backend&, const T&, const U&, const V&, const char* /*event_description*/)
  33. {
  34. }
  35. namespace backends {
  36. template <class Backend>
  37. struct logged_adaptor
  38. {
  39. using signed_types = typename Backend::signed_types ;
  40. using unsigned_types = typename Backend::unsigned_types;
  41. using float_types = typename Backend::float_types ;
  42. using exponent_type = typename extract_exponent_type<Backend, number_category<Backend>::value>::type;
  43. private:
  44. Backend m_value;
  45. public:
  46. logged_adaptor()
  47. {
  48. log_postfix_event(m_value, "Default construct");
  49. }
  50. logged_adaptor(const logged_adaptor& o)
  51. {
  52. log_prefix_event(m_value, o.value(), "Copy construct");
  53. m_value = o.m_value;
  54. log_postfix_event(m_value, "Copy construct");
  55. }
  56. // rvalue copy
  57. logged_adaptor(logged_adaptor&& o)
  58. {
  59. log_prefix_event(m_value, o.value(), "Move construct");
  60. m_value = static_cast<Backend&&>(o.m_value);
  61. log_postfix_event(m_value, "Move construct");
  62. }
  63. logged_adaptor& operator=(logged_adaptor&& o)
  64. {
  65. log_prefix_event(m_value, o.value(), "Move Assignment");
  66. m_value = static_cast<Backend&&>(o.m_value);
  67. log_postfix_event(m_value, "Move construct");
  68. return *this;
  69. }
  70. logged_adaptor& operator=(const logged_adaptor& o)
  71. {
  72. log_prefix_event(m_value, o.value(), "Assignment");
  73. m_value = o.m_value;
  74. log_postfix_event(m_value, "Copy construct");
  75. return *this;
  76. }
  77. template <class T>
  78. logged_adaptor(const T& i, const typename std::enable_if<std::is_convertible<T, Backend>::value>::type* = 0)
  79. : m_value(i)
  80. {
  81. log_postfix_event(m_value, "construct from arithmetic type");
  82. }
  83. template <class T>
  84. logged_adaptor(const logged_adaptor<T>& i, const typename std::enable_if<std::is_convertible<T, Backend>::value>::type* = 0)
  85. : m_value(i.value())
  86. {
  87. log_postfix_event(m_value, "construct from arithmetic type");
  88. }
  89. template <class T>
  90. typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value || std::is_convertible<T, Backend>::value, logged_adaptor&>::type operator=(const T& i)
  91. {
  92. log_prefix_event(m_value, i, "Assignment from arithmetic type");
  93. m_value = i;
  94. log_postfix_event(m_value, "Assignment from arithmetic type");
  95. return *this;
  96. }
  97. logged_adaptor& operator=(const char* s)
  98. {
  99. log_prefix_event(m_value, s, "Assignment from string type");
  100. m_value = s;
  101. log_postfix_event(m_value, "Assignment from string type");
  102. return *this;
  103. }
  104. void swap(logged_adaptor& o)
  105. {
  106. log_prefix_event(m_value, o.value(), "swap");
  107. std::swap(m_value, o.value());
  108. log_postfix_event(m_value, "swap");
  109. }
  110. std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
  111. {
  112. log_prefix_event(m_value, "Conversion to string");
  113. std::string s = m_value.str(digits, f);
  114. log_postfix_event(m_value, s, "Conversion to string");
  115. return s;
  116. }
  117. void negate()
  118. {
  119. log_prefix_event(m_value, "negate");
  120. m_value.negate();
  121. log_postfix_event(m_value, "negate");
  122. }
  123. int compare(const logged_adaptor& o) const
  124. {
  125. log_prefix_event(m_value, o.value(), "compare");
  126. int r = m_value.compare(o.value());
  127. log_postfix_event(m_value, r, "compare");
  128. return r;
  129. }
  130. template <class T>
  131. int compare(const T& i) const
  132. {
  133. log_prefix_event(m_value, i, "compare");
  134. int r = m_value.compare(i);
  135. log_postfix_event(m_value, r, "compare");
  136. return r;
  137. }
  138. Backend& value()
  139. {
  140. return m_value;
  141. }
  142. const Backend& value() const
  143. {
  144. return m_value;
  145. }
  146. template <class Archive>
  147. void serialize(Archive& ar, const unsigned int /*version*/)
  148. {
  149. log_prefix_event(m_value, "serialize");
  150. ar& boost::make_nvp("value", m_value);
  151. log_postfix_event(m_value, "serialize");
  152. }
  153. static unsigned default_precision() noexcept
  154. {
  155. return Backend::default_precision();
  156. }
  157. static void default_precision(unsigned v) noexcept
  158. {
  159. Backend::default_precision(v);
  160. }
  161. unsigned precision() const noexcept
  162. {
  163. return value().precision();
  164. }
  165. void precision(unsigned digits10) noexcept
  166. {
  167. value().precision(digits10);
  168. }
  169. };
  170. template <class T>
  171. inline const T& unwrap_logged_type(const T& a) { return a; }
  172. template <class Backend>
  173. inline const Backend& unwrap_logged_type(const logged_adaptor<Backend>& a) { return a.value(); }
  174. #define NON_MEMBER_OP1(name, str) \
  175. template <class Backend> \
  176. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result) \
  177. { \
  178. using default_ops::BOOST_JOIN(eval_, name); \
  179. log_prefix_event(result.value(), str); \
  180. BOOST_JOIN(eval_, name) \
  181. (result.value()); \
  182. log_postfix_event(result.value(), str); \
  183. }
  184. #define NON_MEMBER_OP2(name, str) \
  185. template <class Backend, class T> \
  186. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a) \
  187. { \
  188. using default_ops::BOOST_JOIN(eval_, name); \
  189. log_prefix_event(result.value(), unwrap_logged_type(a), str); \
  190. BOOST_JOIN(eval_, name) \
  191. (result.value(), unwrap_logged_type(a)); \
  192. log_postfix_event(result.value(), str); \
  193. } \
  194. template <class Backend> \
  195. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a) \
  196. { \
  197. using default_ops::BOOST_JOIN(eval_, name); \
  198. log_prefix_event(result.value(), unwrap_logged_type(a), str); \
  199. BOOST_JOIN(eval_, name) \
  200. (result.value(), unwrap_logged_type(a)); \
  201. log_postfix_event(result.value(), str); \
  202. }
  203. #define NON_MEMBER_OP3(name, str) \
  204. template <class Backend, class T, class U> \
  205. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const U& b) \
  206. { \
  207. using default_ops::BOOST_JOIN(eval_, name); \
  208. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str); \
  209. BOOST_JOIN(eval_, name) \
  210. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \
  211. log_postfix_event(result.value(), str); \
  212. } \
  213. template <class Backend, class T> \
  214. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const T& b) \
  215. { \
  216. using default_ops::BOOST_JOIN(eval_, name); \
  217. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str); \
  218. BOOST_JOIN(eval_, name) \
  219. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \
  220. log_postfix_event(result.value(), str); \
  221. } \
  222. template <class Backend, class T> \
  223. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const logged_adaptor<Backend>& b) \
  224. { \
  225. using default_ops::BOOST_JOIN(eval_, name); \
  226. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str); \
  227. BOOST_JOIN(eval_, name) \
  228. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \
  229. log_postfix_event(result.value(), str); \
  230. } \
  231. template <class Backend> \
  232. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const logged_adaptor<Backend>& b) \
  233. { \
  234. using default_ops::BOOST_JOIN(eval_, name); \
  235. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str); \
  236. BOOST_JOIN(eval_, name) \
  237. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \
  238. log_postfix_event(result.value(), str); \
  239. }
  240. #define NON_MEMBER_OP4(name, str) \
  241. template <class Backend, class T, class U, class V> \
  242. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const U& b, const V& c) \
  243. { \
  244. using default_ops::BOOST_JOIN(eval_, name); \
  245. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
  246. BOOST_JOIN(eval_, name) \
  247. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
  248. log_postfix_event(result.value(), str); \
  249. } \
  250. template <class Backend, class T> \
  251. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const logged_adaptor<Backend>& b, const T& c) \
  252. { \
  253. using default_ops::BOOST_JOIN(eval_, name); \
  254. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
  255. BOOST_JOIN(eval_, name) \
  256. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
  257. log_postfix_event(result.value(), str); \
  258. } \
  259. template <class Backend, class T> \
  260. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const T& b, const logged_adaptor<Backend>& c) \
  261. { \
  262. using default_ops::BOOST_JOIN(eval_, name); \
  263. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
  264. BOOST_JOIN(eval_, name) \
  265. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
  266. log_postfix_event(result.value(), str); \
  267. } \
  268. template <class Backend, class T> \
  269. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const logged_adaptor<Backend>& b, const logged_adaptor<Backend>& c) \
  270. { \
  271. using default_ops::BOOST_JOIN(eval_, name); \
  272. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
  273. BOOST_JOIN(eval_, name) \
  274. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
  275. log_postfix_event(result.value(), str); \
  276. } \
  277. template <class Backend> \
  278. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const logged_adaptor<Backend>& b, const logged_adaptor<Backend>& c) \
  279. { \
  280. using default_ops::BOOST_JOIN(eval_, name); \
  281. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
  282. BOOST_JOIN(eval_, name) \
  283. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
  284. log_postfix_event(result.value(), str); \
  285. } \
  286. template <class Backend, class T, class U> \
  287. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const T& b, const U& c) \
  288. { \
  289. using default_ops::BOOST_JOIN(eval_, name); \
  290. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
  291. BOOST_JOIN(eval_, name) \
  292. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
  293. log_postfix_event(result.value(), str); \
  294. }
  295. NON_MEMBER_OP2(add, "+=")
  296. NON_MEMBER_OP2(subtract, "-=")
  297. NON_MEMBER_OP2(multiply, "*=")
  298. NON_MEMBER_OP2(divide, "/=")
  299. template <class Backend, class R>
  300. inline void eval_convert_to(R* result, const logged_adaptor<Backend>& val)
  301. {
  302. using default_ops::eval_convert_to;
  303. log_prefix_event(val.value(), "convert_to");
  304. eval_convert_to(result, val.value());
  305. log_postfix_event(val.value(), *result, "convert_to");
  306. }
  307. template <class Backend, class Exp>
  308. inline void eval_frexp(logged_adaptor<Backend>& result, const logged_adaptor<Backend>& arg, Exp* exp)
  309. {
  310. log_prefix_event(arg.value(), "frexp");
  311. eval_frexp(result.value(), arg.value(), exp);
  312. log_postfix_event(result.value(), *exp, "frexp");
  313. }
  314. template <class Backend, class Exp>
  315. inline void eval_ldexp(logged_adaptor<Backend>& result, const logged_adaptor<Backend>& arg, Exp exp)
  316. {
  317. log_prefix_event(arg.value(), "ldexp");
  318. eval_ldexp(result.value(), arg.value(), exp);
  319. log_postfix_event(result.value(), exp, "ldexp");
  320. }
  321. template <class Backend, class Exp>
  322. inline void eval_scalbn(logged_adaptor<Backend>& result, const logged_adaptor<Backend>& arg, Exp exp)
  323. {
  324. log_prefix_event(arg.value(), "scalbn");
  325. eval_scalbn(result.value(), arg.value(), exp);
  326. log_postfix_event(result.value(), exp, "scalbn");
  327. }
  328. template <class Backend>
  329. inline typename Backend::exponent_type eval_ilogb(const logged_adaptor<Backend>& arg)
  330. {
  331. log_prefix_event(arg.value(), "ilogb");
  332. typename Backend::exponent_type r = eval_ilogb(arg.value());
  333. log_postfix_event(arg.value(), "ilogb");
  334. return r;
  335. }
  336. NON_MEMBER_OP2(floor, "floor")
  337. NON_MEMBER_OP2(ceil, "ceil")
  338. NON_MEMBER_OP2(sqrt, "sqrt")
  339. template <class Backend>
  340. inline int eval_fpclassify(const logged_adaptor<Backend>& arg)
  341. {
  342. using default_ops::eval_fpclassify;
  343. log_prefix_event(arg.value(), "fpclassify");
  344. int r = eval_fpclassify(arg.value());
  345. log_postfix_event(arg.value(), r, "fpclassify");
  346. return r;
  347. }
  348. /*********************************************************************
  349. *
  350. * Optional arithmetic operations come next:
  351. *
  352. *********************************************************************/
  353. NON_MEMBER_OP3(add, "+")
  354. NON_MEMBER_OP3(subtract, "-")
  355. NON_MEMBER_OP3(multiply, "*")
  356. NON_MEMBER_OP3(divide, "/")
  357. NON_MEMBER_OP3(multiply_add, "fused-multiply-add")
  358. NON_MEMBER_OP3(multiply_subtract, "fused-multiply-subtract")
  359. NON_MEMBER_OP4(multiply_add, "fused-multiply-add")
  360. NON_MEMBER_OP4(multiply_subtract, "fused-multiply-subtract")
  361. NON_MEMBER_OP1(increment, "increment")
  362. NON_MEMBER_OP1(decrement, "decrement")
  363. /*********************************************************************
  364. *
  365. * Optional integer operations come next:
  366. *
  367. *********************************************************************/
  368. NON_MEMBER_OP2(modulus, "%=")
  369. NON_MEMBER_OP3(modulus, "%")
  370. NON_MEMBER_OP2(bitwise_or, "|=")
  371. NON_MEMBER_OP3(bitwise_or, "|")
  372. NON_MEMBER_OP2(bitwise_and, "&=")
  373. NON_MEMBER_OP3(bitwise_and, "&")
  374. NON_MEMBER_OP2(bitwise_xor, "^=")
  375. NON_MEMBER_OP3(bitwise_xor, "^")
  376. NON_MEMBER_OP4(qr, "quotient-and-remainder")
  377. NON_MEMBER_OP2(complement, "~")
  378. template <class Backend>
  379. inline void eval_left_shift(logged_adaptor<Backend>& arg, std::size_t a)
  380. {
  381. using default_ops::eval_left_shift;
  382. log_prefix_event(arg.value(), a, "<<=");
  383. eval_left_shift(arg.value(), a);
  384. log_postfix_event(arg.value(), "<<=");
  385. }
  386. template <class Backend>
  387. inline void eval_left_shift(logged_adaptor<Backend>& arg, const logged_adaptor<Backend>& a, std::size_t b)
  388. {
  389. using default_ops::eval_left_shift;
  390. log_prefix_event(arg.value(), a, b, "<<");
  391. eval_left_shift(arg.value(), a.value(), b);
  392. log_postfix_event(arg.value(), "<<");
  393. }
  394. template <class Backend>
  395. inline void eval_right_shift(logged_adaptor<Backend>& arg, std::size_t a)
  396. {
  397. using default_ops::eval_right_shift;
  398. log_prefix_event(arg.value(), a, ">>=");
  399. eval_right_shift(arg.value(), a);
  400. log_postfix_event(arg.value(), ">>=");
  401. }
  402. template <class Backend>
  403. inline void eval_right_shift(logged_adaptor<Backend>& arg, const logged_adaptor<Backend>& a, std::size_t b)
  404. {
  405. using default_ops::eval_right_shift;
  406. log_prefix_event(arg.value(), a, b, ">>");
  407. eval_right_shift(arg.value(), a.value(), b);
  408. log_postfix_event(arg.value(), ">>");
  409. }
  410. template <class Backend, class T>
  411. inline unsigned eval_integer_modulus(const logged_adaptor<Backend>& arg, const T& a)
  412. {
  413. using default_ops::eval_integer_modulus;
  414. log_prefix_event(arg.value(), a, "integer-modulus");
  415. unsigned r = eval_integer_modulus(arg.value(), a);
  416. log_postfix_event(arg.value(), r, "integer-modulus");
  417. return r;
  418. }
  419. template <class Backend>
  420. inline unsigned eval_lsb(const logged_adaptor<Backend>& arg)
  421. {
  422. using default_ops::eval_lsb;
  423. log_prefix_event(arg.value(), "least-significant-bit");
  424. unsigned r = eval_lsb(arg.value());
  425. log_postfix_event(arg.value(), r, "least-significant-bit");
  426. return r;
  427. }
  428. template <class Backend>
  429. inline unsigned eval_msb(const logged_adaptor<Backend>& arg)
  430. {
  431. using default_ops::eval_msb;
  432. log_prefix_event(arg.value(), "most-significant-bit");
  433. unsigned r = eval_msb(arg.value());
  434. log_postfix_event(arg.value(), r, "most-significant-bit");
  435. return r;
  436. }
  437. template <class Backend>
  438. inline bool eval_bit_test(const logged_adaptor<Backend>& arg, unsigned a)
  439. {
  440. using default_ops::eval_bit_test;
  441. log_prefix_event(arg.value(), a, "bit-test");
  442. bool r = eval_bit_test(arg.value(), a);
  443. log_postfix_event(arg.value(), r, "bit-test");
  444. return r;
  445. }
  446. template <class Backend>
  447. inline void eval_bit_set(const logged_adaptor<Backend>& arg, unsigned a)
  448. {
  449. using default_ops::eval_bit_set;
  450. log_prefix_event(arg.value(), a, "bit-set");
  451. eval_bit_set(arg.value(), a);
  452. log_postfix_event(arg.value(), arg, "bit-set");
  453. }
  454. template <class Backend>
  455. inline void eval_bit_unset(const logged_adaptor<Backend>& arg, unsigned a)
  456. {
  457. using default_ops::eval_bit_unset;
  458. log_prefix_event(arg.value(), a, "bit-unset");
  459. eval_bit_unset(arg.value(), a);
  460. log_postfix_event(arg.value(), arg, "bit-unset");
  461. }
  462. template <class Backend>
  463. inline void eval_bit_flip(const logged_adaptor<Backend>& arg, unsigned a)
  464. {
  465. using default_ops::eval_bit_flip;
  466. log_prefix_event(arg.value(), a, "bit-flip");
  467. eval_bit_flip(arg.value(), a);
  468. log_postfix_event(arg.value(), arg, "bit-flip");
  469. }
  470. NON_MEMBER_OP3(gcd, "gcd")
  471. NON_MEMBER_OP3(lcm, "lcm")
  472. NON_MEMBER_OP4(powm, "powm")
  473. /*********************************************************************
  474. *
  475. * abs/fabs:
  476. *
  477. *********************************************************************/
  478. NON_MEMBER_OP2(abs, "abs")
  479. NON_MEMBER_OP2(fabs, "fabs")
  480. /*********************************************************************
  481. *
  482. * Floating point functions:
  483. *
  484. *********************************************************************/
  485. NON_MEMBER_OP2(trunc, "trunc")
  486. NON_MEMBER_OP2(round, "round")
  487. NON_MEMBER_OP2(exp, "exp")
  488. NON_MEMBER_OP2(log, "log")
  489. NON_MEMBER_OP2(log10, "log10")
  490. NON_MEMBER_OP2(sin, "sin")
  491. NON_MEMBER_OP2(cos, "cos")
  492. NON_MEMBER_OP2(tan, "tan")
  493. NON_MEMBER_OP2(asin, "asin")
  494. NON_MEMBER_OP2(acos, "acos")
  495. NON_MEMBER_OP2(atan, "atan")
  496. NON_MEMBER_OP2(sinh, "sinh")
  497. NON_MEMBER_OP2(cosh, "cosh")
  498. NON_MEMBER_OP2(tanh, "tanh")
  499. NON_MEMBER_OP2(logb, "logb")
  500. NON_MEMBER_OP3(fmod, "fmod")
  501. NON_MEMBER_OP3(pow, "pow")
  502. NON_MEMBER_OP3(atan2, "atan2")
  503. template <class Backend>
  504. int eval_signbit(const logged_adaptor<Backend>& val)
  505. {
  506. using default_ops::eval_signbit;
  507. return eval_signbit(val.value());
  508. }
  509. template <class Backend>
  510. std::size_t hash_value(const logged_adaptor<Backend>& val)
  511. {
  512. return hash_value(val.value());
  513. }
  514. #define NON_MEMBER_COMPLEX_TO_REAL(name, str) \
  515. template <class B1, class B2> \
  516. inline void BOOST_JOIN(eval_, name)(logged_adaptor<B1> & result, const logged_adaptor<B2>& a) \
  517. { \
  518. using default_ops::BOOST_JOIN(eval_, name); \
  519. log_prefix_event(a.value(), a.value(), str); \
  520. BOOST_JOIN(eval_, name) \
  521. (result.value(), a.value()); \
  522. log_postfix_event(result.value(), str); \
  523. } \
  524. template <class B1, class B2> \
  525. inline void BOOST_JOIN(eval_, name)(B1 & result, const logged_adaptor<B2>& a) \
  526. { \
  527. using default_ops::BOOST_JOIN(eval_, name); \
  528. log_prefix_event(a.value(), a.value(), str); \
  529. BOOST_JOIN(eval_, name) \
  530. (result, a.value()); \
  531. log_postfix_event(result, str); \
  532. }
  533. NON_MEMBER_COMPLEX_TO_REAL(real, "real")
  534. NON_MEMBER_COMPLEX_TO_REAL(imag, "imag")
  535. template <class T, class V, class U>
  536. inline void assign_components(logged_adaptor<T>& result, const V& v1, const U& v2)
  537. {
  538. assign_components(result.value(), v1, v2);
  539. }
  540. } // namespace backends
  541. using backends::logged_adaptor;
  542. template <class Backend>
  543. struct number_category<backends::logged_adaptor<Backend> > : public number_category<Backend>
  544. {};
  545. }} // namespace boost::multiprecision
  546. namespace std {
  547. template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
  548. class numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<Backend>, ExpressionTemplates> >
  549. : public std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> >
  550. {
  551. using base_type = std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> > ;
  552. using number_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<Backend>, ExpressionTemplates>;
  553. public:
  554. static number_type(min)() noexcept { return (base_type::min)(); }
  555. static number_type(max)() noexcept { return (base_type::max)(); }
  556. static number_type lowest() noexcept { return -(max)(); }
  557. static number_type epsilon() noexcept { return base_type::epsilon(); }
  558. static number_type round_error() noexcept { return epsilon() / 2; }
  559. static number_type infinity() noexcept { return base_type::infinity(); }
  560. static number_type quiet_NaN() noexcept { return base_type::quiet_NaN(); }
  561. static number_type signaling_NaN() noexcept { return base_type::signaling_NaN(); }
  562. static number_type denorm_min() noexcept { return base_type::denorm_min(); }
  563. };
  564. } // namespace std
  565. namespace boost {
  566. namespace math {
  567. namespace policies {
  568. template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
  569. struct precision<boost::multiprecision::number<boost::multiprecision::logged_adaptor<Backend>, ExpressionTemplates>, Policy>
  570. : public precision<boost::multiprecision::number<Backend, ExpressionTemplates>, Policy>
  571. {};
  572. }
  573. }} // namespace boost::math::policies
  574. #undef NON_MEMBER_OP1
  575. #undef NON_MEMBER_OP2
  576. #undef NON_MEMBER_OP3
  577. #undef NON_MEMBER_OP4
  578. #endif