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_
6 #ifndef BOOST_MATH_DEBUG_ADAPTER_HPP
7 #define BOOST_MATH_DEBUG_ADAPTER_HPP
9 #include <boost/multiprecision/traits/extract_exponent_type.hpp>
10 #include <boost/multiprecision/detail/integer_ops.hpp>
13 namespace multiprecision{
18 #pragma warning(disable:4127) // conditional expression is constant
21 template <class Backend>
24 typedef typename Backend::signed_types signed_types;
25 typedef typename Backend::unsigned_types unsigned_types;
26 typedef typename Backend::float_types float_types;
27 typedef typename extract_exponent_type<
28 Backend, number_category<Backend>::value>::type exponent_type;
31 std::string debug_value;
36 #ifndef BOOST_NO_EXCEPTIONS
40 debug_value = m_value.str(0, static_cast<std::ios_base::fmtflags>(0));
41 #ifndef BOOST_NO_EXCEPTIONS
43 catch(const std::exception& e)
45 debug_value = "String conversion failed with message: \"";
46 debug_value += e.what();
55 debug_adaptor(const debug_adaptor& o) : debug_value(o.debug_value), m_value(o.m_value)
58 debug_adaptor& operator = (const debug_adaptor& o)
60 debug_value = o.debug_value;
65 debug_adaptor(const T& i, const typename enable_if_c<is_convertible<T, Backend>::value>::type* = 0)
71 debug_adaptor(const T& i, const T& j)
77 typename enable_if_c<is_arithmetic<T>::value || is_convertible<T, Backend>::value, debug_adaptor&>::type operator = (const T& i)
83 debug_adaptor& operator = (const char* s)
89 void swap(debug_adaptor& o)
91 std::swap(m_value, o.value());
92 std::swap(debug_value, o.debug_value);
94 std::string str(std::streamsize digits, std::ios_base::fmtflags f)const
96 return m_value.str(digits, f);
103 int compare(const debug_adaptor& o)const
105 return m_value.compare(o.value());
108 int compare(const T& i)const
110 return m_value.compare(i);
116 const Backend& value()const
120 template <class Archive>
121 void serialize(Archive& ar, const unsigned int /*version*/)
124 typedef typename Archive::is_loading tag;
128 static unsigned default_precision() BOOST_NOEXCEPT
130 return Backend::default_precision();
132 static void default_precision(unsigned v) BOOST_NOEXCEPT
134 Backend::default_precision(v);
136 unsigned precision()const BOOST_NOEXCEPT
138 return value().precision();
140 void precision(unsigned digits10) BOOST_NOEXCEPT
142 value().precision(digits10);
146 template <class Backend>
147 inline Backend const& unwrap_debug_type(debug_adaptor<Backend> const& val)
152 inline const T& unwrap_debug_type(const T& val)
157 #define NON_MEMBER_OP1(name, str) \
158 template <class Backend>\
159 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result)\
161 using default_ops::BOOST_JOIN(eval_, name);\
162 BOOST_JOIN(eval_, name)(result.value());\
163 result.update_view();\
166 #define NON_MEMBER_OP2(name, str) \
167 template <class Backend, class T>\
168 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const T& a)\
170 using default_ops::BOOST_JOIN(eval_, name);\
171 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a));\
172 result.update_view();\
174 template <class Backend>\
175 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a)\
177 using default_ops::BOOST_JOIN(eval_, name);\
178 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a));\
179 result.update_view();\
182 #define NON_MEMBER_OP3(name, str) \
183 template <class Backend, class T, class U>\
184 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const T& a, const U& b)\
186 using default_ops::BOOST_JOIN(eval_, name);\
187 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\
188 result.update_view();\
190 template <class Backend, class T>\
191 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a, const T& b)\
193 using default_ops::BOOST_JOIN(eval_, name);\
194 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\
195 result.update_view();\
197 template <class Backend, class T>\
198 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const T& a, const debug_adaptor<Backend>& b)\
200 using default_ops::BOOST_JOIN(eval_, name);\
201 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\
202 result.update_view();\
204 template <class Backend>\
205 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a, const debug_adaptor<Backend>& b)\
207 using default_ops::BOOST_JOIN(eval_, name);\
208 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\
209 result.update_view();\
212 #define NON_MEMBER_OP4(name, str) \
213 template <class Backend, class T, class U, class V>\
214 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const T& a, const U& b, const V& c)\
216 using default_ops::BOOST_JOIN(eval_, name);\
217 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
218 result.update_view();\
220 template <class Backend, class T>\
221 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a, const debug_adaptor<Backend>& b, const T& c)\
223 using default_ops::BOOST_JOIN(eval_, name);\
224 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
225 result.update_view();\
227 template <class Backend, class T>\
228 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a, const T& b, const debug_adaptor<Backend>& c)\
230 using default_ops::BOOST_JOIN(eval_, name);\
231 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
232 result.update_view();\
234 template <class Backend, class T>\
235 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const T& a, const debug_adaptor<Backend>& b, const debug_adaptor<Backend>& c)\
237 using default_ops::BOOST_JOIN(eval_, name);\
238 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
239 result.update_view();\
241 template <class Backend>\
242 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)\
244 using default_ops::BOOST_JOIN(eval_, name);\
245 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
246 result.update_view();\
248 template <class Backend, class T, class U>\
249 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& a, const T& b, const U& c)\
251 using default_ops::BOOST_JOIN(eval_, name);\
252 BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\
253 result.update_view();\
256 NON_MEMBER_OP2(add, "+=");
257 NON_MEMBER_OP2(subtract, "-=");
258 NON_MEMBER_OP2(multiply, "*=");
259 NON_MEMBER_OP2(divide, "/=");
261 template <class Backend, class R>
262 inline void eval_convert_to(R* result, const debug_adaptor<Backend>& val)
264 using default_ops::eval_convert_to;
265 eval_convert_to(result, val.value());
268 template <class Backend, class Exp>
269 inline void eval_frexp(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& arg, Exp* exp)
271 eval_frexp(result.value(), arg.value(), exp);
272 result.update_view();
275 template <class Backend, class Exp>
276 inline void eval_ldexp(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& arg, Exp exp)
278 eval_ldexp(result.value(), arg.value(), exp);
279 result.update_view();
282 template <class Backend, class Exp>
283 inline void eval_scalbn(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& arg, Exp exp)
285 eval_scalbn(result.value(), arg.value(), exp);
286 result.update_view();
289 template <class Backend>
290 inline typename Backend::exponent_type eval_ilogb(const debug_adaptor<Backend>& arg)
292 return eval_ilogb(arg.value());
295 NON_MEMBER_OP2(floor, "floor");
296 NON_MEMBER_OP2(ceil, "ceil");
297 NON_MEMBER_OP2(sqrt, "sqrt");
298 NON_MEMBER_OP2(logb, "logb");
300 template <class Backend>
301 inline int eval_fpclassify(const debug_adaptor<Backend>& arg)
303 using default_ops::eval_fpclassify;
304 return eval_fpclassify(arg.value());
307 /*********************************************************************
309 * Optional arithmetic operations come next:
311 *********************************************************************/
313 NON_MEMBER_OP3(add, "+");
314 NON_MEMBER_OP3(subtract, "-");
315 NON_MEMBER_OP3(multiply, "*");
316 NON_MEMBER_OP3(divide, "/");
317 NON_MEMBER_OP3(multiply_add, "fused-multiply-add");
318 NON_MEMBER_OP3(multiply_subtract, "fused-multiply-subtract");
319 NON_MEMBER_OP4(multiply_add, "fused-multiply-add");
320 NON_MEMBER_OP4(multiply_subtract, "fused-multiply-subtract");
322 NON_MEMBER_OP1(increment, "increment");
323 NON_MEMBER_OP1(decrement, "decrement");
325 /*********************************************************************
327 * Optional integer operations come next:
329 *********************************************************************/
331 NON_MEMBER_OP2(modulus, "%=");
332 NON_MEMBER_OP3(modulus, "%");
333 NON_MEMBER_OP2(bitwise_or, "|=");
334 NON_MEMBER_OP3(bitwise_or, "|");
335 NON_MEMBER_OP2(bitwise_and, "&=");
336 NON_MEMBER_OP3(bitwise_and, "&");
337 NON_MEMBER_OP2(bitwise_xor, "^=");
338 NON_MEMBER_OP3(bitwise_xor, "^");
339 NON_MEMBER_OP4(qr, "quotient-and-remainder");
340 NON_MEMBER_OP2(complement, "~");
342 template <class Backend>
343 inline void eval_left_shift(debug_adaptor<Backend>& arg, unsigned a)
345 using default_ops::eval_left_shift;
346 eval_left_shift(arg.value(), a);
349 template <class Backend>
350 inline void eval_left_shift(debug_adaptor<Backend>& arg, const debug_adaptor<Backend>& a, unsigned b)
352 using default_ops::eval_left_shift;
353 eval_left_shift(arg.value(), a.value(), b);
356 template <class Backend>
357 inline void eval_right_shift(debug_adaptor<Backend>& arg, unsigned a)
359 using default_ops::eval_right_shift;
360 eval_right_shift(arg.value(), a);
363 template <class Backend>
364 inline void eval_right_shift(debug_adaptor<Backend>& arg, const debug_adaptor<Backend>& a, unsigned b)
366 using default_ops::eval_right_shift;
367 eval_right_shift(arg.value(), a.value(), b);
371 template <class Backend, class T>
372 inline unsigned eval_integer_modulus(const debug_adaptor<Backend>& arg, const T& a)
374 using default_ops::eval_integer_modulus;
375 return eval_integer_modulus(arg.value(), a);
378 template <class Backend>
379 inline unsigned eval_lsb(const debug_adaptor<Backend>& arg)
381 using default_ops::eval_lsb;
382 return eval_lsb(arg.value());
385 template <class Backend>
386 inline unsigned eval_msb(const debug_adaptor<Backend>& arg)
388 using default_ops::eval_msb;
389 return eval_msb(arg.value());
392 template <class Backend>
393 inline bool eval_bit_test(const debug_adaptor<Backend>& arg, unsigned a)
395 using default_ops::eval_bit_test;
396 return eval_bit_test(arg.value(), a);
399 template <class Backend>
400 inline void eval_bit_set(const debug_adaptor<Backend>& arg, unsigned a)
402 using default_ops::eval_bit_set;
403 eval_bit_set(arg.value(), a);
406 template <class Backend>
407 inline void eval_bit_unset(const debug_adaptor<Backend>& arg, unsigned a)
409 using default_ops::eval_bit_unset;
410 eval_bit_unset(arg.value(), a);
413 template <class Backend>
414 inline void eval_bit_flip(const debug_adaptor<Backend>& arg, unsigned a)
416 using default_ops::eval_bit_flip;
417 eval_bit_flip(arg.value(), a);
421 NON_MEMBER_OP3(gcd, "gcd");
422 NON_MEMBER_OP3(lcm, "lcm");
423 NON_MEMBER_OP4(powm, "powm");
425 /*********************************************************************
429 *********************************************************************/
431 NON_MEMBER_OP2(abs, "abs");
432 NON_MEMBER_OP2(fabs, "fabs");
434 /*********************************************************************
436 * Floating point functions:
438 *********************************************************************/
440 NON_MEMBER_OP2(trunc, "trunc");
441 NON_MEMBER_OP2(round, "round");
442 NON_MEMBER_OP2(exp, "exp");
443 NON_MEMBER_OP2(log, "log");
444 NON_MEMBER_OP2(log10, "log10");
445 NON_MEMBER_OP2(sin, "sin");
446 NON_MEMBER_OP2(cos, "cos");
447 NON_MEMBER_OP2(tan, "tan");
448 NON_MEMBER_OP2(asin, "asin");
449 NON_MEMBER_OP2(acos, "acos");
450 NON_MEMBER_OP2(atan, "atan");
451 NON_MEMBER_OP2(sinh, "sinh");
452 NON_MEMBER_OP2(cosh, "cosh");
453 NON_MEMBER_OP2(tanh, "tanh");
454 NON_MEMBER_OP3(fmod, "fmod");
455 NON_MEMBER_OP3(pow, "pow");
456 NON_MEMBER_OP3(atan2, "atan2");
458 template <class Backend>
459 std::size_t hash_value(const debug_adaptor<Backend>& val)
461 return hash_value(val.value());
465 } // namespace backends
467 using backends::debug_adaptor;
469 template<class Backend>
470 struct number_category<backends::debug_adaptor<Backend> > : public number_category<Backend> {};
479 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
480 class numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<Backend>, ExpressionTemplates> >
481 : public std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> >
483 typedef std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> > base_type;
484 typedef boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<Backend>, ExpressionTemplates> number_type;
486 static number_type (min)() BOOST_NOEXCEPT { return (base_type::min)(); }
487 static number_type (max)() BOOST_NOEXCEPT { return (base_type::max)(); }
488 static number_type lowest() BOOST_NOEXCEPT { return -(max)(); }
489 static number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); }
490 static number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; }
491 static number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); }
492 static number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); }
493 static number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); }
494 static number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); }
499 namespace boost{ namespace math{
503 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
504 struct precision< boost::multiprecision::number<boost::multiprecision::debug_adaptor<Backend>, ExpressionTemplates>, Policy>
505 : public precision<boost::multiprecision::number<Backend, ExpressionTemplates>, Policy>
508 #undef NON_MEMBER_OP1
509 #undef NON_MEMBER_OP2
510 #undef NON_MEMBER_OP3
511 #undef NON_MEMBER_OP4
513 } // namespace policies
515 }} // namespaces boost::math