What is wrong in my mex file? input/output definition? - c++

I am trying to run my mex function which I've written in c++ in VS. It compiles successfully in MATLAB but returns the wrong values. I'm pretty much sure, I'm not reading the 16-by-21 input matrix gammas. Can anybody see what is wrong here?
void fun(double gammas[], int num1, int num2, int length, double a[])
{
...
}
void mexFunction(int nlhs, mxArray *plhs, int nrhs, const mxArray *prhs)
{
double *gammas, *a;
int num1, num2, length;
size_t mrows, mcols;
mrows = 4; mcols = 21;
length = 21;
plhs[0] = mxCreateDoubleMatrix((mSize)mrows, (mwSize)ncols, mxREAL);
gammas = mxGetPr(prhs[0]);
num1 = (int)*mxGetPr(prhs[1]);
num2 = (int)*mxGetPr(prhs[2]);
a = mxGetPr(plhs[0]);
fun(gammas, num1, num2, length, a);
}
I get correct "a" when I call "fun" within a "main" instead of "mex" function in VS and manually provide the input gammas. I receive wrong "a" when I call the resulted mex file in my MATLAB code.

As suspected in comments to your question issue is due to how matlab and c/c++ order array elements for linear storage as 1D array in memory. Matlab uses column-major order while C/C++ uses row-major.
I would not advice you to do permutation prior to call mex-function but rather do the permutation inside the mex function. Either as suggested by #chappjc by call to permute with mexCallMatlab or by call to mxCalcSingleSubscript which returns matlab's linear index from coordinates (whatever the number of dimensions).
Side note: Need confirmation and find back great article I read about that, but matlab uses column-major ordering because it's more appropriate for matrix multiplication (creates less page-defaults when accessing memory cache, and is thus faster). Again need confirmation ... but at least this organisation is better suited for access by columns rather than by rows ...
Edit
Btw, some simple code (C#) to obtain coordinates from maltab's zero based linear index (reverse of mxCalcSingleSubscript):
private static int[] getCoordinatesFromMatlabLinearIndex(int index, int[] arrayDims)
{
var ret = new int[count];
var count = arrayDims.Length;
for (var k = 0; k < count; k++)
{
index = Math.DivRem(index, arrayDims[k], out ret[k]);
}
return ret;
}

As an alternative to inputting a transposed matrix to address the row/column-major discrepancy that CitizenInsane pointed out, you can have the transpose handled inside the MEX file. Use a helper C++ function. You can either write a loop to copy elements, or simply call permute via mexCallMATLAB. Something like the following:
int permute2DMATtoC(mxArray*& matPermuted, const mxArray* mat)
{
mxAssert(mxGetNumberOfDimensions(mat)<=3, "Requires 2D or 3D matrix.");
mxArray *permuteRHSArgs[2];
permuteRHSArgs[0] = const_cast<mxArray*>(mat);
permuteRHSArgs[1] = mxCreateDoubleMatrix(1,3,mxREAL);
mxGetPr(permuteRHSArgs[1])[0] = 2;
mxGetPr(permuteRHSArgs[1])[1] = 1;
mxGetPr(permuteRHSArgs[1])[2] = 3; // supports 2D and 3D
return mexCallMATLAB(1, &matPermuted, 2, permuteRHSArgs, "permute");
}
Use:
mxArray *matPermuted;
permute2DMATtoC(matPermuted, prhs[0]); // matPermuted is MATLAB-managed
double *gammas = (double*)mxGetData(matPermuted);
NOTE: Since matPermuted is manage by MATLAB, you don't need to explicitly destroy it to reclaim resources, but when you are done you can do this if you want:
mxDestroyArray(matPermuted);
For RGB, it may be necessary to convert pixel order (RGB-RGB-RGB-...) to planar order (RRRR...-GGGG...-BBBB...).

Related

Creating a 3D array in C++ using passed in parameters

I have a function that takes in a void* buffer parameter. This function (which is provided by HDF here. From my understanding, it reads info from a dataset into the buffer. I have this working, but only if I create a 3d int array using constant values. I need to be able to do this using values passed in by the user.
Here is the start of that function:
void* getDataTest(int countX, int countY)
{
int NX = countX;
int NY = countY;
int NZ = 1;
int data_out[NX][NY][NZ]; //I know this doesn't work, just posting it for reference
//.
//. more code here...
//.
// Read function is eventually called...
h5Dataset.read(data_out, H5::PredType::NATIVE_INT, memspace, h5Dataspace);
}
This constantly fails on me. However, my previoud implementation that used const int values when creating the data_out array worked fine:
void* getDataTest(int countX, int countY)
{
const int NX = 5;
const int NY = 5;
const int NZ = 1;
int data_out[NX][NY][NZ];
//.
//. more code here...
//.
// Read function is eventually called...
h5Dataset.read(data_out, H5::PredType::NATIVE_INT, memspace, h5Dataspace);
}
This works fine. From my understanding, this function (which I have no control over) requires dataspaces of the same dimensionality (e.g. a 3D array will only work with a 3D array while a 2D array will only work with a 2D array when copying over the data to the buffer).
So, my key problem here is that I can't seem to figure out how to create a 3D int array that the read function is happy with (the function parameter is a void* but I can't seem to get anything other than a 3d int array to work). I've tried a 3D int array represented as an array of arrays of arrays using:
int*** data_out = new int**[NX];
but this failed as well. Any ideas on how I can create a 3D int array of the form int arrayName[non-constant value][non-constant value][non-constant value]? I know you can't create an array using non-constant values, but I added them in an attempt to clarify my goal. Should there be a way in C++ to use function parameters as values for instantiating an array?
I think the easiest is to do this:
int* data_out = new int[NX * NY * NZ];
You can then access this 1D array as a 3D array like that:
int value = array[z * NX * NY + y * NX + x];
In a more C++11 style, you can use an std::vector:
std::vector<int> data_out;
data_out.resize(NX * NY * NZ);
And calling the function like that:
h5Dataset.read(data_out.begin(), H5::PredType::NATIVE_INT, memspace, h5Dataspace);
Do it like this:
std::vector<int> array;
array.resize(Nx*Ny*Nz);
array[z*Ny*Nx + y*Nx + x] = value
It's nice to have the array[z][y][x] syntax, but supporting it is more trouble than it is worth.

run time error when using a mex file, maybe due to memory allocation

I've written a mex function named mx_minimum_power that I'm calling it in MATLAB as follows:
[Fs,Fd,pow_remained] = mx_minimum_power(A11,A12_real,A12_imag,A13_real,A13_imag,A22,A23_real,A23_imag,A33,MatSize);
A11, A12_real, A13_real, A22, A23_real, A33 are 30555x1 single
matrices
A12_imag, A13_imag, A23_imag are 1x1 single variables
MatSize is a 1x1 double variable with the value 30555, that is the
size of matrices
In an iteration, each time the hermitian matrix A is constructed
and eigenvalues and eigenvectors of it should be found. So I've written the following gateway function with the help of CVM Class Library.
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *arraysizePtr = NULL;
arraysizePtr = mxGetPr(prhs[9]);
const int arraysize = (int)*arraysizePtr;
const int matrixDimention = 3;
float *inMatrixA11 = (float *)mxGetPr(prhs[0]);
float *inMatrixA12_real = (float *)mxGetPr(prhs[1]);
float *inMatrixA12_imag = (float *)mxGetPr(prhs[2]);
float *inMatrixA13_real = (float *)mxGetPr(prhs[3]);
float *inMatrixA13_imag = (float *)mxGetPr(prhs[4]);
float *inMatrixA22 = (float *)mxGetPr(prhs[5]);
float *inMatrixA23_real = (float *)mxGetPr(prhs[6]);
float *inMatrixA23_imag = (float *)mxGetPr(prhs[7]);
float *inMatrixA33 = (float *)mxGetPr(prhs[8]);
basic_schmatrix< float, complex<float> > A(matrixDimention);
basic_scmatrix< float, complex<float> > EigenVectors(matrixDimention);
basic_rvector<float>EigenValues(matrixDimention);
int i = 0;
for (i = 0; i < arraysize; i++)
{
A.set(2, 2, inMatrixA11[i]);
A.set(2, 3, complex<float>(inMatrixA12_real[i], inMatrixA12_imag[0]));
A.set(2, 4, complex<float>(inMatrixA13_real[i], inMatrixA13_imag[0]));
A.set(3, 3, inMatrixA22[i]);
A.set(3, 4, complex<float>(inMatrixA23_real[i], inMatrixA23_imag[0]));
A.set(4, 4, inMatrixA33[i]);
try{ EigenValues = A.eig(EigenVectors);}
catch (cvmexception& ex) {
cout << ex.what() << endl;
}
}
}
until line 28 that is try{ EigenValues = A.eig(EigenVectors);}, here I get the run-time error:
and the control jumps to line 311 of the file cvm.h, that is line 11 of the following code:
CVM_NAMESPACE_BEG
//! %Array deleter helper class
template<typename T>
class ArrayDeleter {
public:
void operator () (T* d) const {
if (d != nullptr) {
::delete[] d;
}
}
};
seems that something causes the array get deleted before returning the control to the gateway function but I don't know what? Because if I stop debugging and return to MATLAB, I will get:
and if I press attempt to continue, I'll get:
so there's no way to see which exception is thrown through the try, catch and cout code.
Hint:
basic_schmatrix is a class in CVM library that is encapsulating hermitian matrices of complex numbers. See here, here and here
basic_scmatrix is a class in CVM library that encapsulates square matrices of complex numbers. See here, here and here, I've used it to allocate memory for Eigenvectors, because they'll be returned in the form of a the square matrix
in which the columns are orthonormal eigenvectors.
basic_rvector is a class in CVM library for encapsulating vector of real numbers. It has been used to allocate memory for eigenvalues because as we know the eigenvalues of a hermitian matrix is real and they'll be returned in the form of the vector
I've used indices 2-4 instead of 1-3 because as I've explained here CVM0=1
Finaly eig is a member function of the class basic_schmatrix that gets the address to the allocated memory for eigenvectors and returns an object of type rvector, please see here
EDIT :
from my inspections it's not an error. The control should normally reach line 311 of the file CVM.h, because it is using dynamic memory allocation and it's going to release resources when returning to the gateway function here's a list of where the control goes when you press F11s and it's not throwing an exception at all. But what's wrong with my gateway function code that causes matlab encounter such a breakpoint?

matlab-mex-c++: in a for loop, It's slow to assign a non-constant value to an array

I tried to use matlab mex (c++) to optimize my matlab program. The problem is that assigning a value (not constant) to an array is very slow. I cannot find the answer myself.
Background:
The c++ source code is following:
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{ ...
int row_num = 6000, col_num=4000;
int total_sim_num=row_num*row_num, total_rate_num=row_num*col_num;
plhs[0] = mxCreateNumericMatrix(row_num, row_num, mxSINGLE_CLASS, mxREAL);
//plhs[0] is the pointer of output matrix, and, indeed, it's an 1-D vector.
//Matlab code can use it as 2-D matrix.
float* out_mat = (float*)mxGetData(plhs[0]);
//later, I want to write the calculated value to matrix: out_mat
This is a 3-layer loop, and the output matrix is large: A_OUT=row_num *row_num
The result depends on some input matrics: A_IN=row_num*col_num.
for(int u=0; u<row_num; u++)
{
for(int v=u, vx=0; v<total_sim_num; v+=row_num, vx++)
{
for (int i=u, ix=vx; i<total_rate_num; i+=row_num, ix+=row_num)
{
float calculated_value = ix/row_num; //it's fast.
out_mat[v] = calculated_value; //It's very slow (~ 10 minutes)
//out_mat[v] -> A_OUT[u][v]
out_mat[v] = 2; //assign constant, it's fast (< 2 seconds)
}
}
}
As mentioned in the comments:
Assign a constant to the out_mat is fast.
Assign a calculated value to a local variable is fast.
Assign a calculated value to out_mat is very slow.
I also tried this:
float* testv = new float[total_sim_num];
then:
testv[v] = calculated_value; //It's very slow too.
Can someone share the light that why it's so slow when assigning calculated value to out_mat?
Is it possible to be as fast as assigning a constant to out_mat?
Thanks very much!
Jun
When writing to out_mat, you overwrite the same array element (out_mat[v], where v is the control variable of the second level for-loop) with multiple values different values (sequentially calculated in the third level loop).
So, maybe, when you only assign constants to the array, the compiler optimizes the assignment to the second level loop, and maybe also optimizes away the third level completely.
Are you sure that the code you pasted here is right?
MATLAB matrices are stored in column-order. The mxArray you are creating is row_num x row_num where as it probably should be row_num x col_num.
You should then index the out_mat array using i + (j-1)*row_num to access the ith row and jth column.

mapping c++ array to Eigen Matrix

What I am currently trying to do is get the data from my variable input, convert it into and Eigen matrix, do some computation and then map the result back to an c++ array.
void RBM::reconstruct(double *input, double *w)
{
double *data = input;
mexPrintf("\n");
for (int j = 0; j < 6; j++){
mexPrintf("%f", data[j]);
}
mexPrintf("\n");
Map<MatrixXd> XX(data,6,6);
MatrixXd resultEigen;
double *result;
Map<MatrixXd>( result, 6, 6 ) = XX;
resultEigen = XX.transpose();
Map<MatrixXd>( result, resultEigen.rows(), resultEigen.cols() ) = resultEigen;
}
The above code compiles but i get (run Time error) probably link to an access violation and i can't really figure out where the problem is. Thanks for any hint.
You misunderstand what a Eigen::Map is. The map wraps an existing memory block and allows you to use Eigens functionality on that block. With a Eigen::Map Eigen does handle any of the memory allocations. This allow you to manipulate the data in objects from other libraries without copying back and forth. As mentioned in the comments, if you allocate the result array as double result[36]; the program should run fine.
#include <Eigen/Dense>
#include <kdl/jntarray.hpp>
Eigen::MatrixXd mat_1, mat_2;
KDL::JntArray arr;
mat_1 = arr.data.matrix() - mat_2 ;
Here, array is converted to matrix

memcpy function calling inside mex

I have an interesting problem. Namely like that; I am trying to use std::memcpy function inside by mex function and calling that mex function inside MATLAB like that;
I2 = b_filter(I);
When I copy the whole image, it works well;
plhs[0] = mxCreateDoubleMatrix(mxGetM(plhs[0]), mxGetN(plhs[0]), mxREAL);
memcpy(mxGetPr(plhs[0]), mxGetPr(prhs[0]), sizeof(double) *mxGetM(plhs[0]) * mxGetN(plhs[0]));
But when I try to copy some part of image
plhs[0] = mxCreateDoubleMatrix(100, 100, mxREAL);
memcpy(mxGetPr(plhs[0]), mxGetPr(prhs[0]), sizeof(double) * 100 * 100);
it doesn't give right image part but gives unmeaningful pixel values.
So what is going on here?
Ha Ha! You've been caught by one of the nastiest of mex file nuances! It's got me before too. Arrays in mex functions are stored in column order not row order, so you:
You still use column-first indexing like in Matlab, though
Blog URL
Try this page too for a nice picture of the ordering.
Finally I would recommend reading this thread to get a better idea behind the difference of C and MATLAB matrix memory being column-ordered.
As explained by #macduff, MATLAB uses a column-major order to store arrays, while C arrays are row-major.
Here is a sample implementation showing how to copy part of a matrix.
matrix_slice_mex.c
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *in, *out;
mwIndex i,j;
mwSize numRows;
/* input checks */
if (nrhs != 1 || nlhs > 1) {
mexErrMsgIdAndTxt("MATLAB:nargchk", "Wrong number of arguments.");
}
if (mxGetNumberOfDimensions(prhs[0])>2 || !mxIsDouble(prhs[0])) {
mexErrMsgIdAndTxt("MATLAB:wrongDims", "Expecting 2D double matrix.");
}
if (mxGetM(prhs[0])<100 || mxGetN(prhs[0])<100) {
mexErrMsgIdAndTxt("MATLAB:wrongDims", "Matrix size must be >= 100x100.");
}
/* extract sub-matrix */
plhs[0] = mxCreateDoubleMatrix(100, 100, mxREAL);
out = mxGetPr(plhs[0]);
in = mxGetPr(prhs[0]);
numRows = mxGetM(prhs[0]);
for(j=0; j<100; j++) {
for(i=0; i<100; i++) {
*out++ = in[i + numRows*j];
}
}
}
And to test this:
x = rand(1000);
y = x(1:100,1:100);
yy = matrix_slice_mex(x);
isequal(y,yy)
You could have also used memcpy to copy each of the columns (one for-loop instead)