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