/*
 * SELMATH1  S-Function for single input elementary math functions.
 * DSP Blockset S-Function for single input elementary math functions.
 * This SIMULINK S-function computes functions of the input vector;
 * it is called by many of the single input elementary math blocks in the 
 * DSP Blockset, including
 *   sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, exp, log, log10,
 *    floor, ceil, sqrt, inv, pow10.
 *
 *  Copyright 1995-2000 The MathWorks, Inc.
 *  $Revision: 1.9 $  $Date: 2000/05/05 20:16:09 $
 */

#define S_FUNCTION_NAME selmath1

#include <math.h>
#include <string.h>   /* strcmp() */

#include "simstruc.h" /* SimStruct, etc */

#define NUMINPUTARGS    1
#define FCN_NAME        ssGetArg(S, 0)


static void mdlInitializeSizes(SimStruct *S)
{
#ifdef MATLAB_MEX_FILE
    mexWarnMsgTxt("Obsolete blocks calling the CMEX S-Function 'selmath1' have\n"
                  "been detected.  If you wish to upgrade this model, replace\n"
                  "all elementary math blocks (such as sin, cos, and tan) with\n"
                  "new versions found in the block library:\n"
                  "        'dsplib/Math Functions/Elementary Math'\n"
                  "If you wish to disable this warning message, type\n"
                  "'warning off' at the MATLAB command line.\n\n");
#endif
    ssSetNumContStates(    S, 0);                 /* number of continuous states */
    ssSetNumDiscStates(    S, 0);                 /* number of discrete states */
    ssSetNumInputs(        S, DYNAMICALLY_SIZED); /* number of inputs */
    ssSetNumOutputs(       S, DYNAMICALLY_SIZED); /* number of outputs */
    ssSetDirectFeedThrough(S, 1);                 /* direct feedthrough flag */
    ssSetNumSampleTimes(   S, 1);                 /* number of sample times */
    ssSetNumInputArgs(     S, NUMINPUTARGS);      /* number of input arguments */
    ssSetNumRWork(         S, 0);                 /* number of real work vector elements */
    ssSetNumIWork(         S, 0);                 /* number of integer work vector elements */
    ssSetNumPWork(         S, 1);                 /* number of pointer work vector elements */
}


static void mdlInitializeSampleTimes(SimStruct *S)
{
    ssSetSampleTimeEvent(S, 0, INHERITED_SAMPLE_TIME);
    ssSetOffsetTimeEvent(S, 0, 0.0);
}

static real_T inverse(real_T u)
{
    return 1.0 / u;
}

static real_T pow10(real_T u)
{
    return pow(10.0, u);
}

static void mdlInitializeConditions(real_T *x0, SimStruct *S)
{
    typedef real_T (*fcn) (const real_T);
    fcn *PWork = (fcn *)ssGetPWork(S);
    char fcnName[16];


    /*
     * get the function name from the input argument, bail out
     * if for some reason mxGetString can't convert it
     */

#ifdef MATLAB_MEX_FILE
    if (mxGetString(FCN_NAME, fcnName, sizeof(fcnName)) != 0) {
	mexErrMsgTxt("Error in function name specification.");
    }
#else    
    /* in case of code generation, don't bother with error checking: */
    /* (works around bug in mxGetString as defined in cg_matrx.h)    */
    mxGetString(FCN_NAME, fcnName, sizeof(fcnName));
#endif

    /*
     * translate the name into a function pointer
     */

    if (strcmp(fcnName, "sin") == 0)
        *PWork = (fcn) sin;
    else if (strcmp(fcnName, "cos") == 0)
        *PWork = (fcn) cos;
    else if (strcmp(fcnName, "tan") == 0)
        *PWork = (fcn) tan;
    else if (strcmp(fcnName, "asin") == 0)
        *PWork = (fcn) asin;
    else if (strcmp(fcnName, "acos") == 0)
        *PWork = (fcn) acos;
    else if (strcmp(fcnName, "atan") == 0)
        *PWork = (fcn) atan;
    else if (strcmp(fcnName, "sinh") == 0)
        *PWork = (fcn) sinh;
    else if (strcmp(fcnName, "cosh") == 0)
        *PWork = (fcn) cosh;
    else if (strcmp(fcnName, "tanh") == 0)
        *PWork = (fcn) tanh;
    else if (strcmp(fcnName, "exp") == 0)
        *PWork = (fcn) exp;
    else if (strcmp(fcnName, "log") == 0)
        *PWork = (fcn) log;
    else if (strcmp(fcnName, "log10") == 0)
        *PWork = (fcn) log10;
    else if (strcmp(fcnName, "floor") == 0)
        *PWork = (fcn) floor;
    else if (strcmp(fcnName, "ceil") == 0)
        *PWork = (fcn) ceil;
    else if (strcmp(fcnName, "sqrt") == 0)
        *PWork = (fcn) sqrt;
    else if (strcmp(fcnName, "inv") == 0)
        *PWork = (fcn) inverse;
    else if (strcmp(fcnName, "pow10") == 0)
        *PWork = (fcn) pow10;
#ifdef MATLAB_MEX_FILE
    else
        mexErrMsgTxt("Error in function name specification.");
#endif
}

static void mdlOutputs(real_T *y, const real_T *x, const real_T *u, 
                       SimStruct *S, int_T tid)
{
    int_T width = ssGetNumInputs(S);
    typedef real_T (*fcn)(const real_T);
    fcn dfcn = ((fcn *)ssGetPWork(S))[0];

    while(width-- != 0) {
      *y++ = (*dfcn)(*u++);
    }
}

static void mdlUpdate(real_T *x, const real_T *u, SimStruct *S, int_T tid)
{
}

static void mdlDerivatives(real_T *dx, const real_T *x, const real_T *u, 
                           SimStruct *S, int_T tid)
{
}


static void mdlTerminate(SimStruct *S)
{
}


#ifdef  MATLAB_MEX_FILE    /* Is this file being compiled as a MEX-file? */
#include "simulink.c"      /* MEX-file interface mechanism */
#else
#include "cg_sfun.h"       /* Code generation registration function */
#endif
