External mex-functions for Function and Gradient

External Functions can be defined as mex-functions, similar to m-functions (see External m-functions for Function and Gradient). The format requirements for the External Functions defined as mex-functions are the same as for the External Functions defined as m-functions.

 

Mex-functions are calculated faster than the m-functions, but user should be careful with MATLAB mex-functions and have some experience of working with mex-functions.

 

Example

To implement mex-functions for the problem described in External m-functions for Function and Gradient, create file fnext_polynom_c.c and grext_polynom_c.c (in the folder .\Aorda\PSG\MATLAB\Examples\Problems\) containing codes for calculating  function and its gradient:

 

// file fnext_polynom_c.c

#include "mex.h"

#include <math.h>

void mexFunction( int nlhs, mxArray *plhs[],

                 int nrhs, const mxArray *prhs[])

{

 int D, i, j;

 double*ptr_point, *ptr_A_matrix;

 double value, loc;

   if(nrhs!=3)

     mexErrMsgTxt("3 inputs are required.");

 else if(!mxIsChar(prhs[0]))

                 mexErrMsgTxt("1 parameter must be a string(tab separated names of variables).");

 else if(!mxIsDouble(prhs[1]))

                 mexErrMsgTxt("2 parameter must be a double array(array of values of variables).");

 else if(!mxIsDouble(prhs[2]))

                 mexErrMsgTxt("3 parameter must be a double array (matrix A).");

 D = mxGetN(prhs[1]);

 if ((mxGetN(prhs[2]) != D) || (mxGetN(prhs[2]) != D)) {

         mexErrMsgTxt("Wrong sizes of matrix_A.");

 }

 ptr_point = mxGetPr(prhs[1]);

 ptr_A_matrix = mxGetPr(prhs[2]);

 value = 0.0;

 for (i=0; i<D; i++) {

         for (j=0; j<D; j++) {

                 value += *(ptr_A_matrix+i*D+j)*ptr_point[i]*ptr_point[j];

         }

         loc = ptr_point[i]*ptr_point[i];

         value += loc*loc;

 }

 plhs[0] = mxCreateDoubleScalar(value);

 return;

}

 

// file grext_polynom_с.с

#include "mex.h"

#include <math.h>

 

void mexFunction( int nlhs, mxArray *plhs[],

                          int nrhs, const mxArray *prhs[])

{

 int D, i, j;

 double*ptr_point, *ptr_A_matrix, *gradient, *ptrgrad;

 if(nrhs!=3)

         mexErrMsgTxt("3 inputs are required.");

 else if(!mxIsChar(prhs[0]))

         mexErrMsgTxt("1 parameter must be a string(tab separated names of variables).");

 else if(!mxIsDouble(prhs[1]))

         mexErrMsgTxt("2 parameter must be a double array(array of values of variables).");

 else if(!mxIsDouble(prhs[2]))

         mexErrMsgTxt("3 parameter must be a double array (matrix A).");

 D = mxGetN(prhs[1]);

 if ((mxGetN(prhs[2]) != D) || (mxGetN(prhs[2]) != D)) {

         mexErrMsgTxt("Wrong sizes of matrix_A.");

 }

 ptr_point = mxGetPr(prhs[1]);

 ptr_A_matrix = mxGetPr(prhs[2]);

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

 ptrgrad = mxGetPr(plhs[0]);

 for (i=0; i<D; i++) {

         ptrgrad[i] = 0.0;

         for (j=0; j<D; j++) {

                 ptrgrad[i] += *(ptr_A_matrix+i*D+j)*ptr_point[j];

         }

         ptrgrad[i] += 4.0*ptr_point[i]*ptr_point[i]*ptr_point[i];

 }

 return;

}

 

Compile the files using the following commands:

 

>> mex fnext_polynom_c.c

>> mex grext_polynom_c.c

 

The compilation created files fnext_polynom_c.mexw32 and grext_polynom_c.mexw32 (for x64 version of PSG — fnext_polynom_c.mexw64 and grext_polynom_c.mexw64) .

 

To run the example described in the section External m-functions for Function and Gradient as mex-function, you need to replace the names fnext_polynom_m and grext_polynom_m of the function and its gradient by fnext_polynom_c and grext_polynom_c.

For example, the string of the function definition included in the objective function will look as follows:

'fnext_polynom_ñ(headerpoint, thispoint, A)'

 

The call of the riskprog function for solving the same problem looks as follows:

 

[xout, fval, status] = riskprog('fnext_polynom_с(headerpoint, thispoint, A)', ...

   [], [], [], [], [], [], [], matrix_linear(1, 2:end), 0, -1, 1);

 

Note that in this case the name of the risk function is fnext_polynom_с .

In general, it is possible to refer to the mex-fuctions using their previous names, by implementing them as fnext_polynom_m.c and grext_polynom_m.c files, without modifying the code to solve the problem . However, in this case, a conflict may arise from using External Function from the fnext_polynom_m.m (grext_polynom_m.m) file or from the fnext_polynom_c.mexw32 (grext_polynom_c.mexw32) file. This conflict is always resolved in favor of fnext_polynom_c.mexw32.