2014-02-12 9 views
4

Согласно https://stackoverflow.com/a/17932632/1700939, должно быть возможно использовать комплексные числа с boost :: multiprecision с gcc-4.7. Это действительно прекрасно работает с усилением :: multiprecision :: float128:Как использовать комплексные числа с boost :: multiprecision :: mpfr?

-----------test.cpp------------ 
#include <cmath> 
#include <boost/multiprecision/float128.hpp> 

using namespace std; 

typedef boost::multiprecision::float128 real_type_b; 
typedef complex<real_type_b> numeric_type_b; 


int main() 
{ 

    numeric_type_b a(2,2); 
    numeric_type_b r = numeric_type_b(2,2)*a; 
    a = sin(r); 
    a = exp(r); 
    cout << a << endl; 

} 
-----------test.cpp------------ 

$ g++-4.7 -std=c++0x test.cpp -lquadmath -o test 
$ ./test 
(-0.1455,0.989358) 

Попытка же самое с буст :: multiprecision :: MPFR терпит неудачу за exp -функции (sin отлично работает (!))

-----------test.cpp------------ 
#include <cmath> 
#include <boost/multiprecision/mpfr.hpp> 

using namespace std; 

typedef boost::multiprecision::mpfr_float_500 real_type_b; 
typedef complex<real_type_b> numeric_type_b; 


int main() 
{ 

    numeric_type_b a(2,2); 
    numeric_type_b r = numeric_type_b(2,2)*a; 
    a = sin(r); 
    a = exp(r); 
    cout << a << endl; 

} 
-----------test.cpp------------ 

компиляция завершится неудачно:

$ g++-4.7 -std=c++0x test.cpp -lmpfr -o test 
In file included from /usr/include/boost/config/no_tr1/complex.hpp:21:0, 
       from /usr/include/boost/math/policies/error_handling.hpp:15, 
       from /usr/include/boost/multiprecision/detail/default_ops.hpp:9, 
       from /usr/include/boost/multiprecision/detail/generic_interconvert.hpp:9, 
       from /usr/include/boost/multiprecision/number.hpp:22, 
       from /usr/include/boost/multiprecision/mpfr.hpp:9, 
       from test.cpp:3: 
/usr/include/c++/4.7/complex: In instantiation of ‘std::complex<_Tp> std::__complex_exp(const std::complex<_Tp>&) [with _Tp = boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<500u> >]’: 
/usr/include/c++/4.7/complex:751:68: required from ‘std::complex<_Tp> std::exp(const std::complex<_Tp>&) [with _Tp = boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<500u> >]’ 
test.cpp:17:18: required from here 
/usr/include/c++/4.7/complex:736:52: error: no matching function for call to ‘polar(boost::enable_if_c<true, boost::multiprecision::detail::expression<boost::multiprecision::detail::function, boost::multiprecision::detail::exp_funct<boost::multiprecision::backends::mpfr_float_backend<500u> >, boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<500u> >, void, void> >::type, boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<500u> >)’ 
/usr/include/c++/4.7/complex:736:52: note: candidate is: 
/usr/include/c++/4.7/complex:662:5: note: template<class _Tp> std::complex<_Tp> std::polar(const _Tp&, const _Tp&) 
/usr/include/c++/4.7/complex:662:5: note: template argument deduction/substitution failed: 
/usr/include/c++/4.7/complex:736:52: note: deduced conflicting types for parameter ‘const _Tp’ (‘boost::multiprecision::detail::expression<boost::multiprecision::detail::function, boost::multiprecision::detail::exp_funct<boost::multiprecision::backends::mpfr_float_backend<500u> >, boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<500u> >, void, void>’ and ‘boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<500u> >’) 

однако, если exp -линии закомментирована, это работает:

$ g++-4.7 -std=c++0x test.cpp -lmpfr -o test 
$ ./test 
(0,1490.48) 

Я что-то не так, или я столкнулся с ошибкой здесь?

+0

Кажется, стоит отчетности, чтобы повысить. –

+0

Собственно, тоже libstdC++ IYAM. Проводка ответа – sehe

+0

+1 для отличного материала вопроса. На моем g ++ (4.8) мне пришлось перейти на std = C++ 03, потому что библиотека не нашла бы используемые пользователем литералы. – sehe

ответ

1

Похоже на ошибку в библиотеке GNU. Он срабатывает, когда есть _GLIBCXX_USE_C99_COMPLEX здесь:

#if _GLIBCXX_USE_C99_COMPLEX 
    // implementations 

    template<typename _Tp> 
    inline complex<_Tp> 
    exp(const complex<_Tp>& __z) { return __complex_exp(__z.__rep()); } 
#else 
    template<typename _Tp> 
    inline complex<_Tp> 
    exp(const complex<_Tp>& __z) { return __complex_exp(__z); } 
#endif 

Похоже, он ломает ADL на вызов ехр (путем пересылки со значением __rep()).

Вы можете легко выяснить для себя, жесткого кодирования exp реализации:

template<typename T> 
    inline std::complex<T> 
    my_exp(const std::complex<T>& x) 
    { 
     using std::exp; // use ADL 
     return std::polar(exp(x.real()), x.imag()); 
    } 

Это работает

#include <cmath> 
#include <boost/multiprecision/float128.hpp> 
#include <boost/multiprecision/mpfr.hpp> 

#if 1 
typedef boost::multiprecision::mpfr_float_500 real_type_b; 
typedef std::complex<real_type_b> numeric_type_b; 
#else 
typedef boost::multiprecision::float128 real_type_b; 
typedef std::complex<real_type_b> numeric_type_b; 
#endif 

namespace check 
{ 
    template<typename T> 
    inline std::complex<T> 
    my_exp(const std::complex<T>& x) 
    { 
     using std::exp; // use ADL 
     T const& r = exp(x.real()); 
     return std::polar(r, x.imag()); 
    } 
} 

#include <iostream> 

int main() 
{ 
    numeric_type_b a(2,2); 
    numeric_type_b r = numeric_type_b(2,2)*a; 
    a = std::sin(r); 
    a = check::my_exp(r); 
    std::cout << a << std::endl; 
} 

Работы для обоих типов.

Выход

(-0.1455,0.989358) 
+0

Спасибо за понимание. Может быть, это должно пойти на какой-то bugtracker, чтобы его можно было исправить? Я думаю, что не знаю достаточно подробностей (пока), чтобы сделать это, но может быть, пока я не смогу прийти, чтобы копать глубже ... – Sunday

+0

Если честно, я думаю, что ваша работа - сообщить об этом. Я не думаю, что знаю больше, чем ты, я просто предоставил тебе кое-что. Кроме того, это никогда не было моей проблемой в первую очередь :) – sehe

+0

(Уточнение: _ Люди не уверены. Дело в том, что я такой же неуверенный, но у меня нет вашей проблемы! Итак, если вы хотите проявить хоть какую-то возможность , убедитесь, что заинтересованная сторона следит за ними. Если заинтересованные стороны этого не делают, никто не будет_) – sehe