web-dev-qa-db-fra.com

Appliquer la fonction à tous les éléments de la matrice Eigen

J'ai un Eigen::MatrixXd et je voudrais modifier tous ses éléments en appliquant une fonction par composant. Par exemple:

MatrixXd m = ...;

for each m[i][j]:
  m[i][j] = exp(m[i][j]);

Y a-t-il un moyen d'obtenir ce résultat?

16
Nick

Oui, utilisez la fonction Eigen::MatrixBase<>::unaryExpr() member. Exemple:

#include <cmath>
#include <iostream>

#include <Eigen/Core>

double Exp(double x) // the functor we want to apply
{
    return std::exp(x);
}

int main()
{
    Eigen::MatrixXd m(2, 2);
    m << 0, 1, 2, 3;
    std::cout << m << std::endl << "becomes: ";
    std::cout << std::endl << m.unaryExpr(&Exp) << std::endl;
}
22
vsoftco

La réponse de vsoftco est très générale et convient aux fonctions personnalisées. Cependant, il existe un moyen plus simple pour de nombreuses fonctions couramment utilisées. En adaptant son exemple, nous pouvons utiliser arrays et cela ressemble à ceci:

#include <iostream>
#include <Eigen/Core>

int main()
{
    Eigen::MatrixXd m(2, 2);
    m << 0, 1, 2, 3;
    std::cout << m << "\nbecomes:\n";
    std::cout << m.array().exp() << std::endl;
    return 0;
}
21
Avi Ginsburg

La réponse de @ vsoftco m'a permis d'obtenir 99% du chemin nécessaire pour résoudre ce problème, mais pour une raison quelconque, passer de &Exp à .unaryExpr() me donnait des erreurs de compilation (g ++, c + 11, Eigen 3.3.5 donnait une erreur liée à: base type ‘double (*)(double)’ fails to be a struct or class type).

Cependant, j’ai trouvé que la création d’un objet std::function et son transfert corrigeaient ce problème. Copier l'exemple de @ vsoftco:

#include <cmath>
#include <iostream>

#include <Eigen/Core>

double Exp(double x) 
{
    return std::exp(x);
}

int main()
{
    Eigen::MatrixXd m(2, 2);
    m << 0, 1, 2, 3;
    std::function<double(double)> exp_wrap = Exp; //added to @vsoftco's answer
    std::cout << m << std::endl << "becomes: ";
    std::cout << std::endl << m.unaryExpr(exp_wrap) << std::endl; //and used here
}

Je ne sais pas combien de temps d'utilisation un objet std::function (ou std::ptr_fun) donne par rapport au passage de &Exp, mais je ne pouvais pas le faire fonctionner sans ces alternatives.

À votre santé

0
KamKam