# 5.4 Introduction to cmex, Part II

The following MEX-file is part two in a series of tutorials intended to demonstrate how to write C MEX-files by way of extended examples. When run in MATLAB this function, mexampl2, accepts one input, a (possibly complex) vector, and if the user requests it, returns one output scalar. The function performs the following actions:

- creates a new figure
- breaks the figure into two subplots
- plots the magnitude and phase of the the vector in the two subplots
- changes the title of the figure to the name of the variable being plotted.

If requested, the function returns the figure handle of the figure created in step one. The user would request this by supplying a return variable when calling mexampl2 from within MATLAB (e.g., fig_handle=mexampl2(...);).

mexampl2 calls the following MEX functions, and discusses their use in detail:

    mexCallMATLAB
    mexEvalString
    mxGetPi
    mxFreeMatrix
    mxCreateString
    mxGetName.

mexampl2 also calls the following MEX functions, which are described more fully in mexample, the first C MEX-files tutorial:

    mexErrMsgTxt
    mxGetM
    mxGetN
    mxIsString
    mxIsSparse
    mxCreateFull
    mxGetPr

In addition, certain basic aspects of MATLAB Handle Graphics are briefly covered in this example.

------------------------------------------------------------

    /*      Include basic header files: */
    #include <math.h>  /* for sqrt, fabs, atan, etc. */
    #include <stdio.h> /* for NULL */
    #include <mex.h>
    /*      First, create two utility functions.  These functions accept two
            arrays of doubles (one representing the real part of a vector
            and the other representing the imaginary part of the vector) and
            return the magnitude and phase of these arrays.  The output data
            is stored in a third input array (whose memory has been
            preallocated), while a fourth input argument represents the
            length of the arrays. */
    #ifdef __STDC__
    void magnitude(
        double *realData,   /* real part of the input vector */
        double *imagData,   /* imaginary part of the input vector */
        double *magData,    /* magnitude of the input vector (return
                               argument)
                            */
        int vectorSize      /* size of the input vector */
        )
    #else
    magnitude(realData,imagData,magData,vectorSize)
    double *realData;       /* real part of the input vector */
    double *imagData;       /* imaginary part of the input vector */
    double *magData;        /* magnitude of the input vector (return
                               argument)
                               */
    int vectorSize;         /* size of the input vector */
    #endif
    {
    int element;            /* loop counter to cycle through elements of the
                               input vector */
    /*      if imagData is not NULL, loop through each element of the input
            vector.  For each element, store in magData the square root of
            the sum of the squares of the real and imaginary parts. */
        if (imagData != NULL)
            for (element=0;element<vectorSize;element++)
                magData[element] = sqrt(realData[element]*realData[element]+
                                        imagData[element]*imagData[element]);
        else                /* otherwise imaginary part is zero, take a
                               short cut: */
            for (element=0;element<vectorSize;element++)
                magData[element] = fabs(realData[element]);

    }                       /* END magnitude() */
    #define PI 3.1415926535897934440892098500626
    #ifdef __STDC__
    void phase(
        double *realData,   /* real part of the input vector */
        double *imagData,   /* imaginary part of the input vector */
        double *phaseData,  /* phase of the input vector (return argument)
                            */
        int vectorSize      /* size of the input vector */
        )
    #else
    phase(realData,imagData,phaseData,vectorSize)
    double *realData;       /* real part of the input vector */
    double *imagData;       /* imaginary part of the input vector */
    double *phaseData;      /* phase of the input vector (return argument)
                            */
    int vectorSize;         /* size of the input vector */
    #endif
    {
    int element;            /* loop counter to cycle through elements of the
                               input vector */
    /*      if imagData is not NULL, loop through each element of the input
            vector.  For each element, store in phaseData the inverse
            tangent of the imaginary part of the vector divided by the real
            part of the vector. */
      if (imagData != NULL)
        for (element=0;element<vectorSize;element++)
          phaseData[element] = atan(imagData[element]/realData[element]);
      else                  /* otherwise imaginary part is zero, take a
                               short cut: */
        for (element=0;element<vectorSize;element++)
          phaseData[element] = (realData[element] > 0 ? 0 : PI);
    }                       /* END phase() */
    /*      Now that the utility functions are defined, we can work on
            mexFunction itself.  But first, some definitions: */

    #define VECTOR_IN prhs[0]
    #define SCALAR_OUT plhs[0]

    #ifdef __STDC__
    void mexFunction(
        int        nlhs,
        Matrix    *plhs[],
        int        nrhs,
        Matrix    *prhs[]
        )
    #else
    mexFunction(nlhs, plhs, nrhs, prhs)
    int nlhs, nrhs;
    Matrix *plhs[], *prhs[];
    #endif
    {
    /*      We will be making several calls to the function mexCallMATLAB.
            Two of that function's inputs are arrays of Matrix pointers.
            The next two variables will be used when we make these calls.
            None of the mexCallMATLAB calls use more than five input
            variables or result in more than 1 output variable, so
            MCM_inputs is declared as a 5-element array, and MCM_outputs is
            declared as a 1 element array.  Optionally, if the maximum
            number of input or output variables were not known ahead of
            time, we could declare MCM_inputs and MCM_outputs to be of type
            Matrix **, and then allocate memory for the array using
            mxCalloc. */
    Matrix * MCM_inputs[5]; /* Matrix pointer array for mexCallMATLAB
                               function */
    Matrix * MCM_outputs[1];/* Matrix pointer array for mexCallMATLAB
                               function */
    Matrix * figure_handle; /* handle to figure that mexampl2 creates */
    int      size_VECTOR_IN;/* number of elements in VECTOR_IN */
    /*      Step 1: Input checking.
            Step 1a: Check nlhs.  Should be 0 or 1. */
      if (nlhs > 1)
        mexErrMsgTxt("mexampl2 only returns up to 1 argument.");
    /*      Step 1b: Check nrhs.  Should be 1. */
      if (nrhs != 1)
        mexErrMsgTxt("Requires 1 input argument.");
    /*      Step 1c: check VECTOR_IN (prhs[0]).  Should be one-dimensional,
            full, and numeric.  Should not be sparse or a string. */
      if ( ((mxGetM(VECTOR_IN) != 1) && (mxGetN(VECTOR_IN) != 1)) ||
        mxIsString(VECTOR_IN) || mxIsSparse(VECTOR_IN) )
        mexErrMsgTxt("Input argument should be Nx1 or 1xN, \
    full, and numeric.");
    /*      For ease later on, we store the size of VECTOR_IN in the
            variable size_VECTOR_IN. */
    size_VECTOR_IN = mxGetM(VECTOR_IN) * mxGetN(VECTOR_IN);
    /*      Step 2: create figure and plot the plots.
            Step 2a: create the figure. In MATLAB, the figure is created
            with the figure command.  To do it here, we will use
            mexCallMATLAB to call the figure function.  The arguments to
            mexCallMATLAB are similar to those for mexFunction itself.
            There is nlhs (the number of output arguments we are
            requesting), plhs (an array of pointers to the output
            arguments), nrhs (the number of input arguments), and
            prhs (an array of pointers to the input arguments).  In
            addition, there is a string which contains the name of the
            function we are going to call (in this case, figure).  The
            mexCallMATLAB call below, then, mimics the MATLAB command
            "figure_handle = figure;".  Note that in this case there are
            zero inputs to figure, so MCM_inputs does not need to be
            initialized. */
    mexCallMATLAB(1,MCM_outputs,0,MCM_inputs,"figure");

    /*      Save result (the figure handle) to SCALAR_OUT.  Since
            mexCallMATLAB reallocates memory for its second argument,
            plhs, each time it is called, we don't need to worry about a
            future mexCallMATLAB call writing over figure_handle.*/
    figure_handle = MCM_outputs[0];
    /*      Step 2b: Create each subplot, title it, and plot the
            corresponding data. This consists of calling mexEvalString to
            call subplot and title, and mexCallMATLAB to call plot.  We
            repeat this twice to plot the magnitude and phase.
            mexEvalString is a simple function which passes its one input, a
            string, to MATLAB for parsing.  Thus it is similar to the eval
            command in MATLAB. */
    mexEvalString("subplot(2,1,1);");       /* causes MATLAB to execute
                                               subplot(2,1,1); */

    /*      Create a matrix to pass to plot as the data to be plotted.  */
    MCM_inputs[0] = mxCreateFull(size_VECTOR_IN,1,REAL);

    /*      Load this matrix with the magnitude of VECTOR_IN: */
    magnitude(mxGetPr(VECTOR_IN),mxGetPi(VECTOR_IN),
    mxGetPr(MCM_inputs[0]),size_VECTOR_IN);

    /*      Call mexCallMATLAB: */
    mexCallMATLAB(0,MCM_outputs,1,MCM_inputs,"plot");

    /*      Title the plot: */
    mexEvalString("title('Magnitude');");  /* Causes MATLAB to execute
                                                 title('Magnitude'); */
    /*      Do it again for imaginary part: First, the subplot command: */
    mexEvalString("subplot(2,1,2);");
    /*      Load the matrix with the phase of VECTOR_IN: */
    phase(mxGetPr(VECTOR_IN),mxGetPi(VECTOR_IN),
    mxGetPr(MCM_inputs[0]),size_VECTOR_IN);

    /*      Call mexCallMATLAB: */
    mexCallMATLAB(0,MCM_outputs,1,MCM_inputs,"plot");

    /*      Title the plot: */
    mexEvalString("title('Phase');");
    /*      Free the matrix pointed to by MCM_inputs[0]. */
    mxFreeMatrix(MCM_inputs[0]);

    /*      For our second to last task, let's make the title of the figure
            be the name of the variable being plotted.  To do this, we need
            to set the figure's 'NumberTitle' property to 'off' and its
            'Name' property to the name of the variable.  We do this with
            another call to mexCallMATLAB, which call the MATLAB set
            command.  To create the MATLAB strings 'NumberTitle', 'off', and
            'Name', we use the function mxCreateString.  This function
            accepts a string input and returns a MATLAB string Matrix
            containing that string.  Note that since mxGetName returns a
            string with the name of VECTOR_IN, we can pass its output
            directly to mxCreateString to create a MATLAB string containing
            the name of VECTOR_IN. */
    MCM_inputs[0] = figure_handle;
    MCM_inputs[1] = mxCreateString("NumberTitle");
    MCM_inputs[2] = mxCreateString("off");
    MCM_inputs[3] = mxCreateString("Name");
    MCM_inputs[4] = mxCreateString(mxGetName(VECTOR_IN));

        mexCallMATLAB(0,MCM_outputs,5,MCM_inputs,"set");
    /*      The above mexCallMATLAB call mimics the MATLAB command
            set(figure_handle,'NumberTitle','off', ...
            'Name',<name of VECTOR_IN>);
            Note, however, that using MEX-files allows users access to the
            name of the input variable, something which no ordinary M-file
            could do!
    */
    /*      Finally, we need to determine what the value of SCALAR_OUT
            should be.  This depends on nlhs.  If nlhs equals 1, then the
            user requested we return the figure handle, and so SCALAR_OUT
            should be set to figure_handle.  If nlhs equals 0, no such
            request was made, and SCALAR_OUT should be NULL. */
    if (nlhs)
          SCALAR_OUT = figure_handle;
    else
          SCALAR_OUT = NULL;
    }       /* END mexFunction() */

(c) Copyright 1994 by The MathWorks, Inc.