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_DEBUG_ADAPTER_HPP
7#define BOOST_MATH_DEBUG_ADAPTER_HPP
8
9#include <boost/multiprecision/traits/extract_exponent_type.hpp>
10#include <boost/multiprecision/detail/integer_ops.hpp>
11
12namespace boost{
13namespace multiprecision{
14namespace backends{
15
16template <class Backend>
17struct debug_adaptor
18{
19 typedef typename Backend::signed_types signed_types;
20 typedef typename Backend::unsigned_types unsigned_types;
21 typedef typename Backend::float_types float_types;
22 typedef typename extract_exponent_type<
23 Backend, number_category<Backend>::value>::type exponent_type;
24
25private:
26 std::string debug_value;
27 Backend m_value;
28public:
29 void update_view()
30 {
31 try
32 {
33 debug_value = m_value.str(0, static_cast<std::ios_base::fmtflags>(0));
34 }
35 catch(const std::exception& e)
36 {
37 debug_value = "String conversion failed with message: \"";
38 debug_value += e.what();
39 debug_value += "\"";
40 }
41 }
42 debug_adaptor()
43 {
44 update_view();
45 }
46 debug_adaptor(const debug_adaptor& o) : debug_value(o.debug_value), m_value(o.m_value)
47 {
48 }
49 debug_adaptor& operator = (const debug_adaptor& o)
50 {
51 debug_value = o.debug_value;
52 m_value = o.m_value;
53 return *this;
54 }
55 template <class T>
56 debug_adaptor(const T& i, const typename enable_if_c<is_convertible<T, Backend>::value>::type* = 0)
57 : m_value(i)
58 {
59 update_view();
60 }
61 template <class T>
62 debug_adaptor(const T& i, const T& j)
63 : m_value(i, j)
64 {
65 update_view();
66 }
67 template <class T>
68 typename enable_if_c<is_arithmetic<T>::value || is_convertible<T, Backend>::value, debug_adaptor&>::type operator = (const T& i)
69 {
70 m_value = i;
71 update_view();
72 return *this;
73 }
74 debug_adaptor& operator = (const char* s)
75 {
76 m_value = s;
77 update_view();
78 return *this;
79 }
80 void swap(debug_adaptor& o)
81 {
82 std::swap(m_value, o.value());
83 std::swap(debug_value, o.debug_value);
84 }
85 std::string str(std::streamsize digits, std::ios_base::fmtflags f)const
86 {
87 return m_value.str(digits, f);
88 }
89 void negate()
90 {
91 m_value.negate();
92 update_view();
93 }
94 int compare(const debug_adaptor& o)const
95 {
96 return m_value.compare(o.value());
97 }
98 template <class T>
99 int compare(const T& i)const
100 {
101 return m_value.compare(i);
102 }
103 Backend& value()
104 {
105 return m_value;
106 }
107 const Backend& value()const
108 {
109 return m_value;
110 }
111 template <class Archive>
112 void serialize(Archive& ar, const unsigned int /*version*/)
113 {
114 ar & m_value;
115 typedef typename Archive::is_loading tag;
116 if(tag::value)
117 update_view();
118 }
119};
120
121template <class Backend>
122inline Backend const& unwrap_debug_type(debug_adaptor<Backend> const& val)
123{
124 return val.value();
125}
126template <class T>
127inline const T& unwrap_debug_type(const T& val)
128{
129 return val;
130}
131
132#define NON_MEMBER_OP1(name, str) \
133 template <class Backend>\
134 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result)\
135 {\
136 using default_ops::BOOST_JOIN(eval_, name);\
137 BOOST_JOIN(eval_, name)(result.value());\
138 result.update_view();\
139 }
140
141#define NON_MEMBER_OP2(name, str) \
142 template <class Backend, class T>\
143 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const T& a)\
144 {\
145 using default_ops::BOOST_JOIN(eval_, name);\
146 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a));\
147 result.update_view();\
148 }\
149 template <class Backend>\
150 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a)\
151 {\
152 using default_ops::BOOST_JOIN(eval_, name);\
153 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a));\
154 result.update_view();\
155 }
156
157#define NON_MEMBER_OP3(name, str) \
158 template <class Backend, class T, class U>\
159 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const T& a, const U& b)\
160 {\
161 using default_ops::BOOST_JOIN(eval_, name);\
162 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\
163 result.update_view();\
164 }\
165 template <class Backend, class T>\
166 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a, const T& b)\
167 {\
168 using default_ops::BOOST_JOIN(eval_, name);\
169 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\
170 result.update_view();\
171 }\
172 template <class Backend, class T>\
173 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const T& a, const debug_adaptor<Backend>& b)\
174 {\
175 using default_ops::BOOST_JOIN(eval_, name);\
176 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\
177 result.update_view();\
178 }\
179 template <class Backend>\
180 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a, const debug_adaptor<Backend>& b)\
181 {\
182 using default_ops::BOOST_JOIN(eval_, name);\
183 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\
184 result.update_view();\
185 }
186
187#define NON_MEMBER_OP4(name, str) \
188 template <class Backend, class T, class U, class V>\
189 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const T& a, const U& b, const V& c)\
190 {\
191 using default_ops::BOOST_JOIN(eval_, name);\
192 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
193 result.update_view();\
194 }\
195 template <class Backend, class T>\
196 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a, const debug_adaptor<Backend>& b, const T& c)\
197 {\
198 using default_ops::BOOST_JOIN(eval_, name);\
199 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
200 result.update_view();\
201 }\
202 template <class Backend, class T>\
203 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a, const T& b, const debug_adaptor<Backend>& c)\
204 {\
205 using default_ops::BOOST_JOIN(eval_, name);\
206 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
207 result.update_view();\
208 }\
209 template <class Backend, class T>\
210 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const T& a, const debug_adaptor<Backend>& b, const debug_adaptor<Backend>& c)\
211 {\
212 using default_ops::BOOST_JOIN(eval_, name);\
213 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
214 result.update_view();\
215 }\
216 template <class Backend>\
217 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a, const debug_adaptor<Backend>& b, const debug_adaptor<Backend>& c)\
218 {\
219 using default_ops::BOOST_JOIN(eval_, name);\
220 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
221 result.update_view();\
222 }\
223 template <class Backend, class T, class U>\
224 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a, const T& b, const U& c)\
225 {\
226 using default_ops::BOOST_JOIN(eval_, name);\
227 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
228 result.update_view();\
229 }\
230
231NON_MEMBER_OP2(add, "+=");
232NON_MEMBER_OP2(subtract, "-=");
233NON_MEMBER_OP2(multiply, "*=");
234NON_MEMBER_OP2(divide, "/=");
235
236template <class Backend, class R>
237inline void eval_convert_to(R* result, const debug_adaptor<Backend>& val)
238{
239 using default_ops::eval_convert_to;
240 eval_convert_to(result, val.value());
241}
242
243template <class Backend, class Exp>
244inline void eval_frexp(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& arg, Exp* exp)
245{
246 eval_frexp(result.value(), arg.value(), exp);
247 result.update_view();
248}
249
250template <class Backend, class Exp>
251inline void eval_ldexp(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& arg, Exp exp)
252{
253 eval_ldexp(result.value(), arg.value(), exp);
254 result.update_view();
255}
256
257template <class Backend, class Exp>
258inline void eval_scalbn(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& arg, Exp exp)
259{
260 eval_scalbn(result.value(), arg.value(), exp);
261 result.update_view();
262}
263
264template <class Backend>
265inline typename Backend::exponent_type eval_ilogb(const debug_adaptor<Backend>& arg)
266{
267 return eval_ilogb(arg.value());
268}
269
270NON_MEMBER_OP2(floor, "floor");
271NON_MEMBER_OP2(ceil, "ceil");
272NON_MEMBER_OP2(sqrt, "sqrt");
273NON_MEMBER_OP2(logb, "logb");
274
275template <class Backend>
276inline int eval_fpclassify(const debug_adaptor<Backend>& arg)
277{
278 using default_ops::eval_fpclassify;
279 return eval_fpclassify(arg.value());
280}
281
282/*********************************************************************
283*
284* Optional arithmetic operations come next:
285*
286*********************************************************************/
287
288NON_MEMBER_OP3(add, "+");
289NON_MEMBER_OP3(subtract, "-");
290NON_MEMBER_OP3(multiply, "*");
291NON_MEMBER_OP3(divide, "/");
292NON_MEMBER_OP3(multiply_add, "fused-multiply-add");
293NON_MEMBER_OP3(multiply_subtract, "fused-multiply-subtract");
294NON_MEMBER_OP4(multiply_add, "fused-multiply-add");
295NON_MEMBER_OP4(multiply_subtract, "fused-multiply-subtract");
296
297NON_MEMBER_OP1(increment, "increment");
298NON_MEMBER_OP1(decrement, "decrement");
299
300/*********************************************************************
301*
302* Optional integer operations come next:
303*
304*********************************************************************/
305
306NON_MEMBER_OP2(modulus, "%=");
307NON_MEMBER_OP3(modulus, "%");
308NON_MEMBER_OP2(bitwise_or, "|=");
309NON_MEMBER_OP3(bitwise_or, "|");
310NON_MEMBER_OP2(bitwise_and, "&=");
311NON_MEMBER_OP3(bitwise_and, "&");
312NON_MEMBER_OP2(bitwise_xor, "^=");
313NON_MEMBER_OP3(bitwise_xor, "^");
314NON_MEMBER_OP4(qr, "quotient-and-remainder");
315NON_MEMBER_OP2(complement, "~");
316
317template <class Backend>
318inline void eval_left_shift(debug_adaptor<Backend>& arg, unsigned a)
319{
320 using default_ops::eval_left_shift;
321 eval_left_shift(arg.value(), a);
322 arg.update_view();\
323}
324template <class Backend>
325inline void eval_left_shift(debug_adaptor<Backend>& arg, const debug_adaptor<Backend>& a, unsigned b)
326{
327 using default_ops::eval_left_shift;
328 eval_left_shift(arg.value(), a.value(), b);
329 arg.update_view();\
330}
331template <class Backend>
332inline void eval_right_shift(debug_adaptor<Backend>& arg, unsigned a)
333{
334 using default_ops::eval_right_shift;
335 eval_right_shift(arg.value(), a);
336 arg.update_view();\
337}
338template <class Backend>
339inline void eval_right_shift(debug_adaptor<Backend>& arg, const debug_adaptor<Backend>& a, unsigned b)
340{
341 using default_ops::eval_right_shift;
342 eval_right_shift(arg.value(), a.value(), b);
343 arg.update_view();\
344}
345
346template <class Backend, class T>
347inline unsigned eval_integer_modulus(const debug_adaptor<Backend>& arg, const T& a)
348{
349 using default_ops::eval_integer_modulus;
350 return eval_integer_modulus(arg.value(), a);
351}
352
353template <class Backend>
354inline unsigned eval_lsb(const debug_adaptor<Backend>& arg)
355{
356 using default_ops::eval_lsb;
357 return eval_lsb(arg.value());
358}
359
360template <class Backend>
361inline unsigned eval_msb(const debug_adaptor<Backend>& arg)
362{
363 using default_ops::eval_msb;
364 return eval_msb(arg.value());
365}
366
367template <class Backend>
368inline bool eval_bit_test(const debug_adaptor<Backend>& arg, unsigned a)
369{
370 using default_ops::eval_bit_test;
371 return eval_bit_test(arg.value(), a);
372}
373
374template <class Backend>
375inline void eval_bit_set(const debug_adaptor<Backend>& arg, unsigned a)
376{
377 using default_ops::eval_bit_set;
378 eval_bit_set(arg.value(), a);
379 arg.update_view();\
380}
381template <class Backend>
382inline void eval_bit_unset(const debug_adaptor<Backend>& arg, unsigned a)
383{
384 using default_ops::eval_bit_unset;
385 eval_bit_unset(arg.value(), a);
386 arg.update_view();\
387}
388template <class Backend>
389inline void eval_bit_flip(const debug_adaptor<Backend>& arg, unsigned a)
390{
391 using default_ops::eval_bit_flip;
392 eval_bit_flip(arg.value(), a);
393 arg.update_view();\
394}
395
396NON_MEMBER_OP3(gcd, "gcd");
397NON_MEMBER_OP3(lcm, "lcm");
398NON_MEMBER_OP4(powm, "powm");
399
400/*********************************************************************
401*
402* abs/fabs:
403*
404*********************************************************************/
405
406NON_MEMBER_OP2(abs, "abs");
407NON_MEMBER_OP2(fabs, "fabs");
408
409/*********************************************************************
410*
411* Floating point functions:
412*
413*********************************************************************/
414
415NON_MEMBER_OP2(trunc, "trunc");
416NON_MEMBER_OP2(round, "round");
417NON_MEMBER_OP2(exp, "exp");
418NON_MEMBER_OP2(log, "log");
419NON_MEMBER_OP2(log10, "log10");
420NON_MEMBER_OP2(sin, "sin");
421NON_MEMBER_OP2(cos, "cos");
422NON_MEMBER_OP2(tan, "tan");
423NON_MEMBER_OP2(asin, "asin");
424NON_MEMBER_OP2(acos, "acos");
425NON_MEMBER_OP2(atan, "atan");
426NON_MEMBER_OP2(sinh, "sinh");
427NON_MEMBER_OP2(cosh, "cosh");
428NON_MEMBER_OP2(tanh, "tanh");
429NON_MEMBER_OP3(fmod, "fmod");
430NON_MEMBER_OP3(pow, "pow");
431NON_MEMBER_OP3(atan2, "atan2");
432
433} // namespace backends
434
435using backends::debug_adaptor;
436
437template<class Backend>
438struct number_category<backends::debug_adaptor<Backend> > : public number_category<Backend> {};
439
440}} // namespaces
441
442namespace std{
443
444template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
445class numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<Backend>, ExpressionTemplates> >
446 : public std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> >
447{
448 typedef std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> > base_type;
449 typedef boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<Backend>, ExpressionTemplates> number_type;
450public:
451 static number_type (min)() BOOST_NOEXCEPT { return (base_type::min)(); }
452 static number_type (max)() BOOST_NOEXCEPT { return (base_type::max)(); }
453 static number_type lowest() BOOST_NOEXCEPT { return -(max)(); }
454 static number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); }
455 static number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; }
456 static number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); }
457 static number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); }
458 static number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); }
459 static number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); }
460};
461
462} // namespace std
463
464namespace boost{ namespace math{
465
466namespace policies{
467
468template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
469struct precision< boost::multiprecision::number<boost::multiprecision::debug_adaptor<Backend>, ExpressionTemplates>, Policy>
470 : public precision<boost::multiprecision::number<Backend, ExpressionTemplates>, Policy>
471{};
472
473#undef NON_MEMBER_OP1
474#undef NON_MEMBER_OP2
475#undef NON_MEMBER_OP3
476#undef NON_MEMBER_OP4
477
478} // namespace policies
479
480}} // namespaces boost::math
481
482
483#endif
484

source code of boost/boost/multiprecision/debug_adaptor.hpp