File indexing completed on 2025-01-30 09:48:47
0001
0002
0003
0004
0005
0006 #ifndef BOOST_MP_LOGGED_ADAPTER_HPP
0007 #define BOOST_MP_LOGGED_ADAPTER_HPP
0008
0009 #include <boost/multiprecision/detail/standalone_config.hpp>
0010 #include <boost/multiprecision/traits/extract_exponent_type.hpp>
0011 #include <boost/multiprecision/detail/integer_ops.hpp>
0012
0013 namespace boost {
0014 namespace multiprecision {
0015
0016 template <class Backend>
0017 inline void log_postfix_event(const Backend&, const char* )
0018 {
0019 }
0020 template <class Backend, class T>
0021 inline void log_postfix_event(const Backend&, const T&, const char* )
0022 {
0023 }
0024 template <class Backend>
0025 inline void log_prefix_event(const Backend&, const char* )
0026 {
0027 }
0028 template <class Backend, class T>
0029 inline void log_prefix_event(const Backend&, const T&, const char* )
0030 {
0031 }
0032 template <class Backend, class T, class U>
0033 inline void log_prefix_event(const Backend&, const T&, const U&, const char* )
0034 {
0035 }
0036 template <class Backend, class T, class U, class V>
0037 inline void log_prefix_event(const Backend&, const T&, const U&, const V&, const char* )
0038 {
0039 }
0040
0041 namespace backends {
0042
0043 template <class Backend>
0044 struct logged_adaptor
0045 {
0046 using signed_types = typename Backend::signed_types ;
0047 using unsigned_types = typename Backend::unsigned_types;
0048 using float_types = typename Backend::float_types ;
0049 using exponent_type = typename extract_exponent_type<Backend, number_category<Backend>::value>::type;
0050
0051 private:
0052 Backend m_value;
0053
0054 public:
0055 logged_adaptor()
0056 {
0057 log_postfix_event(m_value, "Default construct");
0058 }
0059 logged_adaptor(const logged_adaptor& o)
0060 {
0061 log_prefix_event(m_value, o.value(), "Copy construct");
0062 m_value = o.m_value;
0063 log_postfix_event(m_value, "Copy construct");
0064 }
0065
0066 logged_adaptor(logged_adaptor&& o)
0067 {
0068 log_prefix_event(m_value, o.value(), "Move construct");
0069 m_value = static_cast<Backend&&>(o.m_value);
0070 log_postfix_event(m_value, "Move construct");
0071 }
0072 logged_adaptor& operator=(logged_adaptor&& o)
0073 {
0074 log_prefix_event(m_value, o.value(), "Move Assignment");
0075 m_value = static_cast<Backend&&>(o.m_value);
0076 log_postfix_event(m_value, "Move construct");
0077 return *this;
0078 }
0079 logged_adaptor& operator=(const logged_adaptor& o)
0080 {
0081 log_prefix_event(m_value, o.value(), "Assignment");
0082 m_value = o.m_value;
0083 log_postfix_event(m_value, "Copy construct");
0084 return *this;
0085 }
0086 template <class T>
0087 logged_adaptor(const T& i, const typename std::enable_if<std::is_convertible<T, Backend>::value>::type* = nullptr)
0088 : m_value(i)
0089 {
0090 log_postfix_event(m_value, "construct from arithmetic type");
0091 }
0092 template <class T>
0093 logged_adaptor(const logged_adaptor<T>& i, const typename std::enable_if<std::is_convertible<T, Backend>::value>::type* = nullptr)
0094 : m_value(i.value())
0095 {
0096 log_postfix_event(m_value, "construct from arithmetic type");
0097 }
0098 template <class T, class U>
0099 logged_adaptor(const T& i, const U& j, typename std::enable_if<std::is_constructible<Backend, const T&, const U&>::value>::type* = nullptr)
0100 : m_value(i, j)
0101 {
0102 log_postfix_event(m_value, "construct from a pair of arithmetic types");
0103 }
0104 template <class D = Backend>
0105 logged_adaptor(const Backend& i, unsigned digits10, typename std::enable_if<std::is_constructible<D, Backend const&, unsigned>::value>::type const* = nullptr)
0106 : m_value(i, digits10)
0107 {
0108 log_postfix_event(m_value, "construct from arithmetic type and precision");
0109 }
0110 template <class D = Backend>
0111 logged_adaptor(const logged_adaptor<Backend>& i, unsigned digits10, typename std::enable_if<std::is_constructible<D, Backend const&, unsigned>::value>::type const* = nullptr)
0112 : m_value(i.value(), digits10)
0113 {
0114 log_postfix_event(m_value, "construct from arithmetic type and precision");
0115 }
0116 template <class T>
0117 typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value || std::is_assignable<Backend, T>::value, logged_adaptor&>::type operator=(const T& i)
0118 {
0119 log_prefix_event(m_value, i, "Assignment from arithmetic type");
0120 m_value = i;
0121 log_postfix_event(m_value, "Assignment from arithmetic type");
0122 return *this;
0123 }
0124 logged_adaptor& operator=(const char* s)
0125 {
0126 log_prefix_event(m_value, s, "Assignment from string type");
0127 m_value = s;
0128 log_postfix_event(m_value, "Assignment from string type");
0129 return *this;
0130 }
0131 void swap(logged_adaptor& o)
0132 {
0133 log_prefix_event(m_value, o.value(), "swap");
0134 std::swap(m_value, o.value());
0135 log_postfix_event(m_value, "swap");
0136 }
0137 std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
0138 {
0139 log_prefix_event(m_value, "Conversion to string");
0140 std::string s = m_value.str(digits, f);
0141 log_postfix_event(m_value, s, "Conversion to string");
0142 return s;
0143 }
0144 void negate()
0145 {
0146 log_prefix_event(m_value, "negate");
0147 m_value.negate();
0148 log_postfix_event(m_value, "negate");
0149 }
0150 int compare(const logged_adaptor& o) const
0151 {
0152 log_prefix_event(m_value, o.value(), "compare");
0153 int r = m_value.compare(o.value());
0154 log_postfix_event(m_value, r, "compare");
0155 return r;
0156 }
0157 template <class T>
0158 int compare(const T& i) const
0159 {
0160 log_prefix_event(m_value, i, "compare");
0161 int r = m_value.compare(i);
0162 log_postfix_event(m_value, r, "compare");
0163 return r;
0164 }
0165 Backend& value()
0166 {
0167 return m_value;
0168 }
0169 const Backend& value() const
0170 {
0171 return m_value;
0172 }
0173
0174 #ifndef BOOST_MP_STANDALONE
0175 template <class Archive>
0176 void serialize(Archive& ar, const unsigned int )
0177 {
0178 log_prefix_event(m_value, "serialize");
0179 ar& boost::make_nvp("value", m_value);
0180 log_postfix_event(m_value, "serialize");
0181 }
0182 #endif
0183
0184 static unsigned default_precision() noexcept
0185 {
0186 return Backend::default_precision();
0187 }
0188 static void default_precision(unsigned v) noexcept
0189 {
0190 Backend::default_precision(v);
0191 }
0192 static unsigned thread_default_precision() noexcept
0193 {
0194 return Backend::thread_default_precision();
0195 }
0196 static void thread_default_precision(unsigned v) noexcept
0197 {
0198 Backend::thread_default_precision(v);
0199 }
0200 unsigned precision() const noexcept
0201 {
0202 return value().precision();
0203 }
0204 void precision(unsigned digits10) noexcept
0205 {
0206 value().precision(digits10);
0207 }
0208
0209
0210
0211 static constexpr variable_precision_options default_variable_precision_options()noexcept
0212 {
0213 return Backend::default_variable_precision_options();
0214 }
0215 static constexpr variable_precision_options thread_default_variable_precision_options()noexcept
0216 {
0217 return Backend::thread_default_variable_precision_options();
0218 }
0219 static BOOST_MP_CXX14_CONSTEXPR void default_variable_precision_options(variable_precision_options opts)
0220 {
0221 Backend::default_variable_precision_options(opts);
0222 }
0223 static BOOST_MP_CXX14_CONSTEXPR void thread_default_variable_precision_options(variable_precision_options opts)
0224 {
0225 Backend::thread_default_variable_precision_options(opts);
0226 }
0227 };
0228
0229 template <class T>
0230 inline const T& unwrap_logged_type(const T& a) { return a; }
0231 template <class Backend>
0232 inline const Backend& unwrap_logged_type(const logged_adaptor<Backend>& a) { return a.value(); }
0233
0234 #define NON_MEMBER_OP1(name, str) \
0235 template <class Backend> \
0236 inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result) \
0237 { \
0238 using default_ops::BOOST_JOIN(eval_, name); \
0239 log_prefix_event(result.value(), str); \
0240 BOOST_JOIN(eval_, name) \
0241 (result.value()); \
0242 log_postfix_event(result.value(), str); \
0243 }
0244
0245 #define NON_MEMBER_OP2(name, str) \
0246 template <class Backend, class T> \
0247 inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a) \
0248 { \
0249 using default_ops::BOOST_JOIN(eval_, name); \
0250 log_prefix_event(result.value(), unwrap_logged_type(a), str); \
0251 BOOST_JOIN(eval_, name) \
0252 (result.value(), unwrap_logged_type(a)); \
0253 log_postfix_event(result.value(), str); \
0254 } \
0255 template <class Backend> \
0256 inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a) \
0257 { \
0258 using default_ops::BOOST_JOIN(eval_, name); \
0259 log_prefix_event(result.value(), unwrap_logged_type(a), str); \
0260 BOOST_JOIN(eval_, name) \
0261 (result.value(), unwrap_logged_type(a)); \
0262 log_postfix_event(result.value(), str); \
0263 }
0264
0265 #define NON_MEMBER_OP3(name, str) \
0266 template <class Backend, class T, class U> \
0267 inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const U& b) \
0268 { \
0269 using default_ops::BOOST_JOIN(eval_, name); \
0270 log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str); \
0271 BOOST_JOIN(eval_, name) \
0272 (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \
0273 log_postfix_event(result.value(), str); \
0274 } \
0275 template <class Backend, class T> \
0276 inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const T& b) \
0277 { \
0278 using default_ops::BOOST_JOIN(eval_, name); \
0279 log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str); \
0280 BOOST_JOIN(eval_, name) \
0281 (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \
0282 log_postfix_event(result.value(), str); \
0283 } \
0284 template <class Backend, class T> \
0285 inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const logged_adaptor<Backend>& b) \
0286 { \
0287 using default_ops::BOOST_JOIN(eval_, name); \
0288 log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str); \
0289 BOOST_JOIN(eval_, name) \
0290 (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \
0291 log_postfix_event(result.value(), str); \
0292 } \
0293 template <class Backend> \
0294 inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const logged_adaptor<Backend>& b) \
0295 { \
0296 using default_ops::BOOST_JOIN(eval_, name); \
0297 log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str); \
0298 BOOST_JOIN(eval_, name) \
0299 (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \
0300 log_postfix_event(result.value(), str); \
0301 }
0302
0303 #define NON_MEMBER_OP4(name, str) \
0304 template <class Backend, class T, class U, class V> \
0305 inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const U& b, const V& c) \
0306 { \
0307 using default_ops::BOOST_JOIN(eval_, name); \
0308 log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
0309 BOOST_JOIN(eval_, name) \
0310 (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
0311 log_postfix_event(result.value(), str); \
0312 } \
0313 template <class Backend, class T> \
0314 inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const logged_adaptor<Backend>& b, const T& c) \
0315 { \
0316 using default_ops::BOOST_JOIN(eval_, name); \
0317 log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
0318 BOOST_JOIN(eval_, name) \
0319 (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
0320 log_postfix_event(result.value(), str); \
0321 } \
0322 template <class Backend, class T> \
0323 inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const T& b, const logged_adaptor<Backend>& c) \
0324 { \
0325 using default_ops::BOOST_JOIN(eval_, name); \
0326 log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
0327 BOOST_JOIN(eval_, name) \
0328 (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
0329 log_postfix_event(result.value(), str); \
0330 } \
0331 template <class Backend, class T> \
0332 inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const logged_adaptor<Backend>& b, const logged_adaptor<Backend>& c) \
0333 { \
0334 using default_ops::BOOST_JOIN(eval_, name); \
0335 log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
0336 BOOST_JOIN(eval_, name) \
0337 (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
0338 log_postfix_event(result.value(), str); \
0339 } \
0340 template <class Backend> \
0341 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) \
0342 { \
0343 using default_ops::BOOST_JOIN(eval_, name); \
0344 log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
0345 BOOST_JOIN(eval_, name) \
0346 (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
0347 log_postfix_event(result.value(), str); \
0348 } \
0349 template <class Backend, class T, class U> \
0350 inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const T& b, const U& c) \
0351 { \
0352 using default_ops::BOOST_JOIN(eval_, name); \
0353 log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \
0354 BOOST_JOIN(eval_, name) \
0355 (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \
0356 log_postfix_event(result.value(), str); \
0357 }
0358
0359 NON_MEMBER_OP2(add, "+=")
0360 NON_MEMBER_OP2(subtract, "-=")
0361 NON_MEMBER_OP2(multiply, "*=")
0362 NON_MEMBER_OP2(divide, "/=")
0363
0364 template <class Backend, class R>
0365 inline void eval_convert_to(R* result, const logged_adaptor<Backend>& val)
0366 {
0367 using default_ops::eval_convert_to;
0368 log_prefix_event(val.value(), "convert_to");
0369 eval_convert_to(result, val.value());
0370 log_postfix_event(val.value(), *result, "convert_to");
0371 }
0372
0373 template <class Backend, class R>
0374 inline void eval_convert_to(logged_adaptor<R>* result, const logged_adaptor<Backend>& val)
0375 {
0376 using default_ops::eval_convert_to;
0377 log_prefix_event(val.value(), "convert_to");
0378 eval_convert_to(&result->value(), val.value());
0379 log_postfix_event(val.value(), &result->value(), "convert_to");
0380 }
0381 template <class Backend, class R>
0382 inline void eval_convert_to(logged_adaptor<R>* result, const Backend& val)
0383 {
0384 using default_ops::eval_convert_to;
0385 log_prefix_event(val, "convert_to");
0386 eval_convert_to(&result->value(), val);
0387 log_postfix_event(val, &result->value(), "convert_to");
0388 }
0389
0390 template <class Backend>
0391 inline void eval_convert_to(std::complex<float>* result, const logged_adaptor<Backend>& val)
0392 {
0393 using default_ops::eval_convert_to;
0394 log_prefix_event(val.value(), "convert_to");
0395 eval_convert_to(result, val.value());
0396 log_postfix_event(val.value(), *result, "convert_to");
0397 }
0398 template <class Backend>
0399 inline void eval_convert_to(std::complex<double>* result, const logged_adaptor<Backend>& val)
0400 {
0401 using default_ops::eval_convert_to;
0402 log_prefix_event(val.value(), "convert_to");
0403 eval_convert_to(result, val.value());
0404 log_postfix_event(val.value(), *result, "convert_to");
0405 }
0406 template <class Backend>
0407 inline void eval_convert_to(std::complex<long double>* result, const logged_adaptor<Backend>& val)
0408 {
0409 using default_ops::eval_convert_to;
0410 log_prefix_event(val.value(), "convert_to");
0411 eval_convert_to(result, val.value());
0412 log_postfix_event(val.value(), *result, "convert_to");
0413 }
0414
0415
0416 template <class Backend, class Exp>
0417 inline void eval_frexp(logged_adaptor<Backend>& result, const logged_adaptor<Backend>& arg, Exp* exp)
0418 {
0419 log_prefix_event(arg.value(), "frexp");
0420 eval_frexp(result.value(), arg.value(), exp);
0421 log_postfix_event(result.value(), *exp, "frexp");
0422 }
0423
0424 template <class Backend, class Exp>
0425 inline void eval_ldexp(logged_adaptor<Backend>& result, const logged_adaptor<Backend>& arg, Exp exp)
0426 {
0427 log_prefix_event(arg.value(), "ldexp");
0428 eval_ldexp(result.value(), arg.value(), exp);
0429 log_postfix_event(result.value(), exp, "ldexp");
0430 }
0431
0432 template <class Backend, class Exp>
0433 inline void eval_scalbn(logged_adaptor<Backend>& result, const logged_adaptor<Backend>& arg, Exp exp)
0434 {
0435 using default_ops::eval_scalbn;
0436 log_prefix_event(arg.value(), "scalbn");
0437 eval_scalbn(result.value(), arg.value(), exp);
0438 log_postfix_event(result.value(), exp, "scalbn");
0439 }
0440
0441 template <class Backend>
0442 inline typename Backend::exponent_type eval_ilogb(const logged_adaptor<Backend>& arg)
0443 {
0444 using default_ops::eval_ilogb;
0445 log_prefix_event(arg.value(), "ilogb");
0446 typename Backend::exponent_type r = eval_ilogb(arg.value());
0447 log_postfix_event(arg.value(), "ilogb");
0448 return r;
0449 }
0450
0451 NON_MEMBER_OP2(floor, "floor")
0452 NON_MEMBER_OP2(ceil, "ceil")
0453 NON_MEMBER_OP2(sqrt, "sqrt")
0454
0455 template <class Backend>
0456 inline int eval_fpclassify(const logged_adaptor<Backend>& arg)
0457 {
0458 using default_ops::eval_fpclassify;
0459 log_prefix_event(arg.value(), "fpclassify");
0460 int r = eval_fpclassify(arg.value());
0461 log_postfix_event(arg.value(), r, "fpclassify");
0462 return r;
0463 }
0464
0465
0466
0467
0468
0469
0470
0471 NON_MEMBER_OP3(add, "+")
0472 NON_MEMBER_OP3(subtract, "-")
0473 NON_MEMBER_OP3(multiply, "*")
0474 NON_MEMBER_OP3(divide, "/")
0475 NON_MEMBER_OP3(multiply_add, "fused-multiply-add")
0476 NON_MEMBER_OP3(multiply_subtract, "fused-multiply-subtract")
0477 NON_MEMBER_OP4(multiply_add, "fused-multiply-add")
0478 NON_MEMBER_OP4(multiply_subtract, "fused-multiply-subtract")
0479
0480 NON_MEMBER_OP1(increment, "increment")
0481 NON_MEMBER_OP1(decrement, "decrement")
0482
0483
0484
0485
0486
0487
0488
0489 NON_MEMBER_OP2(modulus, "%=")
0490 NON_MEMBER_OP3(modulus, "%")
0491 NON_MEMBER_OP2(bitwise_or, "|=")
0492 NON_MEMBER_OP3(bitwise_or, "|")
0493 NON_MEMBER_OP2(bitwise_and, "&=")
0494 NON_MEMBER_OP3(bitwise_and, "&")
0495 NON_MEMBER_OP2(bitwise_xor, "^=")
0496 NON_MEMBER_OP3(bitwise_xor, "^")
0497 NON_MEMBER_OP4(qr, "quotient-and-remainder")
0498 NON_MEMBER_OP2(complement, "~")
0499
0500 template <class Backend>
0501 inline void eval_left_shift(logged_adaptor<Backend>& arg, std::size_t a)
0502 {
0503 using default_ops::eval_left_shift;
0504 log_prefix_event(arg.value(), a, "<<=");
0505 eval_left_shift(arg.value(), a);
0506 log_postfix_event(arg.value(), "<<=");
0507 }
0508 template <class Backend>
0509 inline void eval_left_shift(logged_adaptor<Backend>& arg, const logged_adaptor<Backend>& a, std::size_t b)
0510 {
0511 using default_ops::eval_left_shift;
0512 log_prefix_event(arg.value(), a, b, "<<");
0513 eval_left_shift(arg.value(), a.value(), b);
0514 log_postfix_event(arg.value(), "<<");
0515 }
0516 template <class Backend>
0517 inline void eval_right_shift(logged_adaptor<Backend>& arg, std::size_t a)
0518 {
0519 using default_ops::eval_right_shift;
0520 log_prefix_event(arg.value(), a, ">>=");
0521 eval_right_shift(arg.value(), a);
0522 log_postfix_event(arg.value(), ">>=");
0523 }
0524 template <class Backend>
0525 inline void eval_right_shift(logged_adaptor<Backend>& arg, const logged_adaptor<Backend>& a, std::size_t b)
0526 {
0527 using default_ops::eval_right_shift;
0528 log_prefix_event(arg.value(), a, b, ">>");
0529 eval_right_shift(arg.value(), a.value(), b);
0530 log_postfix_event(arg.value(), ">>");
0531 }
0532
0533 template <class Backend, class T>
0534 inline T eval_integer_modulus(const logged_adaptor<Backend>& arg, const T& a)
0535 {
0536 using default_ops::eval_integer_modulus;
0537 log_prefix_event(arg.value(), a, "integer-modulus");
0538 T r = eval_integer_modulus(arg.value(), a);
0539 log_postfix_event(arg.value(), r, "integer-modulus");
0540 return r;
0541 }
0542
0543 template <class Backend>
0544 inline std::size_t eval_lsb(const logged_adaptor<Backend>& arg)
0545 {
0546 using default_ops::eval_lsb;
0547 log_prefix_event(arg.value(), "least-significant-bit");
0548 std::size_t r = eval_lsb(arg.value());
0549 log_postfix_event(arg.value(), r, "least-significant-bit");
0550 return r;
0551 }
0552
0553 template <class Backend>
0554 inline std::size_t eval_msb(const logged_adaptor<Backend>& arg)
0555 {
0556 using default_ops::eval_msb;
0557 log_prefix_event(arg.value(), "most-significant-bit");
0558 std::size_t r = eval_msb(arg.value());
0559 log_postfix_event(arg.value(), r, "most-significant-bit");
0560 return r;
0561 }
0562
0563 template <class Backend>
0564 inline bool eval_bit_test(const logged_adaptor<Backend>& arg, std::size_t a)
0565 {
0566 using default_ops::eval_bit_test;
0567 log_prefix_event(arg.value(), a, "bit-test");
0568 bool r = eval_bit_test(arg.value(), a);
0569 log_postfix_event(arg.value(), r, "bit-test");
0570 return r;
0571 }
0572
0573 template <class Backend>
0574 inline void eval_bit_set(const logged_adaptor<Backend>& arg, std::size_t a)
0575 {
0576 using default_ops::eval_bit_set;
0577 log_prefix_event(arg.value(), a, "bit-set");
0578 eval_bit_set(arg.value(), a);
0579 log_postfix_event(arg.value(), arg, "bit-set");
0580 }
0581 template <class Backend>
0582 inline void eval_bit_unset(const logged_adaptor<Backend>& arg, std::size_t a)
0583 {
0584 using default_ops::eval_bit_unset;
0585 log_prefix_event(arg.value(), a, "bit-unset");
0586 eval_bit_unset(arg.value(), a);
0587 log_postfix_event(arg.value(), arg, "bit-unset");
0588 }
0589 template <class Backend>
0590 inline void eval_bit_flip(const logged_adaptor<Backend>& arg, std::size_t a)
0591 {
0592 using default_ops::eval_bit_flip;
0593 log_prefix_event(arg.value(), a, "bit-flip");
0594 eval_bit_flip(arg.value(), a);
0595 log_postfix_event(arg.value(), arg, "bit-flip");
0596 }
0597
0598 NON_MEMBER_OP3(gcd, "gcd")
0599 NON_MEMBER_OP3(lcm, "lcm")
0600 NON_MEMBER_OP4(powm, "powm")
0601
0602
0603
0604
0605
0606
0607
0608 NON_MEMBER_OP2(abs, "abs")
0609 NON_MEMBER_OP2(fabs, "fabs")
0610
0611
0612
0613
0614
0615
0616
0617 NON_MEMBER_OP2(trunc, "trunc")
0618 NON_MEMBER_OP2(round, "round")
0619 NON_MEMBER_OP2(exp, "exp")
0620 NON_MEMBER_OP2(log, "log")
0621 NON_MEMBER_OP2(log10, "log10")
0622 NON_MEMBER_OP2(sin, "sin")
0623 NON_MEMBER_OP2(cos, "cos")
0624 NON_MEMBER_OP2(tan, "tan")
0625 NON_MEMBER_OP2(asin, "asin")
0626 NON_MEMBER_OP2(acos, "acos")
0627 NON_MEMBER_OP2(atan, "atan")
0628 NON_MEMBER_OP2(sinh, "sinh")
0629 NON_MEMBER_OP2(cosh, "cosh")
0630 NON_MEMBER_OP2(tanh, "tanh")
0631 NON_MEMBER_OP2(logb, "logb")
0632 NON_MEMBER_OP3(fmod, "fmod")
0633 NON_MEMBER_OP3(pow, "pow")
0634 NON_MEMBER_OP3(atan2, "atan2")
0635 NON_MEMBER_OP2(asinh, "asinh")
0636 NON_MEMBER_OP2(acosh, "acosh")
0637 NON_MEMBER_OP2(atanh, "atanh")
0638 NON_MEMBER_OP2(conj, "conj")
0639
0640 template <class Backend>
0641 int eval_signbit(const logged_adaptor<Backend>& val)
0642 {
0643 using default_ops::eval_signbit;
0644 return eval_signbit(val.value());
0645 }
0646
0647 template <class Backend>
0648 std::size_t hash_value(const logged_adaptor<Backend>& val)
0649 {
0650 return hash_value(val.value());
0651 }
0652
0653 template <class Backend, expression_template_option ExpressionTemplates>
0654 inline typename std::enable_if<number_category<Backend>::value == number_kind_rational, typename number<logged_adaptor<Backend>, ExpressionTemplates>::value_type>::type
0655 numerator(const number<logged_adaptor<Backend>, ExpressionTemplates>& arg)
0656 {
0657 number<Backend, ExpressionTemplates> t(arg.backend().value());
0658 return numerator(t).backend();
0659 }
0660 template <class Backend, expression_template_option ExpressionTemplates>
0661 inline typename std::enable_if<number_category<Backend>::value == number_kind_rational, typename number<logged_adaptor<Backend>, ExpressionTemplates>::value_type>::type
0662 denominator(const number<logged_adaptor<Backend>, ExpressionTemplates>& arg)
0663 {
0664 number<Backend, ExpressionTemplates> t(arg.backend().value());
0665 return denominator(t).backend();
0666 }
0667
0668 template <class To, class From>
0669 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(To& to, const logged_adaptor<From>& from)
0670 {
0671 using default_ops::eval_set_real;
0672 log_prefix_event(to, from.value(), "Set real part");
0673 eval_set_real(to, from.value());
0674 log_postfix_event(to, from.value(), "Set real part");
0675 }
0676 template <class To, class From>
0677 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(logged_adaptor<To>& to, const logged_adaptor<From>& from)
0678 {
0679 using default_ops::eval_set_real;
0680 log_prefix_event(to.value(), from.value(), "Set real part");
0681 eval_set_real(to.value(), from.value());
0682 log_postfix_event(to.value(), from.value(), "Set real part");
0683 }
0684 template <class To, class From>
0685 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(logged_adaptor<To>& to, const From& from)
0686 {
0687 using default_ops::eval_set_real;
0688 log_prefix_event(to.value(), from, "Set real part");
0689 eval_set_real(to.value(), from);
0690 log_postfix_event(to.value(), from, "Set real part");
0691 }
0692
0693 template <class To, class From>
0694 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(To& to, const logged_adaptor<From>& from)
0695 {
0696 using default_ops::eval_set_imag;
0697 log_prefix_event(to, from.value(), "Set imag part");
0698 eval_set_imag(to, from.value());
0699 log_postfix_event(to, from.value(), "Set imag part");
0700 }
0701 template <class To, class From>
0702 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(logged_adaptor<To>& to, const logged_adaptor<From>& from)
0703 {
0704 using default_ops::eval_set_imag;
0705 log_prefix_event(to.value(), from.value(), "Set imag part");
0706 eval_set_imag(to.value(), from.value());
0707 log_postfix_event(to.value(), from.value(), "Set imag part");
0708 }
0709 template <class To, class From>
0710 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(logged_adaptor<To>& to, const From& from)
0711 {
0712 using default_ops::eval_set_imag;
0713 log_prefix_event(to.value(), from, "Set imag part");
0714 eval_set_imag(to.value(), from);
0715 log_postfix_event(to.value(), from, "Set imag part");
0716 }
0717
0718
0719 #define NON_MEMBER_COMPLEX_TO_REAL(name, str) \
0720 template <class B1, class B2> \
0721 inline void BOOST_JOIN(eval_, name)(logged_adaptor<B1> & result, const logged_adaptor<B2>& a) \
0722 { \
0723 using default_ops::BOOST_JOIN(eval_, name); \
0724 log_prefix_event(a.value(), a.value(), str); \
0725 BOOST_JOIN(eval_, name) \
0726 (result.value(), a.value()); \
0727 log_postfix_event(result.value(), str); \
0728 } \
0729 template <class B1, class B2> \
0730 inline void BOOST_JOIN(eval_, name)(B1 & result, const logged_adaptor<B2>& a) \
0731 { \
0732 using default_ops::BOOST_JOIN(eval_, name); \
0733 log_prefix_event(a.value(), a.value(), str); \
0734 BOOST_JOIN(eval_, name) \
0735 (result, a.value()); \
0736 log_postfix_event(result, str); \
0737 }
0738
0739 NON_MEMBER_COMPLEX_TO_REAL(real, "real")
0740 NON_MEMBER_COMPLEX_TO_REAL(imag, "imag")
0741
0742 template <class T, class V, class U>
0743 inline void assign_components(logged_adaptor<T>& result, const V& v1, const U& v2)
0744 {
0745 using default_ops::assign_components;
0746 assign_components(result.value(), unwrap_logged_type(v1), unwrap_logged_type(v2));
0747 }
0748
0749 }
0750
0751 namespace detail {
0752 template <class Backend>
0753 struct is_variable_precision<logged_adaptor<Backend> > : public is_variable_precision<Backend>
0754 {};
0755 #ifdef BOOST_HAS_INT128
0756 template <class Backend>
0757 struct is_convertible_arithmetic<int128_type, logged_adaptor<Backend> > : public is_convertible_arithmetic<int128_type, Backend>
0758 {};
0759 template <class Backend>
0760 struct is_convertible_arithmetic<uint128_type, logged_adaptor<Backend> > : public is_convertible_arithmetic<uint128_type, Backend>
0761 {};
0762 #endif
0763 #ifdef BOOST_HAS_FLOAT128
0764 template <class Backend>
0765 struct is_convertible_arithmetic<float128_type, logged_adaptor<Backend> > : public is_convertible_arithmetic<float128_type, Backend>
0766 {};
0767 #endif
0768 }
0769
0770 template <class Backend>
0771 struct number_category<backends::logged_adaptor<Backend> > : public number_category<Backend>
0772 {};
0773
0774 template <class Backend, expression_template_option ExpressionTemplates>
0775 struct component_type<number<logged_adaptor<Backend>, ExpressionTemplates>>
0776 {
0777
0778
0779
0780 using base_component_type = typename component_type<number<Backend, ExpressionTemplates>>::type;
0781 using base_component_backend = typename base_component_type::backend_type;
0782 using type = number<logged_adaptor<base_component_backend>, ExpressionTemplates>;
0783 };
0784
0785 template <class Backend>
0786 struct is_interval_number<backends::logged_adaptor<Backend> > : public is_interval_number<Backend> {};
0787
0788 }}
0789
0790 namespace std {
0791
0792 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
0793 class numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<Backend>, ExpressionTemplates> >
0794 : public std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> >
0795 {
0796 using base_type = std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> > ;
0797 using number_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<Backend>, ExpressionTemplates>;
0798
0799 public:
0800 static number_type(min)() noexcept { return (base_type::min)(); }
0801 static number_type(max)() noexcept { return (base_type::max)(); }
0802 static number_type lowest() noexcept { return -(max)(); }
0803 static number_type epsilon() noexcept { return base_type::epsilon(); }
0804 static number_type round_error() noexcept { return epsilon() / 2; }
0805 static number_type infinity() noexcept { return base_type::infinity(); }
0806 static number_type quiet_NaN() noexcept { return base_type::quiet_NaN(); }
0807 static number_type signaling_NaN() noexcept { return base_type::signaling_NaN(); }
0808 static number_type denorm_min() noexcept { return base_type::denorm_min(); }
0809 };
0810
0811 }
0812
0813 #ifdef BOOST_MP_MATH_AVAILABLE
0814 namespace boost {
0815 namespace math {
0816
0817 namespace policies {
0818
0819 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
0820 struct precision<boost::multiprecision::number<boost::multiprecision::logged_adaptor<Backend>, ExpressionTemplates>, Policy>
0821 : public precision<boost::multiprecision::number<Backend, ExpressionTemplates>, Policy>
0822 {};
0823
0824 }
0825
0826 }}
0827 #endif
0828
0829 #undef NON_MEMBER_OP1
0830 #undef NON_MEMBER_OP2
0831 #undef NON_MEMBER_OP3
0832 #undef NON_MEMBER_OP4
0833
0834 #endif