• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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    Backend m_value;
53 
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_CXX11_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& boost::make_nvp("value", 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)                                            \
193       (result.value());                                                  \
194       log_postfix_event(result.value(), str);                            \
195    }
196 
197 #define NON_MEMBER_OP2(name, str)                                                                          \
198    template <class Backend, class T>                                                                       \
199    inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a)                       \
200    {                                                                                                       \
201       using default_ops::BOOST_JOIN(eval_, name);                                                          \
202       log_prefix_event(result.value(), unwrap_logged_type(a), str);                                        \
203       BOOST_JOIN(eval_, name)                                                                              \
204       (result.value(), unwrap_logged_type(a));                                                             \
205       log_postfix_event(result.value(), str);                                                              \
206    }                                                                                                       \
207    template <class Backend>                                                                                \
208    inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a) \
209    {                                                                                                       \
210       using default_ops::BOOST_JOIN(eval_, name);                                                          \
211       log_prefix_event(result.value(), unwrap_logged_type(a), str);                                        \
212       BOOST_JOIN(eval_, name)                                                                              \
213       (result.value(), unwrap_logged_type(a));                                                             \
214       log_postfix_event(result.value(), str);                                                              \
215    }
216 
217 #define NON_MEMBER_OP3(name, str)                                                                                                            \
218    template <class Backend, class T, class U>                                                                                                \
219    inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const U& b)                                             \
220    {                                                                                                                                         \
221       using default_ops::BOOST_JOIN(eval_, name);                                                                                            \
222       log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str);                                                   \
223       BOOST_JOIN(eval_, name)                                                                                                                \
224       (result.value(), unwrap_logged_type(a), unwrap_logged_type(b));                                                                        \
225       log_postfix_event(result.value(), str);                                                                                                \
226    }                                                                                                                                         \
227    template <class Backend, class T>                                                                                                         \
228    inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const T& b)                       \
229    {                                                                                                                                         \
230       using default_ops::BOOST_JOIN(eval_, name);                                                                                            \
231       log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str);                                                   \
232       BOOST_JOIN(eval_, name)                                                                                                                \
233       (result.value(), unwrap_logged_type(a), unwrap_logged_type(b));                                                                        \
234       log_postfix_event(result.value(), str);                                                                                                \
235    }                                                                                                                                         \
236    template <class Backend, class T>                                                                                                         \
237    inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const logged_adaptor<Backend>& b)                       \
238    {                                                                                                                                         \
239       using default_ops::BOOST_JOIN(eval_, name);                                                                                            \
240       log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str);                                                   \
241       BOOST_JOIN(eval_, name)                                                                                                                \
242       (result.value(), unwrap_logged_type(a), unwrap_logged_type(b));                                                                        \
243       log_postfix_event(result.value(), str);                                                                                                \
244    }                                                                                                                                         \
245    template <class Backend>                                                                                                                  \
246    inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const logged_adaptor<Backend>& b) \
247    {                                                                                                                                         \
248       using default_ops::BOOST_JOIN(eval_, name);                                                                                            \
249       log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str);                                                   \
250       BOOST_JOIN(eval_, name)                                                                                                                \
251       (result.value(), unwrap_logged_type(a), unwrap_logged_type(b));                                                                        \
252       log_postfix_event(result.value(), str);                                                                                                \
253    }
254 
255 #define NON_MEMBER_OP4(name, str)                                                                                                                                              \
256    template <class Backend, class T, class U, class V>                                                                                                                         \
257    inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const U& b, const V& c)                                                                   \
258    {                                                                                                                                                                           \
259       using default_ops::BOOST_JOIN(eval_, name);                                                                                                                              \
260       log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str);                                                              \
261       BOOST_JOIN(eval_, name)                                                                                                                                                  \
262       (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 logged_adaptor<Backend>& b, const T& 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)                                                                                                                                                  \
271       (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c));                                                                                   \
272       log_postfix_event(result.value(), str);                                                                                                                                  \
273    }                                                                                                                                                                           \
274    template <class Backend, class T>                                                                                                                                           \
275    inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const T& b, const logged_adaptor<Backend>& c)                       \
276    {                                                                                                                                                                           \
277       using default_ops::BOOST_JOIN(eval_, name);                                                                                                                              \
278       log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str);                                                              \
279       BOOST_JOIN(eval_, name)                                                                                                                                                  \
280       (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c));                                                                                   \
281       log_postfix_event(result.value(), str);                                                                                                                                  \
282    }                                                                                                                                                                           \
283    template <class Backend, class T>                                                                                                                                           \
284    inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const logged_adaptor<Backend>& b, const logged_adaptor<Backend>& c)                       \
285    {                                                                                                                                                                           \
286       using default_ops::BOOST_JOIN(eval_, name);                                                                                                                              \
287       log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str);                                                              \
288       BOOST_JOIN(eval_, name)                                                                                                                                                  \
289       (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c));                                                                                   \
290       log_postfix_event(result.value(), str);                                                                                                                                  \
291    }                                                                                                                                                                           \
292    template <class Backend>                                                                                                                                                    \
293    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) \
294    {                                                                                                                                                                           \
295       using default_ops::BOOST_JOIN(eval_, name);                                                                                                                              \
296       log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str);                                                              \
297       BOOST_JOIN(eval_, name)                                                                                                                                                  \
298       (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c));                                                                                   \
299       log_postfix_event(result.value(), str);                                                                                                                                  \
300    }                                                                                                                                                                           \
301    template <class Backend, class T, class U>                                                                                                                                  \
302    inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const T& b, const U& c)                                             \
303    {                                                                                                                                                                           \
304       using default_ops::BOOST_JOIN(eval_, name);                                                                                                                              \
305       log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str);                                                              \
306       BOOST_JOIN(eval_, name)                                                                                                                                                  \
307       (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c));                                                                                   \
308       log_postfix_event(result.value(), str);                                                                                                                                  \
309    }
310 
311 NON_MEMBER_OP2(add, "+=")
312 NON_MEMBER_OP2(subtract, "-=")
313 NON_MEMBER_OP2(multiply, "*=")
314 NON_MEMBER_OP2(divide, "/=")
315 
316 template <class Backend, class R>
eval_convert_to(R * result,const logged_adaptor<Backend> & val)317 inline void eval_convert_to(R* result, const logged_adaptor<Backend>& val)
318 {
319    using default_ops::eval_convert_to;
320    log_prefix_event(val.value(), "convert_to");
321    eval_convert_to(result, val.value());
322    log_postfix_event(val.value(), *result, "convert_to");
323 }
324 
325 template <class Backend, class Exp>
eval_frexp(logged_adaptor<Backend> & result,const logged_adaptor<Backend> & arg,Exp * exp)326 inline void eval_frexp(logged_adaptor<Backend>& result, const logged_adaptor<Backend>& arg, Exp* exp)
327 {
328    log_prefix_event(arg.value(), "frexp");
329    eval_frexp(result.value(), arg.value(), exp);
330    log_postfix_event(result.value(), *exp, "frexp");
331 }
332 
333 template <class Backend, class Exp>
eval_ldexp(logged_adaptor<Backend> & result,const logged_adaptor<Backend> & arg,Exp exp)334 inline void eval_ldexp(logged_adaptor<Backend>& result, const logged_adaptor<Backend>& arg, Exp exp)
335 {
336    log_prefix_event(arg.value(), "ldexp");
337    eval_ldexp(result.value(), arg.value(), exp);
338    log_postfix_event(result.value(), exp, "ldexp");
339 }
340 
341 template <class Backend, class Exp>
eval_scalbn(logged_adaptor<Backend> & result,const logged_adaptor<Backend> & arg,Exp exp)342 inline void eval_scalbn(logged_adaptor<Backend>& result, const logged_adaptor<Backend>& arg, Exp exp)
343 {
344    log_prefix_event(arg.value(), "scalbn");
345    eval_scalbn(result.value(), arg.value(), exp);
346    log_postfix_event(result.value(), exp, "scalbn");
347 }
348 
349 template <class Backend>
eval_ilogb(const logged_adaptor<Backend> & arg)350 inline typename Backend::exponent_type eval_ilogb(const logged_adaptor<Backend>& arg)
351 {
352    log_prefix_event(arg.value(), "ilogb");
353    typename Backend::exponent_type r = eval_ilogb(arg.value());
354    log_postfix_event(arg.value(), "ilogb");
355    return r;
356 }
357 
358 NON_MEMBER_OP2(floor, "floor")
359 NON_MEMBER_OP2(ceil, "ceil")
360 NON_MEMBER_OP2(sqrt, "sqrt")
361 
362 template <class Backend>
eval_fpclassify(const logged_adaptor<Backend> & arg)363 inline int eval_fpclassify(const logged_adaptor<Backend>& arg)
364 {
365    using default_ops::eval_fpclassify;
366    log_prefix_event(arg.value(), "fpclassify");
367    int r = eval_fpclassify(arg.value());
368    log_postfix_event(arg.value(), r, "fpclassify");
369    return r;
370 }
371 
372 /*********************************************************************
373 *
374 * Optional arithmetic operations come next:
375 *
376 *********************************************************************/
377 
378 NON_MEMBER_OP3(add, "+")
379 NON_MEMBER_OP3(subtract, "-")
380 NON_MEMBER_OP3(multiply, "*")
381 NON_MEMBER_OP3(divide, "/")
382 NON_MEMBER_OP3(multiply_add, "fused-multiply-add")
383 NON_MEMBER_OP3(multiply_subtract, "fused-multiply-subtract")
384 NON_MEMBER_OP4(multiply_add, "fused-multiply-add")
385 NON_MEMBER_OP4(multiply_subtract, "fused-multiply-subtract")
386 
387 NON_MEMBER_OP1(increment, "increment")
388 NON_MEMBER_OP1(decrement, "decrement")
389 
390 /*********************************************************************
391 *
392 * Optional integer operations come next:
393 *
394 *********************************************************************/
395 
396 NON_MEMBER_OP2(modulus, "%=")
397 NON_MEMBER_OP3(modulus, "%")
398 NON_MEMBER_OP2(bitwise_or, "|=")
399 NON_MEMBER_OP3(bitwise_or, "|")
400 NON_MEMBER_OP2(bitwise_and, "&=")
401 NON_MEMBER_OP3(bitwise_and, "&")
402 NON_MEMBER_OP2(bitwise_xor, "^=")
403 NON_MEMBER_OP3(bitwise_xor, "^")
404 NON_MEMBER_OP4(qr, "quotient-and-remainder")
405 NON_MEMBER_OP2(complement, "~")
406 
407 template <class Backend>
eval_left_shift(logged_adaptor<Backend> & arg,std::size_t a)408 inline void eval_left_shift(logged_adaptor<Backend>& arg, std::size_t a)
409 {
410    using default_ops::eval_left_shift;
411    log_prefix_event(arg.value(), a, "<<=");
412    eval_left_shift(arg.value(), a);
413    log_postfix_event(arg.value(), "<<=");
414 }
415 template <class Backend>
eval_left_shift(logged_adaptor<Backend> & arg,const logged_adaptor<Backend> & a,std::size_t b)416 inline void eval_left_shift(logged_adaptor<Backend>& arg, const logged_adaptor<Backend>& a, std::size_t b)
417 {
418    using default_ops::eval_left_shift;
419    log_prefix_event(arg.value(), a, b, "<<");
420    eval_left_shift(arg.value(), a.value(), b);
421    log_postfix_event(arg.value(), "<<");
422 }
423 template <class Backend>
eval_right_shift(logged_adaptor<Backend> & arg,std::size_t a)424 inline void eval_right_shift(logged_adaptor<Backend>& arg, std::size_t a)
425 {
426    using default_ops::eval_right_shift;
427    log_prefix_event(arg.value(), a, ">>=");
428    eval_right_shift(arg.value(), a);
429    log_postfix_event(arg.value(), ">>=");
430 }
431 template <class Backend>
eval_right_shift(logged_adaptor<Backend> & arg,const logged_adaptor<Backend> & a,std::size_t b)432 inline void eval_right_shift(logged_adaptor<Backend>& arg, const logged_adaptor<Backend>& a, std::size_t b)
433 {
434    using default_ops::eval_right_shift;
435    log_prefix_event(arg.value(), a, b, ">>");
436    eval_right_shift(arg.value(), a.value(), b);
437    log_postfix_event(arg.value(), ">>");
438 }
439 
440 template <class Backend, class T>
eval_integer_modulus(const logged_adaptor<Backend> & arg,const T & a)441 inline unsigned eval_integer_modulus(const logged_adaptor<Backend>& arg, const T& a)
442 {
443    using default_ops::eval_integer_modulus;
444    log_prefix_event(arg.value(), a, "integer-modulus");
445    unsigned r = eval_integer_modulus(arg.value(), a);
446    log_postfix_event(arg.value(), r, "integer-modulus");
447    return r;
448 }
449 
450 template <class Backend>
eval_lsb(const logged_adaptor<Backend> & arg)451 inline unsigned eval_lsb(const logged_adaptor<Backend>& arg)
452 {
453    using default_ops::eval_lsb;
454    log_prefix_event(arg.value(), "least-significant-bit");
455    unsigned r = eval_lsb(arg.value());
456    log_postfix_event(arg.value(), r, "least-significant-bit");
457    return r;
458 }
459 
460 template <class Backend>
eval_msb(const logged_adaptor<Backend> & arg)461 inline unsigned eval_msb(const logged_adaptor<Backend>& arg)
462 {
463    using default_ops::eval_msb;
464    log_prefix_event(arg.value(), "most-significant-bit");
465    unsigned r = eval_msb(arg.value());
466    log_postfix_event(arg.value(), r, "most-significant-bit");
467    return r;
468 }
469 
470 template <class Backend>
eval_bit_test(const logged_adaptor<Backend> & arg,unsigned a)471 inline bool eval_bit_test(const logged_adaptor<Backend>& arg, unsigned a)
472 {
473    using default_ops::eval_bit_test;
474    log_prefix_event(arg.value(), a, "bit-test");
475    bool r = eval_bit_test(arg.value(), a);
476    log_postfix_event(arg.value(), r, "bit-test");
477    return r;
478 }
479 
480 template <class Backend>
eval_bit_set(const logged_adaptor<Backend> & arg,unsigned a)481 inline void eval_bit_set(const logged_adaptor<Backend>& arg, unsigned a)
482 {
483    using default_ops::eval_bit_set;
484    log_prefix_event(arg.value(), a, "bit-set");
485    eval_bit_set(arg.value(), a);
486    log_postfix_event(arg.value(), arg, "bit-set");
487 }
488 template <class Backend>
eval_bit_unset(const logged_adaptor<Backend> & arg,unsigned a)489 inline void eval_bit_unset(const logged_adaptor<Backend>& arg, unsigned a)
490 {
491    using default_ops::eval_bit_unset;
492    log_prefix_event(arg.value(), a, "bit-unset");
493    eval_bit_unset(arg.value(), a);
494    log_postfix_event(arg.value(), arg, "bit-unset");
495 }
496 template <class Backend>
eval_bit_flip(const logged_adaptor<Backend> & arg,unsigned a)497 inline void eval_bit_flip(const logged_adaptor<Backend>& arg, unsigned a)
498 {
499    using default_ops::eval_bit_flip;
500    log_prefix_event(arg.value(), a, "bit-flip");
501    eval_bit_flip(arg.value(), a);
502    log_postfix_event(arg.value(), arg, "bit-flip");
503 }
504 
505 NON_MEMBER_OP3(gcd, "gcd")
506 NON_MEMBER_OP3(lcm, "lcm")
507 NON_MEMBER_OP4(powm, "powm")
508 
509 /*********************************************************************
510 *
511 * abs/fabs:
512 *
513 *********************************************************************/
514 
515 NON_MEMBER_OP2(abs, "abs")
516 NON_MEMBER_OP2(fabs, "fabs")
517 
518 /*********************************************************************
519 *
520 * Floating point functions:
521 *
522 *********************************************************************/
523 
524 NON_MEMBER_OP2(trunc, "trunc")
525 NON_MEMBER_OP2(round, "round")
526 NON_MEMBER_OP2(exp, "exp")
527 NON_MEMBER_OP2(log, "log")
528 NON_MEMBER_OP2(log10, "log10")
529 NON_MEMBER_OP2(sin, "sin")
530 NON_MEMBER_OP2(cos, "cos")
531 NON_MEMBER_OP2(tan, "tan")
532 NON_MEMBER_OP2(asin, "asin")
533 NON_MEMBER_OP2(acos, "acos")
534 NON_MEMBER_OP2(atan, "atan")
535 NON_MEMBER_OP2(sinh, "sinh")
536 NON_MEMBER_OP2(cosh, "cosh")
537 NON_MEMBER_OP2(tanh, "tanh")
538 NON_MEMBER_OP2(logb, "logb")
539 NON_MEMBER_OP3(fmod, "fmod")
540 NON_MEMBER_OP3(pow, "pow")
541 NON_MEMBER_OP3(atan2, "atan2")
542 
543 template <class Backend>
eval_signbit(const logged_adaptor<Backend> & val)544 int eval_signbit(const logged_adaptor<Backend>& val)
545 {
546    using default_ops::eval_signbit;
547    return eval_signbit(val.value());
548 }
549 
550 template <class Backend>
hash_value(const logged_adaptor<Backend> & val)551 std::size_t hash_value(const logged_adaptor<Backend>& val)
552 {
553    return hash_value(val.value());
554 }
555 
556 #define NON_MEMBER_COMPLEX_TO_REAL(name, str)                                                    \
557    template <class B1, class B2>                                                                 \
558    inline void BOOST_JOIN(eval_, name)(logged_adaptor<B1> & result, const logged_adaptor<B2>& a) \
559    {                                                                                             \
560       using default_ops::BOOST_JOIN(eval_, name);                                                \
561       log_prefix_event(a.value(), a.value(), str);                                               \
562       BOOST_JOIN(eval_, name)                                                                    \
563       (result.value(), a.value());                                                               \
564       log_postfix_event(result.value(), str);                                                    \
565    }                                                                                             \
566    template <class B1, class B2>                                                                 \
567    inline void BOOST_JOIN(eval_, name)(B1 & result, const logged_adaptor<B2>& a)                 \
568    {                                                                                             \
569       using default_ops::BOOST_JOIN(eval_, name);                                                \
570       log_prefix_event(a.value(), a.value(), str);                                               \
571       BOOST_JOIN(eval_, name)                                                                    \
572       (result, a.value());                                                                       \
573       log_postfix_event(result, str);                                                            \
574    }
575 
576 NON_MEMBER_COMPLEX_TO_REAL(real, "real")
577 NON_MEMBER_COMPLEX_TO_REAL(imag, "imag")
578 
579 template <class T, class V, class U>
assign_components(logged_adaptor<T> & result,const V & v1,const U & v2)580 inline void assign_components(logged_adaptor<T>& result, const V& v1, const U& v2)
581 {
582    assign_components(result.value(), v1, v2);
583 }
584 
585 } // namespace backends
586 
587 using backends::logged_adaptor;
588 
589 template <class Backend>
590 struct number_category<backends::logged_adaptor<Backend> > : public number_category<Backend>
591 {};
592 
593 }} // namespace boost::multiprecision
594 
595 namespace std {
596 
597 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
598 class numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<Backend>, ExpressionTemplates> >
599     : public std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> >
600 {
601    typedef std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> >                            base_type;
602    typedef boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<Backend>, ExpressionTemplates> number_type;
603 
604  public:
number_type(min)605    static number_type(min)() BOOST_NOEXCEPT { return (base_type::min)(); }
number_type(max)606    static number_type(max)() BOOST_NOEXCEPT { return (base_type::max)(); }
lowest()607    static number_type lowest() BOOST_NOEXCEPT { return -(max)(); }
epsilon()608    static number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); }
round_error()609    static number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; }
infinity()610    static number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); }
quiet_NaN()611    static number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); }
signaling_NaN()612    static number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); }
denorm_min()613    static number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); }
614 };
615 
616 } // namespace std
617 
618 namespace boost {
619 namespace math {
620 
621 namespace policies {
622 
623 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
624 struct precision<boost::multiprecision::number<boost::multiprecision::logged_adaptor<Backend>, ExpressionTemplates>, Policy>
625     : public precision<boost::multiprecision::number<Backend, ExpressionTemplates>, Policy>
626 {};
627 
628 }
629 
630 }} // namespace boost::math::policies
631 
632 #undef NON_MEMBER_OP1
633 #undef NON_MEMBER_OP2
634 #undef NON_MEMBER_OP3
635 #undef NON_MEMBER_OP4
636 
637 #endif
638