Применить функцию ко всем элементу матрицы Eigen
У меня есть Eigen::MatrixXd
, и я хотел бы изменить все его элементы, применив компонент-мудрый. Например:
MatrixXd m = ...;
for each m[i][j]:
m[i][j] = exp(m[i][j]);
Есть ли способ достичь этого результата?
Ответы
Ответ 1
Да, используйте функцию Eigen::MatrixBase<>::unaryExpr()
. Пример:
#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;
}
Ответ 2
vsoftco ответ очень общий и хорош для пользовательских функций. Однако для многих из часто используемых функций существует более простой способ. Адаптируя его пример, мы можем использовать array
, и он выглядит так:
#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;
}
Ответ 3
Ответ @vsoftco помог мне решить эту проблему на 99%, но по какой-то причине передача &Exp
в .unaryExpr()
приводила к ошибкам компиляции (g++, c + 11, Eigen 3.3.5 дал ошибку, относящуюся к: base type ‘double (*)(double) fails to be a struct or class type
).
Однако я обнаружил, что создание объекта std::function
и передача, вместо этого, исправили это. Копирование примера @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 answer
std::cout << m << std::endl << "becomes: ";
std::cout << std::endl << m.unaryExpr(exp_wrap) << std::endl; //and used here
}
Я не уверен, сколько издержек дает использование объекта std::function
(или std::ptr_fun
) по сравнению с передачей &Exp
, но я не мог заставить его работать без этих альтернатив.
ура
Ответ 4
FWIW, в С++ 11 и выше, это также работает с лямбда-функциями.
#include <cmath>
#include <iostream>
#include <Eigen/Core>
int main()
{
Eigen::MatrixXd m(2, 2);
m << 0, 1, 2, 3;
std::cout << m << std::endl << " -> "
std::cout << m.unaryExpr([](double x){return x + 1}) << std::endl;
}