Chris@16: /////////////////////////////////////////////////////////////// Chris@16: // Copyright 2012 John Maddock. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ Chris@16: Chris@16: #ifndef BOOST_MATH_DEBUG_ADAPTER_HPP Chris@16: #define BOOST_MATH_DEBUG_ADAPTER_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost{ Chris@16: namespace multiprecision{ Chris@16: namespace backends{ Chris@16: Chris@16: template Chris@16: struct debug_adaptor Chris@16: { Chris@16: typedef typename Backend::signed_types signed_types; Chris@16: typedef typename Backend::unsigned_types unsigned_types; Chris@16: typedef typename Backend::float_types float_types; Chris@16: typedef typename extract_exponent_type< Chris@16: Backend, number_category::value>::type exponent_type; Chris@16: Chris@16: private: Chris@16: std::string debug_value; Chris@16: Backend m_value; Chris@16: public: Chris@16: void update_view() Chris@16: { Chris@16: try Chris@16: { Chris@16: debug_value = m_value.str(0, static_cast(0)); Chris@16: } Chris@16: catch(const std::exception& e) Chris@16: { Chris@16: debug_value = "String conversion failed with message: \""; Chris@16: debug_value += e.what(); Chris@16: debug_value += "\""; Chris@16: } Chris@16: } Chris@16: debug_adaptor() Chris@16: { Chris@16: update_view(); Chris@16: } Chris@16: debug_adaptor(const debug_adaptor& o) : debug_value(o.debug_value), m_value(o.m_value) Chris@16: { Chris@16: } Chris@16: debug_adaptor& operator = (const debug_adaptor& o) Chris@16: { Chris@16: debug_value = o.debug_value; Chris@16: m_value = o.m_value; Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: debug_adaptor(const T& i, const typename enable_if_c::value>::type* = 0) Chris@16: : m_value(i) Chris@16: { Chris@16: update_view(); Chris@16: } Chris@16: template Chris@16: debug_adaptor(const T& i, const T& j) Chris@16: : m_value(i, j) Chris@16: { Chris@16: update_view(); Chris@16: } Chris@16: template Chris@16: typename enable_if_c::value || is_convertible::value, debug_adaptor&>::type operator = (const T& i) Chris@16: { Chris@16: m_value = i; Chris@16: update_view(); Chris@16: return *this; Chris@16: } Chris@16: debug_adaptor& operator = (const char* s) Chris@16: { Chris@16: m_value = s; Chris@16: update_view(); Chris@16: return *this; Chris@16: } Chris@16: void swap(debug_adaptor& o) Chris@16: { Chris@16: std::swap(m_value, o.value()); Chris@16: std::swap(debug_value, o.debug_value); Chris@16: } Chris@16: std::string str(std::streamsize digits, std::ios_base::fmtflags f)const Chris@16: { Chris@16: return m_value.str(digits, f); Chris@16: } Chris@16: void negate() Chris@16: { Chris@16: m_value.negate(); Chris@16: update_view(); Chris@16: } Chris@16: int compare(const debug_adaptor& o)const Chris@16: { Chris@16: return m_value.compare(o.value()); Chris@16: } Chris@16: template Chris@16: int compare(const T& i)const Chris@16: { Chris@16: return m_value.compare(i); Chris@16: } Chris@16: Backend& value() Chris@16: { Chris@16: return m_value; Chris@16: } Chris@16: const Backend& value()const Chris@16: { Chris@16: return m_value; Chris@16: } Chris@16: template Chris@16: void serialize(Archive& ar, const unsigned int /*version*/) Chris@16: { Chris@16: ar & m_value; Chris@16: typedef typename Archive::is_loading tag; Chris@16: if(tag::value) Chris@16: update_view(); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: inline Backend const& unwrap_debug_type(debug_adaptor const& val) Chris@16: { Chris@16: return val.value(); Chris@16: } Chris@16: template Chris@16: inline const T& unwrap_debug_type(const T& val) Chris@16: { Chris@16: return val; Chris@16: } Chris@16: Chris@16: #define NON_MEMBER_OP1(name, str) \ Chris@16: template \ Chris@16: inline void BOOST_JOIN(eval_, name)(debug_adaptor& result)\ Chris@16: {\ Chris@16: using default_ops::BOOST_JOIN(eval_, name);\ Chris@16: BOOST_JOIN(eval_, name)(result.value());\ Chris@16: result.update_view();\ Chris@16: } Chris@16: Chris@16: #define NON_MEMBER_OP2(name, str) \ Chris@16: template \ Chris@16: inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const T& a)\ Chris@16: {\ Chris@16: using default_ops::BOOST_JOIN(eval_, name);\ Chris@16: BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a));\ Chris@16: result.update_view();\ Chris@16: }\ Chris@16: template \ Chris@16: inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const debug_adaptor& a)\ Chris@16: {\ Chris@16: using default_ops::BOOST_JOIN(eval_, name);\ Chris@16: BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a));\ Chris@16: result.update_view();\ Chris@16: } Chris@16: Chris@16: #define NON_MEMBER_OP3(name, str) \ Chris@16: template \ Chris@16: inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const T& a, const U& b)\ Chris@16: {\ Chris@16: using default_ops::BOOST_JOIN(eval_, name);\ Chris@16: BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\ Chris@16: result.update_view();\ Chris@16: }\ Chris@16: template \ Chris@16: inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const debug_adaptor& a, const T& b)\ Chris@16: {\ Chris@16: using default_ops::BOOST_JOIN(eval_, name);\ Chris@16: BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\ Chris@16: result.update_view();\ Chris@16: }\ Chris@16: template \ Chris@16: inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const T& a, const debug_adaptor& b)\ Chris@16: {\ Chris@16: using default_ops::BOOST_JOIN(eval_, name);\ Chris@16: BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\ Chris@16: result.update_view();\ Chris@16: }\ Chris@16: template \ Chris@16: inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const debug_adaptor& a, const debug_adaptor& b)\ Chris@16: {\ Chris@16: using default_ops::BOOST_JOIN(eval_, name);\ Chris@16: BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b));\ Chris@16: result.update_view();\ Chris@16: } Chris@16: Chris@16: #define NON_MEMBER_OP4(name, str) \ Chris@16: template \ Chris@16: inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const T& a, const U& b, const V& c)\ Chris@16: {\ Chris@16: using default_ops::BOOST_JOIN(eval_, name);\ Chris@16: BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\ Chris@16: result.update_view();\ Chris@16: }\ Chris@16: template \ Chris@16: inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const debug_adaptor& a, const debug_adaptor& b, const T& c)\ Chris@16: {\ Chris@16: using default_ops::BOOST_JOIN(eval_, name);\ Chris@16: BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\ Chris@16: result.update_view();\ Chris@16: }\ Chris@16: template \ Chris@16: inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const debug_adaptor& a, const T& b, const debug_adaptor& c)\ Chris@16: {\ Chris@16: using default_ops::BOOST_JOIN(eval_, name);\ Chris@16: BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\ Chris@16: result.update_view();\ Chris@16: }\ Chris@16: template \ Chris@16: inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const T& a, const debug_adaptor& b, const debug_adaptor& c)\ Chris@16: {\ Chris@16: using default_ops::BOOST_JOIN(eval_, name);\ Chris@16: BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\ Chris@16: result.update_view();\ Chris@16: }\ Chris@16: template \ Chris@16: inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const debug_adaptor& a, const debug_adaptor& b, const debug_adaptor& c)\ Chris@16: {\ Chris@16: using default_ops::BOOST_JOIN(eval_, name);\ Chris@16: BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\ Chris@16: result.update_view();\ Chris@16: }\ Chris@16: template \ Chris@16: inline void BOOST_JOIN(eval_, name)(debug_adaptor& result, const debug_adaptor& a, const T& b, const U& c)\ Chris@16: {\ Chris@16: using default_ops::BOOST_JOIN(eval_, name);\ Chris@16: BOOST_JOIN(eval_, name)(result.value(), unwrap_debug_type(a), unwrap_debug_type(b), unwrap_debug_type(c));\ Chris@16: result.update_view();\ Chris@16: }\ Chris@16: Chris@16: NON_MEMBER_OP2(add, "+="); Chris@16: NON_MEMBER_OP2(subtract, "-="); Chris@16: NON_MEMBER_OP2(multiply, "*="); Chris@16: NON_MEMBER_OP2(divide, "/="); Chris@16: Chris@16: template Chris@16: inline void eval_convert_to(R* result, const debug_adaptor& val) Chris@16: { Chris@16: using default_ops::eval_convert_to; Chris@16: eval_convert_to(result, val.value()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_frexp(debug_adaptor& result, const debug_adaptor& arg, Exp* exp) Chris@16: { Chris@16: eval_frexp(result.value(), arg.value(), exp); Chris@101: result.update_view(); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_ldexp(debug_adaptor& result, const debug_adaptor& arg, Exp exp) Chris@16: { Chris@16: eval_ldexp(result.value(), arg.value(), exp); Chris@101: result.update_view(); Chris@101: } Chris@101: Chris@101: template Chris@101: inline void eval_scalbn(debug_adaptor& result, const debug_adaptor& arg, Exp exp) Chris@101: { Chris@101: eval_scalbn(result.value(), arg.value(), exp); Chris@101: result.update_view(); Chris@101: } Chris@101: Chris@101: template Chris@101: inline typename Backend::exponent_type eval_ilogb(const debug_adaptor& arg) Chris@101: { Chris@101: return eval_ilogb(arg.value()); Chris@16: } Chris@16: Chris@16: NON_MEMBER_OP2(floor, "floor"); Chris@16: NON_MEMBER_OP2(ceil, "ceil"); Chris@16: NON_MEMBER_OP2(sqrt, "sqrt"); Chris@101: NON_MEMBER_OP2(logb, "logb"); Chris@16: Chris@16: template Chris@16: inline int eval_fpclassify(const debug_adaptor& arg) Chris@16: { Chris@16: using default_ops::eval_fpclassify; Chris@16: return eval_fpclassify(arg.value()); Chris@16: } Chris@16: Chris@16: /********************************************************************* Chris@16: * Chris@16: * Optional arithmetic operations come next: Chris@16: * Chris@16: *********************************************************************/ Chris@16: Chris@16: NON_MEMBER_OP3(add, "+"); Chris@16: NON_MEMBER_OP3(subtract, "-"); Chris@16: NON_MEMBER_OP3(multiply, "*"); Chris@16: NON_MEMBER_OP3(divide, "/"); Chris@16: NON_MEMBER_OP3(multiply_add, "fused-multiply-add"); Chris@16: NON_MEMBER_OP3(multiply_subtract, "fused-multiply-subtract"); Chris@16: NON_MEMBER_OP4(multiply_add, "fused-multiply-add"); Chris@16: NON_MEMBER_OP4(multiply_subtract, "fused-multiply-subtract"); Chris@16: Chris@16: NON_MEMBER_OP1(increment, "increment"); Chris@16: NON_MEMBER_OP1(decrement, "decrement"); Chris@16: Chris@16: /********************************************************************* Chris@16: * Chris@16: * Optional integer operations come next: Chris@16: * Chris@16: *********************************************************************/ Chris@16: Chris@16: NON_MEMBER_OP2(modulus, "%="); Chris@16: NON_MEMBER_OP3(modulus, "%"); Chris@16: NON_MEMBER_OP2(bitwise_or, "|="); Chris@16: NON_MEMBER_OP3(bitwise_or, "|"); Chris@16: NON_MEMBER_OP2(bitwise_and, "&="); Chris@16: NON_MEMBER_OP3(bitwise_and, "&"); Chris@16: NON_MEMBER_OP2(bitwise_xor, "^="); Chris@16: NON_MEMBER_OP3(bitwise_xor, "^"); Chris@16: NON_MEMBER_OP4(qr, "quotient-and-remainder"); Chris@16: NON_MEMBER_OP2(complement, "~"); Chris@16: Chris@16: template Chris@16: inline void eval_left_shift(debug_adaptor& arg, unsigned a) Chris@16: { Chris@16: using default_ops::eval_left_shift; Chris@16: eval_left_shift(arg.value(), a); Chris@16: arg.update_view();\ Chris@16: } Chris@16: template Chris@16: inline void eval_left_shift(debug_adaptor& arg, const debug_adaptor& a, unsigned b) Chris@16: { Chris@16: using default_ops::eval_left_shift; Chris@16: eval_left_shift(arg.value(), a.value(), b); Chris@16: arg.update_view();\ Chris@16: } Chris@16: template Chris@16: inline void eval_right_shift(debug_adaptor& arg, unsigned a) Chris@16: { Chris@16: using default_ops::eval_right_shift; Chris@16: eval_right_shift(arg.value(), a); Chris@16: arg.update_view();\ Chris@16: } Chris@16: template Chris@16: inline void eval_right_shift(debug_adaptor& arg, const debug_adaptor& a, unsigned b) Chris@16: { Chris@16: using default_ops::eval_right_shift; Chris@16: eval_right_shift(arg.value(), a.value(), b); Chris@16: arg.update_view();\ Chris@16: } Chris@16: Chris@16: template Chris@16: inline unsigned eval_integer_modulus(const debug_adaptor& arg, const T& a) Chris@16: { Chris@16: using default_ops::eval_integer_modulus; Chris@16: return eval_integer_modulus(arg.value(), a); Chris@16: } Chris@16: Chris@16: template Chris@16: inline unsigned eval_lsb(const debug_adaptor& arg) Chris@16: { Chris@16: using default_ops::eval_lsb; Chris@16: return eval_lsb(arg.value()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline unsigned eval_msb(const debug_adaptor& arg) Chris@16: { Chris@16: using default_ops::eval_msb; Chris@16: return eval_msb(arg.value()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool eval_bit_test(const debug_adaptor& arg, unsigned a) Chris@16: { Chris@16: using default_ops::eval_bit_test; Chris@16: return eval_bit_test(arg.value(), a); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_bit_set(const debug_adaptor& arg, unsigned a) Chris@16: { Chris@16: using default_ops::eval_bit_set; Chris@16: eval_bit_set(arg.value(), a); Chris@16: arg.update_view();\ Chris@16: } Chris@16: template Chris@16: inline void eval_bit_unset(const debug_adaptor& arg, unsigned a) Chris@16: { Chris@16: using default_ops::eval_bit_unset; Chris@16: eval_bit_unset(arg.value(), a); Chris@16: arg.update_view();\ Chris@16: } Chris@16: template Chris@16: inline void eval_bit_flip(const debug_adaptor& arg, unsigned a) Chris@16: { Chris@16: using default_ops::eval_bit_flip; Chris@16: eval_bit_flip(arg.value(), a); Chris@16: arg.update_view();\ Chris@16: } Chris@16: Chris@16: NON_MEMBER_OP3(gcd, "gcd"); Chris@16: NON_MEMBER_OP3(lcm, "lcm"); Chris@16: NON_MEMBER_OP4(powm, "powm"); Chris@16: Chris@16: /********************************************************************* Chris@16: * Chris@16: * abs/fabs: Chris@16: * Chris@16: *********************************************************************/ Chris@16: Chris@16: NON_MEMBER_OP2(abs, "abs"); Chris@16: NON_MEMBER_OP2(fabs, "fabs"); Chris@16: Chris@16: /********************************************************************* Chris@16: * Chris@16: * Floating point functions: Chris@16: * Chris@16: *********************************************************************/ Chris@16: Chris@16: NON_MEMBER_OP2(trunc, "trunc"); Chris@16: NON_MEMBER_OP2(round, "round"); Chris@16: NON_MEMBER_OP2(exp, "exp"); Chris@16: NON_MEMBER_OP2(log, "log"); Chris@16: NON_MEMBER_OP2(log10, "log10"); Chris@16: NON_MEMBER_OP2(sin, "sin"); Chris@16: NON_MEMBER_OP2(cos, "cos"); Chris@16: NON_MEMBER_OP2(tan, "tan"); Chris@16: NON_MEMBER_OP2(asin, "asin"); Chris@16: NON_MEMBER_OP2(acos, "acos"); Chris@16: NON_MEMBER_OP2(atan, "atan"); Chris@16: NON_MEMBER_OP2(sinh, "sinh"); Chris@16: NON_MEMBER_OP2(cosh, "cosh"); Chris@16: NON_MEMBER_OP2(tanh, "tanh"); Chris@16: NON_MEMBER_OP3(fmod, "fmod"); Chris@16: NON_MEMBER_OP3(pow, "pow"); Chris@16: NON_MEMBER_OP3(atan2, "atan2"); Chris@16: Chris@16: } // namespace backends Chris@16: Chris@16: using backends::debug_adaptor; Chris@16: Chris@16: template Chris@16: struct number_category > : public number_category {}; Chris@16: Chris@16: }} // namespaces Chris@16: Chris@16: namespace std{ Chris@16: Chris@16: template Chris@16: class numeric_limits, ExpressionTemplates> > Chris@16: : public std::numeric_limits > Chris@16: { Chris@16: typedef std::numeric_limits > base_type; Chris@16: typedef boost::multiprecision::number, ExpressionTemplates> number_type; Chris@16: public: Chris@16: static number_type (min)() BOOST_NOEXCEPT { return (base_type::min)(); } Chris@16: static number_type (max)() BOOST_NOEXCEPT { return (base_type::max)(); } Chris@16: static number_type lowest() BOOST_NOEXCEPT { return -(max)(); } Chris@16: static number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); } Chris@16: static number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; } Chris@16: static number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); } Chris@16: static number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); } Chris@16: static number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); } Chris@16: static number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); } Chris@16: }; Chris@16: Chris@16: } // namespace std Chris@16: Chris@16: namespace boost{ namespace math{ Chris@16: Chris@16: namespace policies{ Chris@16: Chris@16: template Chris@16: struct precision< boost::multiprecision::number, ExpressionTemplates>, Policy> Chris@16: : public precision, Policy> Chris@16: {}; Chris@16: Chris@16: #undef NON_MEMBER_OP1 Chris@16: #undef NON_MEMBER_OP2 Chris@16: #undef NON_MEMBER_OP3 Chris@16: #undef NON_MEMBER_OP4 Chris@16: Chris@16: } // namespace policies Chris@16: Chris@16: }} // namespaces boost::math Chris@16: Chris@16: Chris@16: #endif