logged_adaptor.hpp 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  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_MP_LOGGED_ADAPTER_HPP
  6. #define BOOST_MP_LOGGED_ADAPTER_HPP
  7. #include <boost/multiprecision/detail/standalone_config.hpp>
  8. #include <boost/multiprecision/traits/extract_exponent_type.hpp>
  9. #include <boost/multiprecision/detail/integer_ops.hpp>
  10. namespace boost {
  11. namespace multiprecision {
  12. template <class Backend>
  13. inline void log_postfix_event(const Backend&, const char* /*event_description*/)
  14. {
  15. }
  16. template <class Backend, class T>
  17. inline void log_postfix_event(const Backend&, const T&, const char* /*event_description*/)
  18. {
  19. }
  20. template <class Backend>
  21. inline void log_prefix_event(const Backend&, const char* /*event_description*/)
  22. {
  23. }
  24. template <class Backend, class T>
  25. inline void log_prefix_event(const Backend&, const T&, const char* /*event_description*/)
  26. {
  27. }
  28. template <class Backend, class T, class U>
  29. inline void log_prefix_event(const Backend&, const T&, const U&, const char* /*event_description*/)
  30. {
  31. }
  32. template <class Backend, class T, class U, class V>
  33. inline void log_prefix_event(const Backend&, const T&, const U&, const V&, const char* /*event_description*/)
  34. {
  35. }
  36. namespace backends {
  37. template <class Backend>
  38. struct logged_adaptor
  39. {
  40. using signed_types = typename Backend::signed_types ;
  41. using unsigned_types = typename Backend::unsigned_types;
  42. using float_types = typename Backend::float_types ;
  43. using exponent_type = typename extract_exponent_type<Backend, number_category<Backend>::value>::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. // rvalue copy
  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. logged_adaptor& operator=(const logged_adaptor& o)
  72. {
  73. log_prefix_event(m_value, o.value(), "Assignment");
  74. m_value = o.m_value;
  75. log_postfix_event(m_value, "Copy construct");
  76. return *this;
  77. }
  78. template <class T>
  79. logged_adaptor(const T& i, const typename std::enable_if<std::is_convertible<T, Backend>::value>::type* = nullptr)
  80. : m_value(i)
  81. {
  82. log_postfix_event(m_value, "construct from arithmetic type");
  83. }
  84. template <class T>
  85. logged_adaptor(const logged_adaptor<T>& i, const typename std::enable_if<std::is_convertible<T, Backend>::value>::type* = nullptr)
  86. : m_value(i.value())
  87. {
  88. log_postfix_event(m_value, "construct from arithmetic type");
  89. }
  90. template <class T, class U>
  91. logged_adaptor(const T& i, const U& j, typename std::enable_if<std::is_constructible<Backend, const T&, const U&>::value>::type* = nullptr)
  92. : m_value(i, j)
  93. {
  94. log_postfix_event(m_value, "construct from a pair of arithmetic types");
  95. }
  96. template <class D = Backend>
  97. logged_adaptor(const Backend& i, unsigned digits10, typename std::enable_if<std::is_constructible<D, Backend const&, unsigned>::value>::type const* = nullptr)
  98. : m_value(i, digits10)
  99. {
  100. log_postfix_event(m_value, "construct from arithmetic type and precision");
  101. }
  102. template <class D = Backend>
  103. logged_adaptor(const logged_adaptor<Backend>& i, unsigned digits10, typename std::enable_if<std::is_constructible<D, Backend const&, unsigned>::value>::type const* = nullptr)
  104. : m_value(i.value(), digits10)
  105. {
  106. log_postfix_event(m_value, "construct from arithmetic type and precision");
  107. }
  108. template <class T>
  109. typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value || std::is_assignable<Backend, T>::value, logged_adaptor&>::type operator=(const T& i)
  110. {
  111. log_prefix_event(m_value, i, "Assignment from arithmetic type");
  112. m_value = i;
  113. log_postfix_event(m_value, "Assignment from arithmetic type");
  114. return *this;
  115. }
  116. logged_adaptor& operator=(const char* s)
  117. {
  118. log_prefix_event(m_value, s, "Assignment from string type");
  119. m_value = s;
  120. log_postfix_event(m_value, "Assignment from string type");
  121. return *this;
  122. }
  123. void swap(logged_adaptor& o)
  124. {
  125. log_prefix_event(m_value, o.value(), "swap");
  126. std::swap(m_value, o.value());
  127. log_postfix_event(m_value, "swap");
  128. }
  129. std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
  130. {
  131. log_prefix_event(m_value, "Conversion to string");
  132. std::string s = m_value.str(digits, f);
  133. log_postfix_event(m_value, s, "Conversion to string");
  134. return s;
  135. }
  136. void negate()
  137. {
  138. log_prefix_event(m_value, "negate");
  139. m_value.negate();
  140. log_postfix_event(m_value, "negate");
  141. }
  142. int compare(const logged_adaptor& o) const
  143. {
  144. log_prefix_event(m_value, o.value(), "compare");
  145. int r = m_value.compare(o.value());
  146. log_postfix_event(m_value, r, "compare");
  147. return r;
  148. }
  149. template <class T>
  150. int compare(const T& i) const
  151. {
  152. log_prefix_event(m_value, i, "compare");
  153. int r = m_value.compare(i);
  154. log_postfix_event(m_value, r, "compare");
  155. return r;
  156. }
  157. Backend& value()
  158. {
  159. return m_value;
  160. }
  161. const Backend& value() const
  162. {
  163. return m_value;
  164. }
  165. #ifndef BOOST_MP_STANDALONE
  166. template <class Archive>
  167. void serialize(Archive& ar, const unsigned int /*version*/)
  168. {
  169. log_prefix_event(m_value, "serialize");
  170. ar& boost::make_nvp("value", m_value);
  171. log_postfix_event(m_value, "serialize");
  172. }
  173. #endif
  174. static unsigned default_precision() noexcept
  175. {
  176. return Backend::default_precision();
  177. }
  178. static void default_precision(unsigned v) noexcept
  179. {
  180. Backend::default_precision(v);
  181. }
  182. static unsigned thread_default_precision() noexcept
  183. {
  184. return Backend::thread_default_precision();
  185. }
  186. static void thread_default_precision(unsigned v) noexcept
  187. {
  188. Backend::thread_default_precision(v);
  189. }
  190. unsigned precision() const noexcept
  191. {
  192. return value().precision();
  193. }
  194. void precision(unsigned digits10) noexcept
  195. {
  196. value().precision(digits10);
  197. }
  198. //
  199. // Variable precision options:
  200. //
  201. static constexpr variable_precision_options default_variable_precision_options()noexcept
  202. {
  203. return Backend::default_variable_precision_options();
  204. }
  205. static constexpr variable_precision_options thread_default_variable_precision_options()noexcept
  206. {
  207. return Backend::thread_default_variable_precision_options();
  208. }
  209. static BOOST_MP_CXX14_CONSTEXPR void default_variable_precision_options(variable_precision_options opts)
  210. {
  211. Backend::default_variable_precision_options(opts);
  212. }
  213. static BOOST_MP_CXX14_CONSTEXPR void thread_default_variable_precision_options(variable_precision_options opts)
  214. {
  215. Backend::thread_default_variable_precision_options(opts);
  216. }
  217. };
  218. template <class T>
  219. inline const T& unwrap_logged_type(const T& a) { return a; }
  220. template <class Backend>
  221. inline const Backend& unwrap_logged_type(const logged_adaptor<Backend>& a) { return a.value(); }
  222. #define NON_MEMBER_OP1(name, str) \
  223. template <class Backend> \
  224. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result) \
  225. { \
  226. using default_ops::BOOST_JOIN(eval_, name); \
  227. log_prefix_event(result.value(), str); \
  228. BOOST_JOIN(eval_, name) \
  229. (result.value()); \
  230. log_postfix_event(result.value(), str); \
  231. }
  232. #define NON_MEMBER_OP2(name, str) \
  233. template <class Backend, class T> \
  234. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a) \
  235. { \
  236. using default_ops::BOOST_JOIN(eval_, name); \
  237. log_prefix_event(result.value(), unwrap_logged_type(a), str); \
  238. BOOST_JOIN(eval_, name) \
  239. (result.value(), unwrap_logged_type(a)); \
  240. log_postfix_event(result.value(), str); \
  241. } \
  242. template <class Backend> \
  243. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a) \
  244. { \
  245. using default_ops::BOOST_JOIN(eval_, name); \
  246. log_prefix_event(result.value(), unwrap_logged_type(a), str); \
  247. BOOST_JOIN(eval_, name) \
  248. (result.value(), unwrap_logged_type(a)); \
  249. log_postfix_event(result.value(), str); \
  250. }
  251. #define NON_MEMBER_OP3(name, str) \
  252. template <class Backend, class T, class U> \
  253. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const U& b) \
  254. { \
  255. using default_ops::BOOST_JOIN(eval_, name); \
  256. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str); \
  257. BOOST_JOIN(eval_, name) \
  258. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \
  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) \
  263. { \
  264. using default_ops::BOOST_JOIN(eval_, name); \
  265. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str); \
  266. BOOST_JOIN(eval_, name) \
  267. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \
  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) \
  272. { \
  273. using default_ops::BOOST_JOIN(eval_, name); \
  274. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str); \
  275. BOOST_JOIN(eval_, name) \
  276. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \
  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) \
  281. { \
  282. using default_ops::BOOST_JOIN(eval_, name); \
  283. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str); \
  284. BOOST_JOIN(eval_, name) \
  285. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \
  286. log_postfix_event(result.value(), str); \
  287. }
  288. #define NON_MEMBER_OP4(name, str) \
  289. template <class Backend, class T, class U, class V> \
  290. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const U& b, const V& c) \
  291. { \
  292. using default_ops::BOOST_JOIN(eval_, name); \
  293. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
  294. BOOST_JOIN(eval_, name) \
  295. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
  296. log_postfix_event(result.value(), str); \
  297. } \
  298. template <class Backend, class T> \
  299. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const logged_adaptor<Backend>& b, const T& c) \
  300. { \
  301. using default_ops::BOOST_JOIN(eval_, name); \
  302. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
  303. BOOST_JOIN(eval_, name) \
  304. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
  305. log_postfix_event(result.value(), str); \
  306. } \
  307. template <class Backend, class T> \
  308. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const T& b, const logged_adaptor<Backend>& c) \
  309. { \
  310. using default_ops::BOOST_JOIN(eval_, name); \
  311. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
  312. BOOST_JOIN(eval_, name) \
  313. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
  314. log_postfix_event(result.value(), str); \
  315. } \
  316. template <class Backend, class T> \
  317. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const logged_adaptor<Backend>& b, const logged_adaptor<Backend>& c) \
  318. { \
  319. using default_ops::BOOST_JOIN(eval_, name); \
  320. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
  321. BOOST_JOIN(eval_, name) \
  322. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
  323. log_postfix_event(result.value(), str); \
  324. } \
  325. template <class Backend> \
  326. 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) \
  327. { \
  328. using default_ops::BOOST_JOIN(eval_, name); \
  329. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
  330. BOOST_JOIN(eval_, name) \
  331. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
  332. log_postfix_event(result.value(), str); \
  333. } \
  334. template <class Backend, class T, class U> \
  335. inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const T& b, const U& c) \
  336. { \
  337. using default_ops::BOOST_JOIN(eval_, name); \
  338. log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
  339. BOOST_JOIN(eval_, name) \
  340. (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
  341. log_postfix_event(result.value(), str); \
  342. }
  343. NON_MEMBER_OP2(add, "+=")
  344. NON_MEMBER_OP2(subtract, "-=")
  345. NON_MEMBER_OP2(multiply, "*=")
  346. NON_MEMBER_OP2(divide, "/=")
  347. template <class Backend, class R>
  348. inline void eval_convert_to(R* result, const logged_adaptor<Backend>& val)
  349. {
  350. using default_ops::eval_convert_to;
  351. log_prefix_event(val.value(), "convert_to");
  352. eval_convert_to(result, val.value());
  353. log_postfix_event(val.value(), *result, "convert_to");
  354. }
  355. template <class Backend, class R>
  356. inline void eval_convert_to(logged_adaptor<R>* result, const logged_adaptor<Backend>& val)
  357. {
  358. using default_ops::eval_convert_to;
  359. log_prefix_event(val.value(), "convert_to");
  360. eval_convert_to(&result->value(), val.value());
  361. log_postfix_event(val.value(), &result->value(), "convert_to");
  362. }
  363. template <class Backend, class R>
  364. inline void eval_convert_to(logged_adaptor<R>* result, const Backend& val)
  365. {
  366. using default_ops::eval_convert_to;
  367. log_prefix_event(val, "convert_to");
  368. eval_convert_to(&result->value(), val);
  369. log_postfix_event(val, &result->value(), "convert_to");
  370. }
  371. template <class Backend>
  372. inline void eval_convert_to(std::complex<float>* result, const logged_adaptor<Backend>& val)
  373. {
  374. using default_ops::eval_convert_to;
  375. log_prefix_event(val.value(), "convert_to");
  376. eval_convert_to(result, val.value());
  377. log_postfix_event(val.value(), *result, "convert_to");
  378. }
  379. template <class Backend>
  380. inline void eval_convert_to(std::complex<double>* result, const logged_adaptor<Backend>& val)
  381. {
  382. using default_ops::eval_convert_to;
  383. log_prefix_event(val.value(), "convert_to");
  384. eval_convert_to(result, val.value());
  385. log_postfix_event(val.value(), *result, "convert_to");
  386. }
  387. template <class Backend>
  388. inline void eval_convert_to(std::complex<long double>* result, const logged_adaptor<Backend>& val)
  389. {
  390. using default_ops::eval_convert_to;
  391. log_prefix_event(val.value(), "convert_to");
  392. eval_convert_to(result, val.value());
  393. log_postfix_event(val.value(), *result, "convert_to");
  394. }
  395. template <class Backend, class Exp>
  396. inline void eval_frexp(logged_adaptor<Backend>& result, const logged_adaptor<Backend>& arg, Exp* exp)
  397. {
  398. log_prefix_event(arg.value(), "frexp");
  399. eval_frexp(result.value(), arg.value(), exp);
  400. log_postfix_event(result.value(), *exp, "frexp");
  401. }
  402. template <class Backend, class Exp>
  403. inline void eval_ldexp(logged_adaptor<Backend>& result, const logged_adaptor<Backend>& arg, Exp exp)
  404. {
  405. log_prefix_event(arg.value(), "ldexp");
  406. eval_ldexp(result.value(), arg.value(), exp);
  407. log_postfix_event(result.value(), exp, "ldexp");
  408. }
  409. template <class Backend, class Exp>
  410. inline void eval_scalbn(logged_adaptor<Backend>& result, const logged_adaptor<Backend>& arg, Exp exp)
  411. {
  412. using default_ops::eval_scalbn;
  413. log_prefix_event(arg.value(), "scalbn");
  414. eval_scalbn(result.value(), arg.value(), exp);
  415. log_postfix_event(result.value(), exp, "scalbn");
  416. }
  417. template <class Backend>
  418. inline typename Backend::exponent_type eval_ilogb(const logged_adaptor<Backend>& arg)
  419. {
  420. using default_ops::eval_ilogb;
  421. log_prefix_event(arg.value(), "ilogb");
  422. typename Backend::exponent_type r = eval_ilogb(arg.value());
  423. log_postfix_event(arg.value(), "ilogb");
  424. return r;
  425. }
  426. NON_MEMBER_OP2(floor, "floor")
  427. NON_MEMBER_OP2(ceil, "ceil")
  428. NON_MEMBER_OP2(sqrt, "sqrt")
  429. template <class Backend>
  430. inline int eval_fpclassify(const logged_adaptor<Backend>& arg)
  431. {
  432. using default_ops::eval_fpclassify;
  433. log_prefix_event(arg.value(), "fpclassify");
  434. int r = eval_fpclassify(arg.value());
  435. log_postfix_event(arg.value(), r, "fpclassify");
  436. return r;
  437. }
  438. /*********************************************************************
  439. *
  440. * Optional arithmetic operations come next:
  441. *
  442. *********************************************************************/
  443. NON_MEMBER_OP3(add, "+")
  444. NON_MEMBER_OP3(subtract, "-")
  445. NON_MEMBER_OP3(multiply, "*")
  446. NON_MEMBER_OP3(divide, "/")
  447. NON_MEMBER_OP3(multiply_add, "fused-multiply-add")
  448. NON_MEMBER_OP3(multiply_subtract, "fused-multiply-subtract")
  449. NON_MEMBER_OP4(multiply_add, "fused-multiply-add")
  450. NON_MEMBER_OP4(multiply_subtract, "fused-multiply-subtract")
  451. NON_MEMBER_OP1(increment, "increment")
  452. NON_MEMBER_OP1(decrement, "decrement")
  453. /*********************************************************************
  454. *
  455. * Optional integer operations come next:
  456. *
  457. *********************************************************************/
  458. NON_MEMBER_OP2(modulus, "%=")
  459. NON_MEMBER_OP3(modulus, "%")
  460. NON_MEMBER_OP2(bitwise_or, "|=")
  461. NON_MEMBER_OP3(bitwise_or, "|")
  462. NON_MEMBER_OP2(bitwise_and, "&=")
  463. NON_MEMBER_OP3(bitwise_and, "&")
  464. NON_MEMBER_OP2(bitwise_xor, "^=")
  465. NON_MEMBER_OP3(bitwise_xor, "^")
  466. NON_MEMBER_OP4(qr, "quotient-and-remainder")
  467. NON_MEMBER_OP2(complement, "~")
  468. template <class Backend>
  469. inline void eval_left_shift(logged_adaptor<Backend>& arg, std::size_t a)
  470. {
  471. using default_ops::eval_left_shift;
  472. log_prefix_event(arg.value(), a, "<<=");
  473. eval_left_shift(arg.value(), a);
  474. log_postfix_event(arg.value(), "<<=");
  475. }
  476. template <class Backend>
  477. inline void eval_left_shift(logged_adaptor<Backend>& arg, const logged_adaptor<Backend>& a, std::size_t b)
  478. {
  479. using default_ops::eval_left_shift;
  480. log_prefix_event(arg.value(), a, b, "<<");
  481. eval_left_shift(arg.value(), a.value(), b);
  482. log_postfix_event(arg.value(), "<<");
  483. }
  484. template <class Backend>
  485. inline void eval_right_shift(logged_adaptor<Backend>& arg, std::size_t a)
  486. {
  487. using default_ops::eval_right_shift;
  488. log_prefix_event(arg.value(), a, ">>=");
  489. eval_right_shift(arg.value(), a);
  490. log_postfix_event(arg.value(), ">>=");
  491. }
  492. template <class Backend>
  493. inline void eval_right_shift(logged_adaptor<Backend>& arg, const logged_adaptor<Backend>& a, std::size_t b)
  494. {
  495. using default_ops::eval_right_shift;
  496. log_prefix_event(arg.value(), a, b, ">>");
  497. eval_right_shift(arg.value(), a.value(), b);
  498. log_postfix_event(arg.value(), ">>");
  499. }
  500. template <class Backend, class T>
  501. inline T eval_integer_modulus(const logged_adaptor<Backend>& arg, const T& a)
  502. {
  503. using default_ops::eval_integer_modulus;
  504. log_prefix_event(arg.value(), a, "integer-modulus");
  505. T r = eval_integer_modulus(arg.value(), a);
  506. log_postfix_event(arg.value(), r, "integer-modulus");
  507. return r;
  508. }
  509. template <class Backend>
  510. inline std::size_t eval_lsb(const logged_adaptor<Backend>& arg)
  511. {
  512. using default_ops::eval_lsb;
  513. log_prefix_event(arg.value(), "least-significant-bit");
  514. std::size_t r = eval_lsb(arg.value());
  515. log_postfix_event(arg.value(), r, "least-significant-bit");
  516. return r;
  517. }
  518. template <class Backend>
  519. inline std::size_t eval_msb(const logged_adaptor<Backend>& arg)
  520. {
  521. using default_ops::eval_msb;
  522. log_prefix_event(arg.value(), "most-significant-bit");
  523. std::size_t r = eval_msb(arg.value());
  524. log_postfix_event(arg.value(), r, "most-significant-bit");
  525. return r;
  526. }
  527. template <class Backend>
  528. inline bool eval_bit_test(const logged_adaptor<Backend>& arg, std::size_t a)
  529. {
  530. using default_ops::eval_bit_test;
  531. log_prefix_event(arg.value(), a, "bit-test");
  532. bool r = eval_bit_test(arg.value(), a);
  533. log_postfix_event(arg.value(), r, "bit-test");
  534. return r;
  535. }
  536. template <class Backend>
  537. inline void eval_bit_set(const logged_adaptor<Backend>& arg, std::size_t a)
  538. {
  539. using default_ops::eval_bit_set;
  540. log_prefix_event(arg.value(), a, "bit-set");
  541. eval_bit_set(arg.value(), a);
  542. log_postfix_event(arg.value(), arg, "bit-set");
  543. }
  544. template <class Backend>
  545. inline void eval_bit_unset(const logged_adaptor<Backend>& arg, std::size_t a)
  546. {
  547. using default_ops::eval_bit_unset;
  548. log_prefix_event(arg.value(), a, "bit-unset");
  549. eval_bit_unset(arg.value(), a);
  550. log_postfix_event(arg.value(), arg, "bit-unset");
  551. }
  552. template <class Backend>
  553. inline void eval_bit_flip(const logged_adaptor<Backend>& arg, std::size_t a)
  554. {
  555. using default_ops::eval_bit_flip;
  556. log_prefix_event(arg.value(), a, "bit-flip");
  557. eval_bit_flip(arg.value(), a);
  558. log_postfix_event(arg.value(), arg, "bit-flip");
  559. }
  560. NON_MEMBER_OP3(gcd, "gcd")
  561. NON_MEMBER_OP3(lcm, "lcm")
  562. NON_MEMBER_OP4(powm, "powm")
  563. /*********************************************************************
  564. *
  565. * abs/fabs:
  566. *
  567. *********************************************************************/
  568. NON_MEMBER_OP2(abs, "abs")
  569. NON_MEMBER_OP2(fabs, "fabs")
  570. /*********************************************************************
  571. *
  572. * Floating point functions:
  573. *
  574. *********************************************************************/
  575. NON_MEMBER_OP2(trunc, "trunc")
  576. NON_MEMBER_OP2(round, "round")
  577. NON_MEMBER_OP2(exp, "exp")
  578. NON_MEMBER_OP2(log, "log")
  579. NON_MEMBER_OP2(log10, "log10")
  580. NON_MEMBER_OP2(sin, "sin")
  581. NON_MEMBER_OP2(cos, "cos")
  582. NON_MEMBER_OP2(tan, "tan")
  583. NON_MEMBER_OP2(asin, "asin")
  584. NON_MEMBER_OP2(acos, "acos")
  585. NON_MEMBER_OP2(atan, "atan")
  586. NON_MEMBER_OP2(sinh, "sinh")
  587. NON_MEMBER_OP2(cosh, "cosh")
  588. NON_MEMBER_OP2(tanh, "tanh")
  589. NON_MEMBER_OP2(logb, "logb")
  590. NON_MEMBER_OP3(fmod, "fmod")
  591. NON_MEMBER_OP3(pow, "pow")
  592. NON_MEMBER_OP3(atan2, "atan2")
  593. NON_MEMBER_OP2(asinh, "asinh")
  594. NON_MEMBER_OP2(acosh, "acosh")
  595. NON_MEMBER_OP2(atanh, "atanh")
  596. NON_MEMBER_OP2(conj, "conj")
  597. template <class Backend>
  598. int eval_signbit(const logged_adaptor<Backend>& val)
  599. {
  600. using default_ops::eval_signbit;
  601. return eval_signbit(val.value());
  602. }
  603. template <class Backend>
  604. std::size_t hash_value(const logged_adaptor<Backend>& val)
  605. {
  606. return hash_value(val.value());
  607. }
  608. template <class Backend, expression_template_option ExpressionTemplates>
  609. inline typename std::enable_if<number_category<Backend>::value == number_kind_rational, typename number<logged_adaptor<Backend>, ExpressionTemplates>::value_type>::type
  610. numerator(const number<logged_adaptor<Backend>, ExpressionTemplates>& arg)
  611. {
  612. number<Backend, ExpressionTemplates> t(arg.backend().value());
  613. return numerator(t).backend();
  614. }
  615. template <class Backend, expression_template_option ExpressionTemplates>
  616. inline typename std::enable_if<number_category<Backend>::value == number_kind_rational, typename number<logged_adaptor<Backend>, ExpressionTemplates>::value_type>::type
  617. denominator(const number<logged_adaptor<Backend>, ExpressionTemplates>& arg)
  618. {
  619. number<Backend, ExpressionTemplates> t(arg.backend().value());
  620. return denominator(t).backend();
  621. }
  622. template <class To, class From>
  623. inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(To& to, const logged_adaptor<From>& from)
  624. {
  625. using default_ops::eval_set_real;
  626. log_prefix_event(to, from.value(), "Set real part");
  627. eval_set_real(to, from.value());
  628. log_postfix_event(to, from.value(), "Set real part");
  629. }
  630. template <class To, class From>
  631. inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(logged_adaptor<To>& to, const logged_adaptor<From>& from)
  632. {
  633. using default_ops::eval_set_real;
  634. log_prefix_event(to.value(), from.value(), "Set real part");
  635. eval_set_real(to.value(), from.value());
  636. log_postfix_event(to.value(), from.value(), "Set real part");
  637. }
  638. template <class To, class From>
  639. inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(logged_adaptor<To>& to, const From& from)
  640. {
  641. using default_ops::eval_set_real;
  642. log_prefix_event(to.value(), from, "Set real part");
  643. eval_set_real(to.value(), from);
  644. log_postfix_event(to.value(), from, "Set real part");
  645. }
  646. template <class To, class From>
  647. inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(To& to, const logged_adaptor<From>& from)
  648. {
  649. using default_ops::eval_set_imag;
  650. log_prefix_event(to, from.value(), "Set imag part");
  651. eval_set_imag(to, from.value());
  652. log_postfix_event(to, from.value(), "Set imag part");
  653. }
  654. template <class To, class From>
  655. inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(logged_adaptor<To>& to, const logged_adaptor<From>& from)
  656. {
  657. using default_ops::eval_set_imag;
  658. log_prefix_event(to.value(), from.value(), "Set imag part");
  659. eval_set_imag(to.value(), from.value());
  660. log_postfix_event(to.value(), from.value(), "Set imag part");
  661. }
  662. template <class To, class From>
  663. inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(logged_adaptor<To>& to, const From& from)
  664. {
  665. using default_ops::eval_set_imag;
  666. log_prefix_event(to.value(), from, "Set imag part");
  667. eval_set_imag(to.value(), from);
  668. log_postfix_event(to.value(), from, "Set imag part");
  669. }
  670. #define NON_MEMBER_COMPLEX_TO_REAL(name, str) \
  671. template <class B1, class B2> \
  672. inline void BOOST_JOIN(eval_, name)(logged_adaptor<B1> & result, const logged_adaptor<B2>& a) \
  673. { \
  674. using default_ops::BOOST_JOIN(eval_, name); \
  675. log_prefix_event(a.value(), a.value(), str); \
  676. BOOST_JOIN(eval_, name) \
  677. (result.value(), a.value()); \
  678. log_postfix_event(result.value(), str); \
  679. } \
  680. template <class B1, class B2> \
  681. inline void BOOST_JOIN(eval_, name)(B1 & result, const logged_adaptor<B2>& a) \
  682. { \
  683. using default_ops::BOOST_JOIN(eval_, name); \
  684. log_prefix_event(a.value(), a.value(), str); \
  685. BOOST_JOIN(eval_, name) \
  686. (result, a.value()); \
  687. log_postfix_event(result, str); \
  688. }
  689. NON_MEMBER_COMPLEX_TO_REAL(real, "real")
  690. NON_MEMBER_COMPLEX_TO_REAL(imag, "imag")
  691. template <class T, class V, class U>
  692. inline void assign_components(logged_adaptor<T>& result, const V& v1, const U& v2)
  693. {
  694. using default_ops::assign_components;
  695. assign_components(result.value(), unwrap_logged_type(v1), unwrap_logged_type(v2));
  696. }
  697. } // namespace backends
  698. namespace detail {
  699. template <class Backend>
  700. struct is_variable_precision<logged_adaptor<Backend> > : public is_variable_precision<Backend>
  701. {};
  702. #ifdef BOOST_HAS_INT128
  703. template <class Backend>
  704. struct is_convertible_arithmetic<int128_type, logged_adaptor<Backend> > : public is_convertible_arithmetic<int128_type, Backend>
  705. {};
  706. template <class Backend>
  707. struct is_convertible_arithmetic<uint128_type, logged_adaptor<Backend> > : public is_convertible_arithmetic<uint128_type, Backend>
  708. {};
  709. #endif
  710. #ifdef BOOST_HAS_FLOAT128
  711. template <class Backend>
  712. struct is_convertible_arithmetic<float128_type, logged_adaptor<Backend> > : public is_convertible_arithmetic<float128_type, Backend>
  713. {};
  714. #endif
  715. } // namespace detail
  716. template <class Backend>
  717. struct number_category<backends::logged_adaptor<Backend> > : public number_category<Backend>
  718. {};
  719. template <class Backend, expression_template_option ExpressionTemplates>
  720. struct component_type<number<logged_adaptor<Backend>, ExpressionTemplates>>
  721. {
  722. //
  723. // We'll make the component_type also a logged_adaptor:
  724. //
  725. using base_component_type = typename component_type<number<Backend, ExpressionTemplates>>::type;
  726. using base_component_backend = typename base_component_type::backend_type;
  727. using type = number<logged_adaptor<base_component_backend>, ExpressionTemplates>;
  728. };
  729. template <class Backend>
  730. struct is_interval_number<backends::logged_adaptor<Backend> > : public is_interval_number<Backend> {};
  731. }} // namespace boost::multiprecision
  732. namespace std {
  733. template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
  734. class numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<Backend>, ExpressionTemplates> >
  735. : public std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> >
  736. {
  737. using base_type = std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> > ;
  738. using number_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<Backend>, ExpressionTemplates>;
  739. public:
  740. static number_type(min)() noexcept { return (base_type::min)(); }
  741. static number_type(max)() noexcept { return (base_type::max)(); }
  742. static number_type lowest() noexcept { return -(max)(); }
  743. static number_type epsilon() noexcept { return base_type::epsilon(); }
  744. static number_type round_error() noexcept { return epsilon() / 2; }
  745. static number_type infinity() noexcept { return base_type::infinity(); }
  746. static number_type quiet_NaN() noexcept { return base_type::quiet_NaN(); }
  747. static number_type signaling_NaN() noexcept { return base_type::signaling_NaN(); }
  748. static number_type denorm_min() noexcept { return base_type::denorm_min(); }
  749. };
  750. } // namespace std
  751. #ifdef BOOST_MP_MATH_AVAILABLE
  752. namespace boost {
  753. namespace math {
  754. namespace policies {
  755. template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
  756. struct precision<boost::multiprecision::number<boost::multiprecision::logged_adaptor<Backend>, ExpressionTemplates>, Policy>
  757. : public precision<boost::multiprecision::number<Backend, ExpressionTemplates>, Policy>
  758. {};
  759. }
  760. }} // namespace boost::math::policies
  761. #endif // BOOST_MP_MATH_AVAILABLE
  762. #undef NON_MEMBER_OP1
  763. #undef NON_MEMBER_OP2
  764. #undef NON_MEMBER_OP3
  765. #undef NON_MEMBER_OP4
  766. #endif