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