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