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