I have correlation matrix of a data and i want to use pca to transform them to uncorrelated set.
so i've decided to use matlab engine(c++ mex API) to perform the pca
my question is how to copy the matrix contents to mxArray efficiently i used loops to allocate each element of matrix...on the other hand i've looked up for memcpy and it seems error prone.
although i've tested the following and it just copies the first column!
memcpy((double *)mxGetPr(T), &rho_mat[0][0], rows * sizeof(double));
what is the best way to copy the data (matrix -> mxArray and mxArray -> matrix) ?
void pca(vector<vector<double>>& rho_mat)
{
Engine *ep;
mxArray *T = NULL, *result = NULL;
if (!(ep = engOpen(""))) {
fprintf(stderr, "\nCan't start MATLAB engine\n");
return;
}
size_t rows = rho_mat.size();
size_t cols = rho_mat[0].size();
T = mxCreateDoubleMatrix(rows, cols, mxREAL);
double * buf = (double *)mxGetPr(T);
for (int i = 0; i<rows; i++) {
for (int j = 0; j<cols; j++) {
buf[i*(cols)+j] = rho_mat[i][j];
}
}
engPutVariable(ep, "T", T);
engEvalString(ep, "PC = pcacov(T);");
result = engGetVariable(ep, "PC");
}
Thanks
Regards
You can try using std::memcpy
in a loop for each row.
for (int i = 0; i<rows; i++)
{
std::memcpy(buf + i*cols, &rho_mat[i][0], cols * sizeof(double));
}
Please note you have to use cols in you memcpy to ensure each row is copied. In your example, it might have been coincidental if your matrix was square.
You can refer to this answer on how to copy a 1-d vector using memcpy.
Edit:
To copy from 2-D array to 2-D vector(assuming vector is already of size rows*cols)
for (int i = 0; i<rows; i++)
{
std::memcpy(&rho_mat[i][0], buf + i*cols, cols * sizeof(double));
}
Please note the assumption made
OR
A much cleaner way would be to use std::assign
or constructor to std::vector
if(rho_mat.size() == 0)
{
for (int i = 0; i<rows; i++)
{
rho_mat.push_back(vector<int>(buf + i*cols, buf + i*cols + cols));
//OR
//rho_mat.push_back(vector<int>());
//rho_mat[i].assign(buf + i*cols, buf + i*cols + cols);
}
}