J'écris une petite bibliothèque d'utilitaires d'algèbre linéaire sur Eigen pour mon code-base personnel. Pour essayer de le rendre aussi flexible que possible, j'ai typedefed différents types de matrice Eigen à utiliser comme paramètres. Cependant, un problème que je continue de rencontrer est que lorsque je l'utilise, je ne peux pas passer une matrice de taille fixe (c'est-à-dire à la compilation) comme argument à une fonction qui a une taille dynamique (définie à l'exécution) matrice typedef en tant que paramètre. Je pourrais comprendre l'inverse - ne pas être en mesure de passer une matrice de taille dynamique comme fixe en raison de vérifications à la compilation, mais il semble que cela devrait fonctionner.Passage de matrices Eigen de taille fixe en tant qu'arguments de fonction appelant des matrices de taille dynamique
Un exemple testable est la fonction pdist2
ci-dessous (qui devrait avoir une implémentation native dans l'API Eigen).
#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;
}
Ce code ne compile pas:
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);
La fonction ci-dessus a été testé et unité correctement évalue, mais il ne fonctionnera que si X
et Y
sont Eigen::MatrixXd
types. Il semble que ce soit mon template typedef qui cause le problème, mais c'est juste une matrice de taille dynamique (c'est-à-dire à l'exécution) avec un type de template.
L'erreur se lit comme suit:
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>’
Pourquoi ce ne fonctionne pas? Ou peut-être plus précisément, comment puis-je utiliser un typedef de modèle pour m'assurer que mes matrices de taille fixe dérivent de Eigen::MatrixXT<T>
?
Remarque: Tout cela utilise Eigen 3.3.3.
Ce n'est pas possible. 'Matrix' et MatrixXt 'sont des types différents. Cela signifie que vous ne pouvez pas lier une référence à 'MatrixXt ' à une instance de 'Matrix '. Utilisez pass by value ou jetez un oeil à 'Eigen :: Ref'. –
@HenriMenke Je ne pense pas que ce soit le problème, il y a des conversions en cours (même si les dims sont incorrects, vous obtiendrez une erreur d'affirmation). Le problème est de déduire le type de template 'T', essayant toujours de comprendre pourquoi. – vsoftco