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
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;
37 #ifndef BOOST_NO_EXCEPTIONS
41 debug_value = m_value.str(0, static_cast<std::ios_base::fmtflags>(0));
42 #ifndef BOOST_NO_EXCEPTIONS
44 catch (const std::exception& e)
46 debug_value = "String conversion failed with message: \"";
47 debug_value += e.what();
56 debug_adaptor(const debug_adaptor& o) : debug_value(o.debug_value), m_value(o.m_value)
59 debug_adaptor& operator=(const debug_adaptor& o)
61 debug_value = o.debug_value;
66 debug_adaptor(const T& i, const typename enable_if_c<is_convertible<T, Backend>::value>::type* = 0)
72 debug_adaptor(const T& i, const T& j)
78 typename enable_if_c<is_arithmetic<T>::value || is_convertible<T, Backend>::value, debug_adaptor&>::type operator=(const T& i)
84 debug_adaptor& operator=(const char* s)
90 void swap(debug_adaptor& o)
92 std::swap(m_value, o.value());
93 std::swap(debug_value, o.debug_value);
95 std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
97 return m_value.str(digits, f);
104 int compare(const debug_adaptor& o) const
106 return m_value.compare(o.value());
109 int compare(const T& i) const
111 return m_value.compare(i);
117 const Backend& value() const
121 template <class Archive>
122 void serialize(Archive& ar, const unsigned int /*version*/)
124 ar & boost::make_nvp("value", m_value);
125 typedef typename Archive::is_loading tag;
129 static unsigned default_precision() BOOST_NOEXCEPT
131 return Backend::default_precision();
133 static void default_precision(unsigned v) BOOST_NOEXCEPT
135 Backend::default_precision(v);
137 unsigned precision() const BOOST_NOEXCEPT
139 return value().precision();
141 void precision(unsigned digits10) BOOST_NOEXCEPT
143 value().precision(digits10);
147 template <class Backend>
148 inline Backend const& unwrap_debug_type(debug_adaptor<Backend> const& val)
153 inline const T& unwrap_debug_type(const T& val)
158 #define NON_MEMBER_OP1(name, str) \
159 template <class Backend> \
160 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result) \
162 using default_ops::BOOST_JOIN(eval_, name); \
163 BOOST_JOIN(eval_, name) \
165 result.update_view(); \
168 #define NON_MEMBER_OP2(name, str) \
169 template <class Backend, class T> \
170 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const T& a) \
172 using default_ops::BOOST_JOIN(eval_, name); \
173 BOOST_JOIN(eval_, name) \
174 (result.value(), unwrap_debug_type(a)); \
175 result.update_view(); \
177 template <class Backend> \
178 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const debug_adaptor<Backend>& a) \
180 using default_ops::BOOST_JOIN(eval_, name); \
181 BOOST_JOIN(eval_, name) \
182 (result.value(), unwrap_debug_type(a)); \
183 result.update_view(); \
186 #define NON_MEMBER_OP3(name, str) \
187 template <class Backend, class T, class U> \
188 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const T& a, const U& b) \
190 using default_ops::BOOST_JOIN(eval_, name); \
191 BOOST_JOIN(eval_, name) \
192 (result.value(), unwrap_debug_type(a), unwrap_debug_type(b)); \
193 result.update_view(); \
195 template <class Backend, class T> \
196 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const debug_adaptor<Backend>& a, const T& b) \
198 using default_ops::BOOST_JOIN(eval_, name); \
199 BOOST_JOIN(eval_, name) \
200 (result.value(), unwrap_debug_type(a), unwrap_debug_type(b)); \
201 result.update_view(); \
203 template <class Backend, class T> \
204 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const T& a, const debug_adaptor<Backend>& b) \
206 using default_ops::BOOST_JOIN(eval_, name); \
207 BOOST_JOIN(eval_, name) \
208 (result.value(), unwrap_debug_type(a), unwrap_debug_type(b)); \
209 result.update_view(); \
211 template <class Backend> \
212 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const debug_adaptor<Backend>& a, const debug_adaptor<Backend>& b) \
214 using default_ops::BOOST_JOIN(eval_, name); \
215 BOOST_JOIN(eval_, name) \
216 (result.value(), unwrap_debug_type(a), unwrap_debug_type(b)); \
217 result.update_view(); \
220 #define NON_MEMBER_OP4(name, str) \
221 template <class Backend, class T, class U, class V> \
222 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const T& a, const U& b, const V& c) \
224 using default_ops::BOOST_JOIN(eval_, name); \
225 BOOST_JOIN(eval_, name) \
226 (result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c)); \
227 result.update_view(); \
229 template <class Backend, class T> \
230 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const debug_adaptor<Backend>& a, const debug_adaptor<Backend>& b, const T& c) \
232 using default_ops::BOOST_JOIN(eval_, name); \
233 BOOST_JOIN(eval_, name) \
234 (result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c)); \
235 result.update_view(); \
237 template <class Backend, class T> \
238 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const debug_adaptor<Backend>& a, const T& b, const debug_adaptor<Backend>& c) \
240 using default_ops::BOOST_JOIN(eval_, name); \
241 BOOST_JOIN(eval_, name) \
242 (result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c)); \
243 result.update_view(); \
245 template <class Backend, class T> \
246 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const T& a, const debug_adaptor<Backend>& b, const debug_adaptor<Backend>& c) \
248 using default_ops::BOOST_JOIN(eval_, name); \
249 BOOST_JOIN(eval_, name) \
250 (result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c)); \
251 result.update_view(); \
253 template <class Backend> \
254 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) \
256 using default_ops::BOOST_JOIN(eval_, name); \
257 BOOST_JOIN(eval_, name) \
258 (result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c)); \
259 result.update_view(); \
261 template <class Backend, class T, class U> \
262 inline void BOOST_JOIN(eval_, name)(debug_adaptor<Backend> & result, const debug_adaptor<Backend>& a, const T& b, const U& c) \
264 using default_ops::BOOST_JOIN(eval_, name); \
265 BOOST_JOIN(eval_, name) \
266 (result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c)); \
267 result.update_view(); \
270 NON_MEMBER_OP2(add, "+=")
271 NON_MEMBER_OP2(subtract, "-=")
272 NON_MEMBER_OP2(multiply, "*=")
273 NON_MEMBER_OP2(divide, "/=")
275 template <class Backend, class R>
276 inline void eval_convert_to(R* result, const debug_adaptor<Backend>& val)
278 using default_ops::eval_convert_to;
279 eval_convert_to(result, val.value());
282 template <class Backend, class Exp>
283 inline void eval_frexp(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& arg, Exp* exp)
285 eval_frexp(result.value(), arg.value(), exp);
286 result.update_view();
289 template <class Backend, class Exp>
290 inline void eval_ldexp(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& arg, Exp exp)
292 eval_ldexp(result.value(), arg.value(), exp);
293 result.update_view();
296 template <class Backend, class Exp>
297 inline void eval_scalbn(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& arg, Exp exp)
299 using default_ops::eval_scalbn;
300 eval_scalbn(result.value(), arg.value(), exp);
301 result.update_view();
304 template <class Backend>
305 inline typename Backend::exponent_type eval_ilogb(const debug_adaptor<Backend>& arg)
307 using default_ops::eval_ilogb;
308 return eval_ilogb(arg.value());
311 NON_MEMBER_OP2(floor, "floor")
312 NON_MEMBER_OP2(ceil, "ceil")
313 NON_MEMBER_OP2(sqrt, "sqrt")
314 NON_MEMBER_OP2(logb, "logb")
316 template <class Backend>
317 inline int eval_fpclassify(const debug_adaptor<Backend>& arg)
319 using default_ops::eval_fpclassify;
320 return eval_fpclassify(arg.value());
323 /*********************************************************************
325 * Optional arithmetic operations come next:
327 *********************************************************************/
329 NON_MEMBER_OP3(add, "+")
330 NON_MEMBER_OP3(subtract, "-")
331 NON_MEMBER_OP3(multiply, "*")
332 NON_MEMBER_OP3(divide, "/")
333 NON_MEMBER_OP3(multiply_add, "fused-multiply-add")
334 NON_MEMBER_OP3(multiply_subtract, "fused-multiply-subtract")
335 NON_MEMBER_OP4(multiply_add, "fused-multiply-add")
336 NON_MEMBER_OP4(multiply_subtract, "fused-multiply-subtract")
338 NON_MEMBER_OP1(increment, "increment")
339 NON_MEMBER_OP1(decrement, "decrement")
341 /*********************************************************************
343 * Optional integer operations come next:
345 *********************************************************************/
347 NON_MEMBER_OP2(modulus, "%=")
348 NON_MEMBER_OP3(modulus, "%")
349 NON_MEMBER_OP2(bitwise_or, "|=")
350 NON_MEMBER_OP3(bitwise_or, "|")
351 NON_MEMBER_OP2(bitwise_and, "&=")
352 NON_MEMBER_OP3(bitwise_and, "&")
353 NON_MEMBER_OP2(bitwise_xor, "^=")
354 NON_MEMBER_OP3(bitwise_xor, "^")
355 NON_MEMBER_OP4(qr, "quotient-and-remainder")
356 NON_MEMBER_OP2(complement, "~")
358 template <class Backend>
359 inline void eval_left_shift(debug_adaptor<Backend>& arg, std::size_t a)
361 using default_ops::eval_left_shift;
362 eval_left_shift(arg.value(), a);
365 template <class Backend>
366 inline void eval_left_shift(debug_adaptor<Backend>& arg, const debug_adaptor<Backend>& a, std::size_t b)
368 using default_ops::eval_left_shift;
369 eval_left_shift(arg.value(), a.value(), b);
372 template <class Backend>
373 inline void eval_right_shift(debug_adaptor<Backend>& arg, std::size_t a)
375 using default_ops::eval_right_shift;
376 eval_right_shift(arg.value(), a);
379 template <class Backend>
380 inline void eval_right_shift(debug_adaptor<Backend>& arg, const debug_adaptor<Backend>& a, std::size_t b)
382 using default_ops::eval_right_shift;
383 eval_right_shift(arg.value(), a.value(), b);
387 template <class Backend, class T>
388 inline unsigned eval_integer_modulus(const debug_adaptor<Backend>& arg, const T& a)
390 using default_ops::eval_integer_modulus;
391 return eval_integer_modulus(arg.value(), a);
394 template <class Backend>
395 inline unsigned eval_lsb(const debug_adaptor<Backend>& arg)
397 using default_ops::eval_lsb;
398 return eval_lsb(arg.value());
401 template <class Backend>
402 inline unsigned eval_msb(const debug_adaptor<Backend>& arg)
404 using default_ops::eval_msb;
405 return eval_msb(arg.value());
408 template <class Backend>
409 inline bool eval_bit_test(const debug_adaptor<Backend>& arg, unsigned a)
411 using default_ops::eval_bit_test;
412 return eval_bit_test(arg.value(), a);
415 template <class Backend>
416 inline void eval_bit_set(const debug_adaptor<Backend>& arg, unsigned a)
418 using default_ops::eval_bit_set;
419 eval_bit_set(arg.value(), a);
422 template <class Backend>
423 inline void eval_bit_unset(const debug_adaptor<Backend>& arg, unsigned a)
425 using default_ops::eval_bit_unset;
426 eval_bit_unset(arg.value(), a);
429 template <class Backend>
430 inline void eval_bit_flip(const debug_adaptor<Backend>& arg, unsigned a)
432 using default_ops::eval_bit_flip;
433 eval_bit_flip(arg.value(), a);
437 NON_MEMBER_OP3(gcd, "gcd")
438 NON_MEMBER_OP3(lcm, "lcm")
439 NON_MEMBER_OP4(powm, "powm")
441 /*********************************************************************
445 *********************************************************************/
447 NON_MEMBER_OP2(abs, "abs")
448 NON_MEMBER_OP2(fabs, "fabs")
450 /*********************************************************************
452 * Floating point functions:
454 *********************************************************************/
456 NON_MEMBER_OP2(trunc, "trunc")
457 NON_MEMBER_OP2(round, "round")
458 NON_MEMBER_OP2(exp, "exp")
459 NON_MEMBER_OP2(log, "log")
460 NON_MEMBER_OP2(log10, "log10")
461 NON_MEMBER_OP2(sin, "sin")
462 NON_MEMBER_OP2(cos, "cos")
463 NON_MEMBER_OP2(tan, "tan")
464 NON_MEMBER_OP2(asin, "asin")
465 NON_MEMBER_OP2(acos, "acos")
466 NON_MEMBER_OP2(atan, "atan")
467 NON_MEMBER_OP2(sinh, "sinh")
468 NON_MEMBER_OP2(cosh, "cosh")
469 NON_MEMBER_OP2(tanh, "tanh")
470 NON_MEMBER_OP3(fmod, "fmod")
471 NON_MEMBER_OP3(pow, "pow")
472 NON_MEMBER_OP3(atan2, "atan2")
474 template <class Backend>
475 int eval_signbit(const debug_adaptor<Backend>& val)
477 return eval_signbit(val.value());
480 template <class Backend>
481 std::size_t hash_value(const debug_adaptor<Backend>& val)
483 return hash_value(val.value());
486 } // namespace backends
488 using backends::debug_adaptor;
490 template <class Backend>
491 struct number_category<backends::debug_adaptor<Backend> > : public number_category<Backend>
497 }} // namespace boost::multiprecision
501 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
502 class numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<Backend>, ExpressionTemplates> >
503 : public std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> >
505 typedef std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> > base_type;
506 typedef boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<Backend>, ExpressionTemplates> number_type;
509 static number_type(min)() BOOST_NOEXCEPT { return (base_type::min)(); }
510 static number_type(max)() BOOST_NOEXCEPT { return (base_type::max)(); }
511 static number_type lowest() BOOST_NOEXCEPT { return -(max)(); }
512 static number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); }
513 static number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; }
514 static number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); }
515 static number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); }
516 static number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); }
517 static number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); }
527 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
528 struct precision<boost::multiprecision::number<boost::multiprecision::debug_adaptor<Backend>, ExpressionTemplates>, Policy>
529 : public precision<boost::multiprecision::number<Backend, ExpressionTemplates>, Policy>
532 #undef NON_MEMBER_OP1
533 #undef NON_MEMBER_OP2
534 #undef NON_MEMBER_OP3
535 #undef NON_MEMBER_OP4
539 }} // namespace boost::math::policies