/*
 * SDSPMNMX DSP Blockset S-Function for min/max computation,
 * with value and index outputs.
 *
 *  Updated: D. Orofino, 25-Jun-97
 *  Copyright 1995-2000 The MathWorks, Inc.
 *  $Revision: 1.8 $  $Date: 2000/05/05 20:16:03 $
 */

#define S_FUNCTION_NAME sdspmnmx

#include "dsp_sim.h"

#define FCN_TYPE ssGetArg(S,0)
#define NUM_ARGS 1

typedef enum {
    fcnMin,
    fcnMax
} FcnType;


#ifdef MATLAB_MEX_FILE
#define MDL_CHECK_PARAMETERS
static void mdlCheckParameters(SimStruct *S) {
    /*
     * One parameter, a scalar double (0 or 1, only):
     */
    if ( !mxIsDouble(FCN_TYPE)    ||
         (mxGetM(FCN_TYPE) != 1)  ||
         (mxGetN(FCN_TYPE) != 1)  ||
         ( (mxGetPr(FCN_TYPE)[0]!=0) &&
           (mxGetPr(FCN_TYPE)[0]!=1)  )
       ) {
        ssSetErrorStatus(S, "Function type must be 0 (min) or 1 (max).");
    }
}
#endif


static void mdlInitializeSizes(SimStruct *S)
{
    ssSetNumSFcnParams(S, NUM_ARGS);      /* number of input arguments */

#if defined(MATLAB_MEX_FILE)
    if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) return;
    mdlCheckParameters(S);
    if (ssGetErrorStatus(S) != NULL) return;
#endif

    ssSetNumInputs(        S, DYNAMICALLY_SIZED);
    ssSetNumOutputs(       S, 2);
    ssSetDirectFeedThrough(S, 1);
    ssSetNumSampleTimes(   S, 1);
    ssSetOptions(          S, SS_OPTION_EXCEPTION_FREE_CODE |
                              SS_OPTION_USING_ssGetUPtrs);
}


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


static void mdlInitializeConditions(real_T *x0, SimStruct *S)
{
}


static void mdlOutputs(real_T *y, const real_T *x, const real_T *u, 
                       SimStruct *S, int_T tid)
{
    FcnType   ftype = (FcnType)((int_T)mxGetPr(FCN_TYPE)[0]);
    UPtrsType uptr  = ssGetUPtrs(S);
    int_T     width = ssGetNumInputs(S);
    real_T    m_val = **(uptr++);  /* 1st element is initial min or max */
    int_T     m_idx = 0;           /* 0-based index of 1st element is 0 */

    switch(ftype) {
    case fcnMin:
        {
            int_T idx;
            for (idx=1; idx<width; idx++) {
                real_T val = **(uptr++);
                if (val < m_val) {
                    m_val = val;
                    m_idx = idx;
                }
            }
            break;
        }

    case fcnMax:
        {
            int_T idx;
            for (idx=1; idx<width; idx++) {
                real_T val = **(uptr++);
                if (val > m_val) {
                    m_val = val;
                    m_idx = idx;
                }
            }
            break;
        }
    }

    y[0] = m_val;
    y[1] = (real_T)(m_idx + 1); /* Convert C-index to 1-based MATLAB index */
}


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)
{
}


#include "dsp_trailer.c"
 
/* [EOF]: sdspmnmx.c */