logged_adaptor.hpp 34 KB

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