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.