При создании объекта Eigen::JacobiSVD
вы не запрашиваете, что матрицы U и V должны быть вычислены.По умолчанию они не вычисляются.Очевидно, что доступ к этим матрицам, если они не вычислены, приведет к нарушению сегментации.
См. документацию для конструктора .Второй входной аргумент должен указывать либо ComputeFullU | ComputeFullV
, либо ComputeThinU | ComputeThinV
.Тонкие из них предпочтительны при вычислении псевдообратных, поскольку остальные матрицы не нужны.
Я бы не наследовал класс JacobiSVD
только для добавления метода.Вместо этого я просто написал бы бесплатную функцию.Это и проще, и позволяет вам использовать только документированные части Eigen API.
Я написал следующий MEX-файл, который работает как задумано (используя код, который я уже имел для этого вычисления).Он делает то же самое, но немного по-другому, избегая написания явного цикла.Не уверен, что этот способ написания очень понятен, но он работает.
// Compile with:
// mex -v test.cpp -I/usr/local/include/eigen3
#include "mex.h"
#include <Eigen/Dense>
#include <Eigen/SVD>
#include <cstdlib>
#include <cmath>
#include <iostream>
Eigen::MatrixXf PseudoInverse(Eigen::MatrixXf matrix) {
Eigen::JacobiSVD< Eigen::MatrixXf > svd( matrix, Eigen::ComputeThinU | Eigen::ComputeThinV );
float tolerance = 1.0e-6f * float(std::max(matrix.rows(), matrix.cols())) * svd.singularValues().array().abs()(0);
return svd.matrixV()
* (svd.singularValues().array().abs() > tolerance).select(svd.singularValues().array().inverse(), 0).matrix().asDiagonal()
* svd.matrixU().adjoint();
}
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
Eigen::MatrixXf X = Eigen::MatrixXf::Random(5, 5);
Eigen::MatrixXf Y = PseudoInverse(X);
std::cout << Y << '\n';
std::cout << "hi\n";
}