diff --git a/include/boost/multiprecision/detail/default_ops.hpp b/include/boost/multiprecision/detail/default_ops.hpp index 9ab878b3..6aa0b489 100644 --- a/include/boost/multiprecision/detail/default_ops.hpp +++ b/include/boost/multiprecision/detail/default_ops.hpp @@ -1699,6 +1699,21 @@ inline int eval_signbit(const T& val) return eval_get_sign(val) < 0 ? 1 : 0; } +// +// Real and imaginary parts: +// +template +inline void eval_real(To& to, const From& from) +{ + to = from; +} +template +inline void eval_imag(To& to, const From& from) +{ + typedef typename mpl::front::type ui_type; + to = ui_type(0); +} + // // These functions are implemented in separate files, but expanded inline here, // DO NOT CHANGE THE ORDER OF THESE INCLUDES: @@ -1830,12 +1845,27 @@ inline typename multiprecision::detail::expression::result_ return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b)); } // -// Complex number functions, these are overloaded at the Backend level, we just provide the -// expression template versions here: +// real and imag: // +template +inline typename real_and_imag_result >::type + real(const multiprecision::number& a) +{ + typename real_and_imag_result >::type result; + eval_real(result.backend(), a.backend()); + return result; +} +template +inline typename real_and_imag_result >::type + imag(const multiprecision::number& a) +{ + typename real_and_imag_result >::type result; + eval_imag(result.backend(), a.backend()); + return result; +} + template -inline typename boost::enable_if_c::result_type>::value == number_kind_complex, - typename component_type::result_type>::type>::type +inline typename component_type::result_type>::type real(const multiprecision::detail::expression& arg) { typedef typename multiprecision::detail::expression::result_type value_type; @@ -1843,14 +1873,17 @@ inline typename boost::enable_if_c -inline typename boost::enable_if_c::result_type>::value == number_kind_complex, - typename component_type::result_type>::type>::type +inline typename component_type::result_type>::type imag(const multiprecision::detail::expression& arg) { typedef typename multiprecision::detail::expression::result_type value_type; return imag(value_type(arg)); } +// +// Complex number functions, these are overloaded at the Backend level, we just provide the +// expression template versions here: +// template inline typename boost::lazy_enable_if_c::value == number_kind_complex, component_type > >::type abs(const number& v) diff --git a/include/boost/multiprecision/detail/number_base.hpp b/include/boost/multiprecision/detail/number_base.hpp index 0f3d704d..b517662b 100644 --- a/include/boost/multiprecision/detail/number_base.hpp +++ b/include/boost/multiprecision/detail/number_base.hpp @@ -1043,13 +1043,6 @@ template struct is_interval_number : public mpl::false_ {}; template struct is_interval_number > : public is_interval_number{}; -// -// These will never be enabled, but their presence allows us to use real() and imag() for ADL later: -// -template -typename boost::enable_if_c::type real(); -template -typename boost::enable_if_c::type imag(); }} // namespaces diff --git a/include/boost/multiprecision/mpc.hpp b/include/boost/multiprecision/mpc.hpp index 3cf8fc3e..9f122025 100644 --- a/include/boost/multiprecision/mpc.hpp +++ b/include/boost/multiprecision/mpc.hpp @@ -875,6 +875,17 @@ inline void eval_proj(mpc_float_backend& result, const mpc_float_backe mpc_proj(result.data(), arg.data(), GMP_RNDN); } +template +inline void eval_real(mpfr_float_backend& result, const mpc_float_backend& arg) +{ + mpc_real(result.data(), arg.data(), GMP_RNDN); +} +template +inline void eval_imag(mpfr_float_backend& result, const mpc_float_backend& arg) +{ + mpc_imag(result.data(), arg.data(), GMP_RNDN); +} + template inline std::size_t hash_value(const mpc_float_backend& val) { @@ -928,24 +939,6 @@ struct component_type, ExpressionTemplates> > typedef number, ExpressionTemplates> type; }; -template -inline typename component_type, ExpressionTemplates> >::type - real(const boost::multiprecision::number, ExpressionTemplates>& arg) -{ - typename component_type, ExpressionTemplates> >::type result; - mpc_real(result.backend().data(), arg.backend().data(), GMP_RNDN); - return result; -} - -template -inline typename component_type, ExpressionTemplates> >::type - imag(const boost::multiprecision::number, ExpressionTemplates>& arg) -{ - typename component_type, ExpressionTemplates> >::type result; - mpc_imag(result.backend().data(), arg.backend().data(), GMP_RNDN); - return result; -} - template number > polar(number, ExpressionTemplates>const& r, number, ExpressionTemplates> const& theta) { diff --git a/include/boost/multiprecision/number.hpp b/include/boost/multiprecision/number.hpp index fb71fde5..7d776c56 100644 --- a/include/boost/multiprecision/number.hpp +++ b/include/boost/multiprecision/number.hpp @@ -709,37 +709,19 @@ public: // // Complex number real and imag: // -private: - typename real_and_imag_result >::type - real_imp(const mpl::true_&)const - { - return boost::multiprecision::real(*this); // Individual backend must overload the non-member function "real". - } - typename real_and_imag_result >::type - imag_imp(const mpl::true_&)const - { - return boost::multiprecision::imag(*this); // Individual backend must overload the non-member function "imag". - } - typename real_and_imag_result >::type - real_imp(const mpl::false_&)const - { - return *this; - } - typename real_and_imag_result >::type - imag_imp(const mpl::false_&)const - { - return 0; - } -public: typename real_and_imag_result >::type real()const { - return real_imp(mpl::bool_::value == number_kind_complex>()); + typename real_and_imag_result >::type result; + eval_real(result.backend(), backend()); + return result; } typename real_and_imag_result >::type imag()const { - return imag_imp(mpl::bool_::value == number_kind_complex>()); + typename real_and_imag_result >::type result; + eval_imag(result.backend(), backend()); + return result; } private: template diff --git a/test/test_arithmetic.hpp b/test/test_arithmetic.hpp index fc202bb5..4052c62e 100644 --- a/test/test_arithmetic.hpp +++ b/test/test_arithmetic.hpp @@ -1952,12 +1952,12 @@ typename boost::enable_if_c::value BOOST_CHECK_EQUAL(b, 20); Real c(2, 3); -/* + BOOST_CHECK_EQUAL(a.real(), 30); BOOST_CHECK_EQUAL(a.imag(), 0); BOOST_CHECK_EQUAL(c.real(), 2); BOOST_CHECK_EQUAL(c.imag(), 3); -*/ + BOOST_CHECK_EQUAL(real(a), 30); BOOST_CHECK_EQUAL(imag(a), 0); BOOST_CHECK_EQUAL(real(c), 2);