我試圖使用Eigen
對boost::multiprecision
的mutliprecision浮點類型進行特徵向量分解。我從一個非常簡單的例子開始,我從不同的來源複製過來。下面的代碼:模板分辨率失敗,並提升多精度+特徵
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <eigen3/Eigen/Dense>
#include <eigen3/Eigen/LU>
#include <eigen3/Eigen/Eigenvalues>
#include <iostream>
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<100> > SuperFloat;
typedef std::complex<SuperFloat> SuperComplex;
// this is the first fix I came up with to overcome the problem
// that multiprecision doesn't come with an int() operator
namespace Eigen {
namespace internal {
template<typename NewType>
struct cast_impl<SuperFloat,NewType> {
static inline NewType run(const SuperFloat& x) {
return x.convert_to<NewType>();
}
};
}
}
typedef Eigen::Matrix<SuperFloat, Eigen::Dynamic, Eigen::Dynamic> EigenMatrixR;
typedef Eigen::Matrix<SuperFloat, Eigen::Dynamic, 1 > EigenVectorR;
typedef Eigen::Matrix<SuperComplex, Eigen::Dynamic, Eigen::Dynamic> EigenMatrixC;
typedef Eigen::Matrix<SuperComplex, Eigen::Dynamic, 1 > EigenVectorC;
int main(){
int size = 10;
EigenMatrixR A = EigenMatrixR::Identity(size, size);
Eigen::EigenSolver<EigenMatrixR> es(A);
std::cout << "The eigenvalues of A are:" << std::endl << es.eigenvalues() << std::endl;
std::cout << "The matrix of eigenvectors, V, is:" << std::endl << es.eigenvectors() << std::endl << std::endl;
SuperComplex lambda = es.eigenvalues()[0];
std::cout << "Consider the first eigenvalue, lambda = " << lambda << std::endl;
EigenVectorC v = es.eigenvectors().col(0);
std::cout << "If v is the corresponding eigenvector, then lambda * v = " << std::endl << lambda * v << std::endl;
std::cout << "... and A * v = " << std::endl << A.cast<SuperComplex>() * v << std::endl << std::endl;
EigenMatrixC D = es.eigenvalues().asDiagonal();
EigenMatrixC V = es.eigenvectors();
std::cout << "Finally, V * D * V^(-1) = " << std::endl << V * D * V.inverse() << std::endl;
return 0;
}
我已經克服了最初的幾個陷阱(如缺少int()
運營商爲boost::multiprecision
類型,使用convert_to
方法來代替),但現在我已經達到的地步只是編譯吐出有關失敗模板分辨率的錯誤消息。
完整的錯誤日誌很長(我把它放在引擎收錄:http://pastebin.com/a2R0NDSA),但第一個錯誤是:
/usr/include/eigen3/Eigen/src/Eigenvalues/EigenSolver.h:549:43: error: no matching function for call to ‘cdiv(boost::multiprecision::detail::expression<boost::multiprecision::detail::negate, boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<100u> >, void, void, void>, boost::multiprecision::detail::expression<boost::multiprecision::detail::negate, boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<100u> >, void, void, void>, Eigen::EigenSolver<Eigen::Matrix<boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<100u> >, -1, -1> >::Scalar&, Eigen::EigenSolver<Eigen::Matrix<boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<100u> >, -1, -1> >::Scalar&)’
std::complex<Scalar> cc = cdiv(-ra,-sa,w,q);
^
/usr/include/eigen3/Eigen/src/Eigenvalues/EigenSolver.h:422:22: note: candidate: template<class Scalar> std::complex<_Tp> Eigen::cdiv(const Scalar&, const Scalar&, const Scalar&, const Scalar&)
std::complex<Scalar> cdiv(const Scalar& xr, const Scalar& xi, const Scalar& yr, const Scalar& yi)
換句話說,Eigen
試圖使用功能需要四個標量,但boost
爲前兩個提供了表達式模板(並且編譯器拒絕隱式地將它們轉換爲標量)。
我在正確的道路上,還是這種努力徒勞?有關如何繼續教授Eigen
如何利用boost::multiprecision
類型的任何建議?
更新
由於下面這個問題的有益的意見,我已經能夠通過關閉表達式模板來解決問題。
typedef boost::multiprecision::cpp_dec_float<50> mp_backend;
typedef boost::multiprecision::number<mp_backend, boost::multiprecision::et_off> SuperFloat;
有關故障模板分辨率check_in_range
其餘的錯誤信息可以固定這樣的:
namespace boost{
namespace multiprecision {
namespace default_ops{
template <> inline bool check_in_range<SuperComplex,long double>(const long double& t){
return false;
}
}
}
}
您可以嘗試其他多精度數據類型,例如'boost :: multiprecision :: mpf_float <>'或'boost :: multiprecision :: mpfr_float <>'(如果您對所產生的依賴性和加速感到滿意)。 – Walter
我對此並不滿意,但如果能夠發揮作用的話,它會有用。然而,爲'boost :: multiprecision :: mpf_float_100'切換'boost :: multiprecision :: number>會導致相同的錯誤。我忘記了什麼嗎? –
carsten
我已經能夠解決這個問題了,謝謝。隨意將關於表達式模板的評論編譯成答案,然後我會接受。 – carsten