/*
 * SDSPRHST  S-Function for running-histogram function.
 *
 *  Copyright 1995-2000 The MathWorks, Inc. 
 *  $Revision: 1.10 $   $Date: 2000/06/14 14:27:59 $
 */

#define S_FUNCTION_NAME sdsprhst

#include <math.h>
#include <string.h>  /* memset */

#include "dsp_sim.h"

#define MIN_ARG   ssGetArg(S,0)
#define MAX_ARG   ssGetArg(S,1)
#define NBINS_ARG ssGetArg(S,2)
#define NUM_ARGS  3


#ifdef MATLAB_MEX_FILE
#define MDL_CHECK_PARAMETERS
static void mdlCheckParameters(SimStruct *S)
{
    const char *msg = NULL;
    int_T  i;
    real_T d,umin,umax;

    /* Check min/max/nbins: */
    if ((mxGetNumberOfElements(MIN_ARG) != 1)  ||
        (mxGetNumberOfElements(MAX_ARG) != 1)  ||
        (mxGetNumberOfElements(NBINS_ARG) != 1) ) {
      msg = "Minimum, maximum, and number of bins must be scalar values";
      goto FCN_EXIT;
    }


	/* Check nbins: */
    d = mxGetPr(NBINS_ARG)[0];
    i = (int_T)d;
    if ((i != d) || (d <= 0)) {
      msg = "Number of bins must be a non-zero integer";
      goto FCN_EXIT;
    }

	/* Check min/max: */
	if (mxGetPr(MIN_ARG)[0] >= mxGetPr(MAX_ARG)[0]) {
		msg = "Minimum must be less than maximum";
		goto FCN_EXIT;
	}

FCN_EXIT:
    ssSetErrorStatus(S, msg);    
}
#endif


static void mdlInitializeSizes(SimStruct *S)
{
    int_T Nbins;

    ssSetNumSFcnParams(S, NUM_ARGS);

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

    Nbins = (int_T) mxGetPr(NBINS_ARG)[0];

    ssSetNumInputs(        S, 2);  /* One data input, and one reset line */
    ssSetNumOutputs(       S, Nbins);
    ssSetDirectFeedThrough(S, 1);
    ssSetNumSampleTimes(   S, 1);
    ssSetNumIWork(         S, Nbins);
    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)
{
#ifdef MATLAB_MEX_FILE
    if (ssGetSampleTime(S,0) == CONTINUOUS_SAMPLE_TIME) {
        ssSetErrorStatus(S,"Block must have a discrete sample time > 0");
        return;
    }
#endif

    /* Set all histogram bin counts to zero: */
    memset((void *)ssGetIWork(S), (int_T)0, ssGetNumIWork(S)*sizeof(int_T));
}


static void mdlOutputs(real_T *y, const real_T *x, const real_T *u, 
                       SimStruct *S, int_T tid)
{
        UPtrsType    uptr  = ssGetUPtrs(S);
        int_T        Nbins = ssGetNumIWork(S);
        int_T       *h     = ssGetIWork(S);
        const real_T umin  = mxGetPr(MIN_ARG)[0];
        const real_T umax  = mxGetPr(MAX_ARG)[0];

        /*
         * The last input element is a reset line.
         * If non-zero, all states are to be reset.
         */
        if (*uptr[1] != 0.0) {
            memset((void *)h, 0, Nbins*sizeof(int_T));
        }

        /*
         * Update appropriate histogram bin:
         */
        {
            real_T val = *uptr[0];
            int_T  i;

            if (val <= umin) {
                i = 0;
            } else if (val > umax) {
                i = Nbins-1;
            } else {
	             real_T idelta = Nbins/(umax-umin);
	             i = (int_T) (ceil((val - umin)*idelta) - 1);
				}
            (*(h + i))++;

            /* Post buffer to output: */
            for (i=0; i<Nbins; i++) {
                *y++ = (real_T)(*h++);
            }
        }
}


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]: sdsprhst.c */