Ich schreibe eine kleine lineare Algebra-Dienstprogramm-Bibliothek über Eigen für meine persönliche Code-Basis. Um es so flexibel wie möglich zu gestalten, habe ich verschiedene Eigen-Matrixtypen zur Verwendung als Parameter angegeben. Ein Problem, auf das ich immer wieder zurückgreife, ist, dass ich keine Matrix fester Größe (dh zur Kompilierungszeit gesetzt) als Argument an eine Funktion übergeben kann, die eine dynamisch große Größe hat (zur Laufzeit gesetzt). matrix typedef als Parameter. Ich könnte die Umkehrung verstehen - nicht in der Lage zu sein, eine Matrix dynamischer Größe aufgrund von Compile-Time-Prüfungen als fixiert zu übergeben, aber es scheint, dass dies funktionieren sollte.Übergeben von festen Eigen-Matrizen als Argumente zum Aufrufen von Matrizen mit dynamischer Größe
Ein testbares Beispiel ist die pdist2
-Funktion unten (die wirklich eine native Implementierung in der Eigen-API haben sollte).
#include <Eigen/Core>
namespace Eigen
{
template <typename T>
using MatrixXT = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>;
}
// X is M x N
// Y is M x K
// Output is N x K
template <typename T>
inline Eigen::MatrixXT<T> pdist2(const Eigen::MatrixXT<T> &X, const Eigen::MatrixXT<T> &Y)
{
// ASSERT(X.rows() == Y.rows(), "Input observations must have same number of rows (" +
// std::to_string(X.rows()) + "!=" + std::to_string(Y.rows()) + ")");
Eigen::MatrixXT<T> dists = X.colwise().squaredNorm().transpose() * Eigen::MatrixXT<T>::Ones(1, Y.cols()) +
Eigen::MatrixXT<T>::Ones(X.cols(), 1) * Y.colwise().squaredNorm() -
2 * X.transpose() * Y;
return dists;
}
Dieser Code nicht kompiliert:
Eigen::Matrix<double, 3, 5> X;
X << 8.147236863931790, 9.133758561390193, 2.784982188670484, 9.648885351992766, 9.571669482429456,
9.057919370756192, 6.323592462254095, 5.468815192049838, 1.576130816775483, 4.853756487228412,
1.269868162935061, 0.975404049994095, 9.575068354342976, 9.705927817606156, 8.002804688888002;
Eigen::Matrix<double, 3, 4> Y;
Y << 1.418863386272153, 7.922073295595544, 0.357116785741896, 6.787351548577734,
4.217612826262750, 9.594924263929030, 8.491293058687772, 7.577401305783335,
9.157355251890671, 6.557406991565868, 9.339932477575505, 7.431324681249162;
Eigen::Matrix<double, 5, 4> D = pdist2(X, Y);
Die obige Funktion korrekt Einheit geprüft und bewertet wurde, aber es wird nur funktionieren, wenn X
und Y
Eigen::MatrixXd
Typen sind. Es scheint, dass es meine Vorlage typedef sein muss, die das Problem verursacht, aber es ist nur eine dynamisch (d. H. Zur Laufzeit) große Matrix mit einem Templat-Typ.
Der Fehler lautet:
error: no matching function for call to ‘pdist2(Eigen::Matrix<double, 3, 5>&, Eigen::Matrix<double, 3, 4>&)’
Eigen::Matrix<double, 5, 4> D = Util::Math::pdist2(X, Y);
^
note: candidate: template<class T> Eigen::MatrixXT<T> Util::Math::pdist2(Eigen::MatrixXT<T>&, Eigen::MatrixXT<T>&)
inline Eigen::MatrixXT<T> pdist2(const Eigen::MatrixXT<T> &X, const Eigen::MatrixXT<T> &Y)
^
note: template argument deduction/substitution failed:
note: template argument ‘3’ does not match ‘#‘integer_cst’ not supported by dump_decl#<declaration error>’
Eigen::Matrix<double, 5, 4> D_est = Util::Math::pdist2(X, Y);
^
note: ‘Eigen::Matrix<double, 3, 5>’ is not derived from ‘Eigen::MatrixXT<T>’
Warum ist das nicht? Oder vielleicht genauer gesagt Wie verwende ich eine Vorlage typedef um sicherzustellen, dass meine feste Größe Matrizen tun von Eigen::MatrixXT<T>
abgeleitet werden?
Hinweis: Dies ist alles mit Eigen 3.3.3.
Das ist nicht möglich. 'Matrix' und 'MatrixXt ' sind unterschiedliche Typen. Das bedeutet, dass Sie einen Verweis auf MatrixXt 'nicht an eine Instanz von' Matrix 'binden können. Verwenden Sie pass-by-value oder werfen Sie einen Blick auf 'Eigen :: Ref'. –
@HenriMenke Ich glaube nicht, dass das das Problem ist, es gibt Konvertierungen (selbst wenn die Dims falsch sind, würde man einen Assert-Fehler bekommen). Das Problem besteht darin, den Schablonentyp "T" abzuleiten und immer noch herauszufinden, warum. – vsoftco