From: Aino on
Hi all!

I have tried to speed up my Matlab code (parfor was not enough to do that..) and now decided to try with mex-file. Turned out to be a bit challenging.. The code below gives 12 error messages, all "type error: pointer expected". But I feel like I have a pointer to all of my variables. So, is there something wrong with the way I'm using the mxCalloc-function, have I understood it completely wrong? Also in m-files I could use a statement such as: a=A(1:3), do I really need to use for loops in here (loops ii and jj in my code)?

In my code, cop is a column vector, M is a scalar integer, and r and c are scalars (type double). I am starting to wonder if this mex-file will ever speed my code, which is something I need to do (regardless of my ability to do that.. ;) ).

Any comments (also the ones that do not concern the pointer problem) are appreciated!

Thank You so much,
Aino



#include <math.h>
#include "mex.h"


/*Subroutine to calculate the Fuzzy Sample Entropy*/
void FSE(double *cop, int M, double r, double c, mwSize N, double *FuzzSampEnt) {

mwSize m, i, ii, j, jj, k, l;
int *countii, *countjj;
double *expo, *d, *seg_i, *seg_j, *count, *sumCim, *Cim, *CIM;

expo=mxCalloc(1,sizeof(double));
d=mxCalloc(1,sizeof(double));
count=mxCalloc(1,sizeof(double));
sumCim=mxCalloc(1,sizeof(double));
countii=mxCalloc(1,sizeof(int));
countjj=mxCalloc(1,sizeof(int));
CIM=mxCalloc(2,sizeof(double));


*expo=(log(log(pow(2, c)))/log(r));


for (m=M;m<M+2;m++) {

seg_i=mxCalloc(m, sizeof(double));
seg_j=mxCalloc(m, sizeof(double));
Cim=mxCalloc(N-m, sizeof(double));

for (i=0; i<N-m; i++) {
*count=0;

*countii=-1;
for (ii=i; ii<i+m; ii++){
*countii=*countii++;
*seg_i[*countii]=cop[ii];
}

for (j=0; j<N-m; j++) {

*countjj=-1;
for (jj=j; jj<j+m; jj++) {
*countjj=*countjj++;
*seg_j[*countjj]=cop[jj];
}


*d=0;
/*Finding the maximum absolut value of seg_i-seg_j*/
for (k=0; k<N; k++) {
if (*d < abs(*seg_i[k]-*seg_j[k])) {
*d=abs(*seg_i[k]-*seg_j[k]);
}
}

/*if d=0, self match*/
if (*d>0) {
*count+=exp(-(pow(*d, *expo/c)));
}

}
*Cim[i]=*count/(N-m-1);
}

*sumCim=0;
for(l=0;l<N-m;l++){
*sumCim+=*Cim[l];
}

if (m==M){
*CIM[0]=*sumCim/(N-m);
}
else if (m==M+1){
*CIM[1]=*sumCim/(N-m);
}

}

*FuzzSampEnt=-log(*CIM[1]/ *CIM[0]);

mxFree(seg_i);
mxFree(seg_j);
mxFree(Cim);
mxFree(expo);
mxFree(CIM);
mxFree(count);
mxFree(d);
}


/*the gateway function*/
void mexFunction(int nlhs, mxArray *plhs[ ],
int nrhs, const mxArray *prhs[ ]) {

int M;
double *cop, *FuzzSampEnt;
double c, r;
mwSize N;

if(nrhs!=4) {
mexErrMsgTxt("Four inputs required (cop,M,r,c).");
}

/*Assign pointers*/
cop=mxGetPr(prhs[0]);
N=mxGetM(prhs[0]);//Not sure if this should be mxGetN
M=(int)(mxGetScalar(prhs[1]));
r=mxGetScalar(prhs[2]);
c=mxGetScalar(prhs[3]);

plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
FuzzSampEnt = mxGetPr(plhs[0]);

/*Call the subroutine */
FSE(cop, M, r, c, N, FuzzSampEnt);

return;
}
From: Aino on
I forgot, here are the lines where the pointer errors are found.

-Aino

#include <math.h>
#include "mex.h"



/*Subroutine to calculate the Fuzzy Sample Entropy*/
void FSE(double *cop, int M, double r, double c, mwSize N, double *FuzzSampEnt) {

mwSize m, i, ii, j, jj, k, l;
int *countii, *countjj;
double *expo, *d, *seg_i, *seg_j, *count, *sumCim, *Cim, *CIM;

expo=mxCalloc(1,sizeof(double));
d=mxCalloc(1,sizeof(double));
count=mxCalloc(1,sizeof(double));
sumCim=mxCalloc(1,sizeof(double));
countii=mxCalloc(1,sizeof(int));
countjj=mxCalloc(1,sizeof(int));
CIM=mxCalloc(2,sizeof(double));


*expo=(log(log(pow(2, c)))/log(r));


for (m=M;m<M+2;m++) {

seg_i=mxCalloc(m, sizeof(double));
seg_j=mxCalloc(m, sizeof(double));
Cim=mxCalloc(N-m, sizeof(double));

for (i=0; i<N-m; i++) {
*count=0;

*countii=-1;
for (ii=i; ii<i+m; ii++){
*countii=*countii++;
*seg_i[*countii]=cop[ii];//ERROR
}

for (j=0; j<N-m; j++) {

*countjj=-1;
for (jj=j; jj<j+m; jj++) {
*countjj=*countjj++;
*seg_j[*countjj]=cop[jj];//ERROR
}


*d=0;
/*Finding the maximum absolut value of seg_i-seg_j*/
for (k=0; k<N; k++) {
if (*d < abs(*seg_i[k]-*seg_j[k])) {//ERROR x 2
*d=abs(*seg_i[k]-*seg_j[k]);//ERROR x 2
}
}

/*if d=0, self match*/
if (*d>0) {
*count+=exp(-(pow(*d, *expo/c)));
}

}
*Cim[i]=*count/(N-m-1);//ERROR
}

*sumCim=0;
for(l=0;l<N-m;l++){
*sumCim+=*Cim[l];//ERROR
}

if (m==M){
*CIM[0]=*sumCim/(N-m);//ERROR
}
else if (m==M+1){
*CIM[1]=*sumCim/(N-m);//ERROR
}

}

*FuzzSampEnt=-log(*CIM[1]/ *CIM[0]);//ERROR x 2

mxFree(seg_i);
mxFree(seg_j);
mxFree(Cim);
mxFree(expo);
mxFree(CIM);
mxFree(count);
mxFree(d);
}


/*the gateway function*/
void mexFunction(int nlhs, mxArray *plhs[ ],
int nrhs, const mxArray *prhs[ ]) {

int M;
double *cop, *FuzzSampEnt;
double c, r;
mwSize N;

if(nrhs!=4) {
mexErrMsgTxt("Four inputs required (cop,M,r,c).");
}

/*Assign pointers*/
cop=mxGetPr(prhs[0]);
N=mxGetM(prhs[0]);
M=(int)(mxGetScalar(prhs[1]));
r=mxGetScalar(prhs[2]);
c=mxGetScalar(prhs[3]);

plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
FuzzSampEnt = mxGetPr(plhs[0]);

/*Call the subroutine */
FSE(cop, M, r, c, N, FuzzSampEnt);

return;
}
From: Aino on
Hi again, I cleaned up the code a little bit, now it compiles (I had to change several variables *var[i]->var[i], I guess that asterisk does not always have to be there). It still doesn't do what it is supposed to, though, something wrong with the seg_i and seg_j variables..

Need to continue tomorrow..

-Aino

#include <math.h>
#include "mex.h"

/*Subroutine to calculate the Fuzzy Sample Entropy*/
void FSE(double *cop, int M, double r, double c, mwSize N, double *FuzzSampEnt) {

mwIndex m, i, ii, j, jj, k, l;
double *expo, *d, *seg_i, *seg_j, *count, *sumCim, *Cim, *CIM;

expo=mxCalloc(1,sizeof(double));
d=mxCalloc(1,sizeof(double));
count=mxCalloc(1,sizeof(double));
sumCim=mxCalloc(1,sizeof(double));
CIM=mxCalloc(2,sizeof(double));


*expo=(log(log(pow(2, c)))/log(r));


for (m=M;m<M+2;m++) {

seg_i=mxCalloc(m, sizeof(double));
seg_j=mxCalloc(m, sizeof(double));
Cim=mxCalloc(N-m, sizeof(double));

for (i=0; i<N-m; i++) {
*count=0;

for (ii=0; ii<m; ii++){
seg_i[ii]=cop[i+ii];
}

for (j=0; j<N-m; j++) {

for (jj=0; jj<m; jj++) {
seg_j[jj]=cop[j+jj];
}


*d=0;
/*Finding the maximum absolut value of seg_i-seg_j*/
for (k=0; k<m; k++) {
if (*d < abs(seg_i[k]-seg_j[k])) {
*d=abs(seg_i[k]-seg_j[k]);
}
}

/*if d=0, self match*/
if (*d>0) {
*count+=exp(-(pow(*d, *expo/c)));
}

}
Cim[i]=*count/(N-m-1);
}

*sumCim=0;
for(l=0;l<N-m;l++){
*sumCim+=Cim[l];
}

if (m==M){
CIM[0]=*sumCim/(N-m);
}
else if (m==M+1){
CIM[1]=*sumCim/(N-m);
}

}

*FuzzSampEnt=-log(CIM[1]/ CIM[0]);

mxFree(seg_i);
mxFree(seg_j);
mxFree(Cim);
mxFree(expo);
mxFree(CIM);
mxFree(count);
mxFree(d);
}


/*the gateway function*/
void mexFunction(int nlhs, mxArray *plhs[ ],
int nrhs, const mxArray *prhs[ ]) {

int M;
double *cop, *FuzzSampEnt;
double c, r;
mwSize N;

if(nrhs!=4) {
mexErrMsgTxt("Four inputs required (cop,M,r,c).");
}

/*Assign pointers*/
cop=mxGetPr(prhs[0]);
N=mxGetM(prhs[0]);
M=(int)(mxGetScalar(prhs[1]));
r=mxGetScalar(prhs[2]);
c=mxGetScalar(prhs[3]);

plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
FuzzSampEnt = mxGetPr(plhs[0]);

/*Call the subroutine */
FSE(cop, M, r, c, N, FuzzSampEnt);

return;
}
From: James Tursa on
"Aino" <aino.tietavainen(a)removeThis.helsinki.fi> wrote in message <i3d6pc$5rd$1(a)fred.mathworks.com>...
>
> double *expo, *d, *seg_i, *seg_j, *count, *sumCim, *Cim, *CIM;
>
> expo=mxCalloc(1,sizeof(double));
> d=mxCalloc(1,sizeof(double));
> count=mxCalloc(1,sizeof(double));
> sumCim=mxCalloc(1,sizeof(double));
> countii=mxCalloc(1,sizeof(int));
> countjj=mxCalloc(1,sizeof(int));
> CIM=mxCalloc(2,sizeof(double));

Why the heck are you doing this??? What is the point of declaring these as pointers and then allocating them to size 1 or 2? Why not just declare them as scalars or arrays of length 2 and be done with it? I don't understand this unnecessary complication.

(snip)

> *seg_i[*countii]=cop[ii];//ERROR

OK. So just follow the syntax to see what is going on. seg_i is type (double *). Then the brackets [ ] come next, and that dereferences seg_i, so the type of seg_i[*countii] is (double). So next comes the * dereference operator. So when the compiler sees *seg_i[*countii] it means you are trying to dereference something of type (double), which of course makes no sense, so you get a compiler error. You repeat this problem over and over again in your code.

You have a fundamental misunderstanding of the use of pointers and dereferencing them via the * and [ ] operators. When looking at this type of syntax, basically follow these rules:

Do everything inside any parentheses first ( )
Then do any [ ] dereferencing
Then do any * dereferencing

You might want to consult a good C/C++ text or look online for some tutorials.


James Tursa
From: Aino on
Dear Mr. Tursa,

thank you for your useful comments!

"James Tursa" <aclassyguy_with_a_k_not_a_c(a)hotmail.com> wrote in message <i3dbl0$907$1(a)fred.mathworks.com>...
> "Aino" <aino.tietavainen(a)removeThis.helsinki.fi> wrote in message <i3d6pc$5rd$1(a)fred.mathworks.com>...
> >
> > double *expo, *d, *seg_i, *seg_j, *count, *sumCim, *Cim, *CIM;
> >
> > expo=mxCalloc(1,sizeof(double));
> > d=mxCalloc(1,sizeof(double));
> > count=mxCalloc(1,sizeof(double));
> > sumCim=mxCalloc(1,sizeof(double));
> > countii=mxCalloc(1,sizeof(int));
> > countjj=mxCalloc(1,sizeof(int));
> > CIM=mxCalloc(2,sizeof(double));
>
> Why the heck are you doing this??? What is the point of declaring these as pointers and then allocating them to size 1 or 2? Why not just declare them as scalars or arrays of length 2 and be done with it? I don't understand this unnecessary complication.

I read somewhere that the pointers are the most difficult part in C to understand so I tried to look at examples that used them. Maybe I looked at too many.. End of my post is another code where I have tried to get rid of these mxCallocs.

>
> (snip)
>
> > *seg_i[*countii]=cop[ii];//ERROR
>
> OK. So just follow the syntax to see what is going on. seg_i is type (double *). Then the brackets [ ] come next, and that dereferences seg_i, so the type of seg_i[*countii] is (double). So next comes the * dereference operator. So when the compiler sees *seg_i[*countii] it means you are trying to dereference something of type (double), which of course makes no sense, so you get a compiler error. You repeat this problem over and over again in your code.

I think I didn't realize that brackets dereference. I got rid of them already in my previous post.

>
> You have a fundamental misunderstanding of the use of pointers and dereferencing them via the * and [ ] operators.

Agreed.

When looking at this type of syntax, basically follow these rules:
>
> Do everything inside any parentheses first ( )
> Then do any [ ] dereferencing
> Then do any * dereferencing
>
> You might want to consult a good C/C++ text or look online for some tutorials.

I am going to a book store hopefully today, my problem is not so much laziness but lack of time (I guess I'm not the only one). I am trying to get the code to calculate my results ASAP so that I have any possibility to meet my DL.

>
>
> James Tursa

So below is my code as it is now. I left the seg_i, seg_j and Cim as they were previously (I tried to declare them as arrays of size M+1 or N-M as "double seg_i[M+1], seg_j[M+1], Cim[N-M];", but this just created new errors). It compiles, but doesn't still work as it should. I believe the problem lies in here:

seg_i[ii]=cop[i+ii];//TROUBLE,

and more particularly in the left hand side (so again pointer stuff..). I don't understand why seg_i is not getting the cop[i+ii]-value in ii. Is it so that I am now trying to put double (cop[i+ii]) in to a double (seg_i[ii])? If so, I cannot figure out how to get around it. I know this must seen trivial to you, but I am really stuck here..

Thank you,
Aino



#include <math.h>
#include "mex.h"

/*Subroutine to calculate the Fuzzy Sample Entropy*/
void FSE(double *cop, int M, double r, double c, mwSize N, double *FuzzSampEnt) {

mwIndex m, i, ii, j, jj, k, l;
double expo, d, *seg_i, *seg_j, count, sumCim, *Cim, CIM[2];

expo=(log(log(pow(2, c)))/log(r));


for (m=M;m<M+2;m++) {

seg_i=mxCalloc(m, sizeof(double));
seg_j=mxCalloc(m, sizeof(double));
Cim=mxCalloc(N-m, sizeof(double));

for (i=0; i<N-m; i++) {
count=0;

for (ii=0; ii<m; ii++){
seg_i[ii]=cop[i+ii];//TROUBLE?
}

for (j=0; j<N-m; j++) {

for (jj=0; jj<m; jj++) {
seg_j[jj]=cop[j+jj];//TROUBLE?
}

d=0;
/*Finding the maximum absolut value of seg_i-seg_j*/
for (k=0; k<m; k++) {
if (d < fabs(seg_i[k]-seg_j[k])) {
d=fabs(seg_i[k]-seg_j[k]);
}
}

/*if d=0, self match*/
if (d>0) {
count+=exp(-(pow(d, expo/c)));
}

}
Cim[i]=count/(N-m-1);//MORE TROUBLE?
}

sumCim=0;
for(l=0;l<N-m;l++){
sumCim+=Cim[l];
}

if (m==M){
CIM[0]=sumCim/(N-m);
}
else if (m==M+1){
CIM[1]=sumCim/(N-m);
}

}

*FuzzSampEnt=-log(CIM[1]/ CIM[0]);

mxFree(seg_i);
mxFree(seg_j);
mxFree(Cim);

}


/*the gateway function*/
void mexFunction(int nlhs, mxArray *plhs[ ],
int nrhs, const mxArray *prhs[ ]) {

int M;
double *cop, *FuzzSampEnt;
double c, r;
mwSize N;

if(nrhs!=4) {
mexErrMsgTxt("Four inputs required (cop,M,r,c).");
}

/*Assign pointers*/
cop=mxGetPr(prhs[0]);
N=mxGetM(prhs[0]);
M=(int)(mxGetScalar(prhs[1]));
r=mxGetScalar(prhs[2]);
c=mxGetScalar(prhs[3]);

plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
FuzzSampEnt = mxGetPr(plhs[0]);

/*Call the subroutine */
FSE(cop, M, r, c, N, FuzzSampEnt);

return;
}