MEX-file implementing Eigen library pseudo-inverse function crashes - c++

I am trying to implement an Eigen library pseudo-inverse function in a Matlab MEX-file. It compiles successfully but crashes when I run it.
I am trying to follow the FAQ on how to implement a pseudo-inverse function using the Eigen library.
The FAQ suggests adding it as a method to the JacobiSVD class but since you can't do that in C++ I'm adding it to a child class. It compiles successfully but then crashes without an error message. It successfully outputs "hi" without crashing if I comment out the line with the .pinv call so that's where the problem is arising. To run, I just compile it (as test.cpp) and then type test at the command line. I am using Matlab R2019a under MacOS 10.14.5 and Eigen 3.3.7. In my full code I also get lots of weird error messages regarding the pinv code but before I can troubleshoot I need this simple test case to work. This is all at the far limits of my understanding of C++. Any help appreciated.
#include "mex.h"
#include <Eigen/Dense>
#include <Eigen/SVD>
#include <cstdlib>
#include <cmath>
#include <iostream>
using namespace Eigen;
using namespace std;
//https://stackoverflow.com/questions/18804402/add-a-method-to-existing-c-class-in-other-file
class JacobiSVDext : public JacobiSVD<MatrixXf> {
typedef SVDBase<JacobiSVD<MatrixXf>> Base;
public:
using JacobiSVD::JacobiSVD; //inherit constructors //https://stackoverflow.com/questions/347358/inheriting-constructors
MatrixXf pinv() //http://eigen.tuxfamily.org/index.php?title=FAQ
{
eigen_assert(m_isInitialized && "SVD is not initialized.");
double pinvtoler=1.e-6; // choose your tolerance wisely!
JacobiSVDext::SingularValuesType singularValues_inv=m_singularValues;
for ( long i=0; i<m_workMatrix.cols(); ++i) {
if ( m_singularValues(i) > pinvtoler )
singularValues_inv(i)=1.0/m_singularValues(i);
else singularValues_inv(i)=0;
}
return m_matrixV*singularValues_inv.asDiagonal()*m_matrixU.transpose();
};
};
/* The gateway function */
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
MatrixXf X = MatrixXf::Random(5, 5);
JacobiSVDext svd(X);
MatrixXf Y=svd.pinv();
cout << Y << endl;
cout << "hi" << endl;
}
The expected result is to output the pseudo-inverse of the random matrix and also "hi". Instead it crashes without an error message.

When constructing the Eigen::JacobiSVD object, you fail to request that matrices U and V should be computed. By default, these are not computed. Obviously, accessing these matrices if they are not computed will cause a segmentation violation.
See the documentation to the constructor. A second input argument must specify either ComputeFullU | ComputeFullV, or ComputeThinU | ComputeThinV. The thin ones are preferable when computing the pseudo-inverse, as the rest of the matrices are not needed.
I would not derive from the JacobiSVD class just to add a method. Instead, I would simply write a free function. This is both easier, and allows you to use only the documented portions of the Eigen API.
I wrote the following MEX-file, which works as intended (using code I already had for this computation). It does the same, but in a slightly different way that avoids writing an explicit loop. Not sure this way of writing it is very clear, but it works.
// 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";
}

Related

Unable to load armadillo Cube<uword> when using RcppArmadillo

I was prepossessing data in C++ using the Armadillo library. The program end product is a ucube, which is a cube filled with unsigned integers. After its run, I want to load the ucube to R to perform some final statistical tests. To do so, I made a C++ function that load the ucube returning an array.
But it does not work!
I got the following warning: "warning: Cube::load(): incorrect header in B.bin" and the program returns a 0x0x0 array.
Trying to find why, I made a toy C++ program, which works fine. It is able to load the cubes without any problem.
#include <iostream>
#include <armadillo>
using namespace arma;
void read_cubes(char const* A, char const* B){
cube C;
ucube D;
C.load(A, arma_binary);
D.load(B, arma_binary);
}
int main(int argc, char** argv){
cube A = randu<cube>(5,5,5);
ucube B = randi<ucube>(5,5,5, distr_param(1, 10));
A.save(argv[1], arma_binary);
B.save(argv[2], arma_binary);
read_cubes(argv[1], argv[2]);
}
But I do not know why, doing the same steps in R does not work. To illustrate, please run the toy program as ./a.out A.bin B.bin. It will yield the Cube<double> A.bin and the Cube<uword> B.bin, which I will mention later.
The problem
If I source the following C++ code with Rcpp::sourceCpp and I try to read the Cube<double> A.bin with read_cube("A.bin") it works, but if I do the same for the Cube<uword> B.bin with read_ucube("B.bin") it does not (I get the warning).
#include <RcppArmadillo.h>
#include <iostream>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::cube read_cube(char const* x){
arma::cube A;
A.load(x, arma::arma_binary);
return A;
}
// [[Rcpp::export]]
arma::ucube read_ucube(char const* x){
arma::ucube B;
B.load(x, arma::arma_binary);
return B;
}
Of course I could cast the Cube<uword> to a Cube<double> before ending the C++ program, but I would like to know why this happen and if it is possible to load a Cube<uword> in RcppArmadillo. Because it should be possible, right?
Unfortunately R still only supports 32 bit integers, so RcppArmadillo forces Armadillo to use 32 bit integers. This is done by defining ARMA_32BIT_WORD before including the armadillo header. See RcppArmadillo's configuration here.
You can apply the same "trick" with your Armadillo programs like so:
#define ARMA_32BIT_WORD
#include <armadillo>
One of the effects is that ucube (Cube<uword>) will use 32 bit unsigned integers.
After doing the above trick, recompile your Armadillo programs and save the ucubes again. They can then be loaded in RcppArmadillo.

Prototype Functions C++

I am having build errors when declaring prototype functions within Xcode. I am writing in C++. The script is pulled from my professor's lecture. Attached below is a picture of the build errors, along with the script itself.
Note: I only run into build issues when trying to declare prototype functions. It is as if Xcode is trying to pull the functions from a Library, and not recognizing it.
Code:
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <cmath>
#include <cctype>
#include <cstdlib>
using namespace std;
int calcSquare (int num) ;
int main ()
{
int num = 5;
int result;
result = calcSquare(num);
cout << "The Square of " << num << " is " << result << endl;
return 0;
}
Errors: https://farm3.staticflickr.com/2871/33406384892_68ee0843c7_b.jpg
The problem with your program is that you forgot to DEFINE the function prototype later in your source code.
Right now, you simply have a function prototype ( int calcSquare ), but you called that function anyways.
That throws you the linker exception as shown.
In other words, define the function somewhere in your source code to use the <cmath>, <cctype>, <cstdlib> modules and libraries.
After the function prototype, declare the function later:
int calcSquare (int num) {
...
}
I hope this helps! :)

Writing an extremely basic mex function in matlab

I am trying to to write a very simple mex file, let's say just to try out the way it works. I have gone through a lot of materials and more I read, more I get confused. I need this to further write a mex file that interacts with external hardware. Please help!
// header file - printing.h //
#include<iostream>
class printing
{
public:
void name();
void age();
};
// cpp file - printing.cpp //
#include<iostream>
#include "mex.h"
#include "matrix.h"
#include "printing.h"
#include <string>
using namespace std;
void mexFunction(int nlhs, mxArray*plhs[],
int nrhs, const mxArray *prhs[])
{
printing p1;
p1.name();
p1.age();
}
void printing::name()
{
cout << "NAME" << endl;
}
void printing::age()
{
cout << "20" << endl;
}
// .m file - test.m //
sprintf ('WELCOME')
printing()
When i run the test.m file, I would like to see
WELCOME
NAME
20
However I see only welcome. I understand that I have not updated the plhs[] array. But all I want to do is execute something inside mexFunction.Why wouldn't the cout inside name() and age() achieve this?
Also, how do i confirm that name() and age() are executed?
The call to cout will not print to the MATLAB console, you need to use the MEX printf function.
mexPrintf("NAME\n");

cygwin_exception::open_stackdumpfile: Dumping stack trace to *.exe.stackdump

I am getting "cygwin_exception::open_stackdumpfile: Dumping stack trace to TestProject.exe.stackdump" error. My project is nothing but a C++ HalloWorld project that contains an additional class in which I set and get a variable. I am getting this error at the line I try to set a matrix variable of type Eigen. Here is my code:
TestProject.cpp
#include <iostream>
#include "TestClass.hpp"
using namespace std;
int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
TestClass testClass;
Eigen::MatrixXd XX = testClass.getVariable();
cout << "X = " << XX;
return 0;
}
TestClass.hpp:
#ifndef TESTCLASS_HPP_
#define TESTCLASS_HPP_
#include <Eigen/Core>
#include <Eigen/Eigenvalues>
#include <unsupported/Eigen/MatrixFunctions>
#include <Eigen/Geometry>
class TestClass {
private:
Eigen::MatrixXd X;
public:
TestClass();
void setVariable(Eigen::MatrixXd);
Eigen::MatrixXd getVariable();
virtual ~TestClass();
};
#endif /* TESTCLASS_HPP_ */
and finally the TestClass.cpp:
#include "TestClass.hpp"
using namespace std;
TestClass::TestClass() {
X << 0, 1, 2;
}
TestClass::~TestClass() {
// TODO Auto-generated destructor stub
}
void TestClass::setVariable(Eigen::MatrixXd x){
X = x;
}
/* namespace std */
Eigen::MatrixXd TestClass::getVariable(){
return X;
}
The output I get in the Console is:
!!!Hello World!!!
0 [main] TestProject 8416 cygwin_exception::open_stackdumpfile: Dumping stack trace to TestProject.exe.stackdump
It is worth mentioning that when I change the type of the class variable X (and all related types in the methods and the header file) into an integer I don't get this error and the code compiles and runs.
I would appreciate any help since I didn't find useful info online.
Thanks
You are using a dynamic sized Matrix X, and you try to comma initialize it without setting its size first. This will raise an exception:
As explained here:
Eigen offers a comma initializer syntax which allows the user to
easily set all the coefficients of a matrix, vector or array. Simply
list the coefficients, starting at the top-left corner and moving from
left to right and from the top to the bottom. The size of the object
needs to be specified beforehand.
and here:
The coefficients must be provided in a row major order and exactly
match the size of the matrix. Otherwise an assertion is raised.
So resize your matrix first:
TestClass::TestClass() {
X.resize (1,3);
X << 0, 1, 2;
}

eigen library selfadjointView problem

I am persistently getting error messages whenever I try to use the selfadjointView property of any matrix or sparse matrix using the eigen library. Below is a simple code to check that. In my program I do try with self-adjoint matrix:
#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
#include <Eigen/Sparse>
#include <Eigen/Dense>
#include <Eigen/Core>
#include <iostream>
using namespace Eigen;
int main ()
{
SparseMatrix<float> mat(3,3);
Matrix<float, 3, 1> vec;
std::cout<<mat.selfadjointView<>()*vec;
}
The error message I get is:
error: no matching function for call to ‚'Eigen::SparseMatrix::selfadjointView()‚
You have to specify the template argument, so it should read mat.selfadjointView<Upper>() or mat.selfadjointView<Lower>() . The first one means that it should use the entries in the upper triangular part of mat and fill the lower triangular part to make the matrix self-adjoint. The second one is the other way around.