#ifndef __SIMSTRUC__
#define __SIMSTRUC__

/* Copyright (c) 1993,1994 The Mathworks, Inc.
 * All Rights Reserved.
 *
 * File    : simstruc.h
 *
 * Abstract:
 *
 *      Data structures and access methods for S-function C files.
 *      This file contains details of SimStruct which is used to
 *      store attributes of the model such as pointers to storge
 *      vectors.
 *
 * Defines:
 *      Defines used from generated model source.
 *        ANSI_FUNCTION_PROTOTYPES
 *        SIMULINK_NAME="name"
 *        NSAMPLE_TIMES=n
 *
 *      Defines required before include of this file (usually defined when 
 *      invoking compiler):
 *        MODEL_NAME=name    - Required ifndef MATLAB_MEX_FILE.
 *        MULTITASKING       - Optional (use MT for a synonym).
 *        MATLAB_MEX_FILE    - Must be defined when compiling as a MEX file,
 *                             otherwise must not be defined.
 *        NUMST=n            - Optional, if specified must equal number of 
 *                             sample times in the root SimStruct.  Specifying
 *                             this value may increase performance.
 */


#ifdef MATLAB_MEX_FILE
# include "matrix.h"
#else
# include "cg_matrx.h"
#endif


/*
 * Let MT be synonym for MULTITASKING (to shorten command line for DOS) 
 */
#ifdef MT
# define MULTITASKING
#endif


/*=========*
 * Defines *
 *=========*/

/*
 * DYNAMICALLY_SIZED     - Specify for sizes entries that inherit their values
 *                         from the block that drives them.
 *
 * INHERITED_SAMPLE_TIME - Specify for blocks that inherit their sample time 
 *                         from the block that feeds their input.
 *
 * TID_EQUALS_SAMPLE_TIME_INDEX - The model will function correctly if this
 *                         define is false, however if this define is true
 *                         the model's performance may be increased depending
 *                         upon whether or not the model has fast to slow 
 *                         rate transitions.
 */

#define INHERITED_SAMPLE_TIME   -1.0
#define DYNAMICALLY_SIZED       -1
#define SIMSTRUCT_VERSION	1.0


#define TID_EQUALS_SAMPLE_TIME_INDEX     0   /* assume FALSE */

#ifdef NUMST
# ifdef NSAMPLE_TIMES
#  if NUMST < NSAMPLE_TIMES
     --> NUMST specified incorrectly
#  endif
#  if NUMST == NSAMPLE_TIMES
#    undef  TID_EQUALS_SAMPLE_TIME_INDEX
#    define TID_EQUALS_SAMPLE_TIME_INDEX    1
#  endif
# endif
#endif


/*===============================================*
 * Defines use to check for existance of defines *
 *===============================================*/
#ifdef SIMULINK_NAME
# define defined_SIMULINK_NAME   1
#else
# define defined_SIMULINK_NAME   0
#endif

#ifdef S_FUNCTION_NAME
# define defined_S_FUNCTION_NAME 1
#else
# define defined_S_FUNCTION_NAME 0
#endif


/*================*
 * ModelScopeInfo *
 *================*/
typedef struct ModelScopeInfo_tag {

  char	 *name;		/* the name of this scope variable                   */
  int	 scope;		/* 1 if this is a scope, 0 if a to_workspace         */
  int	 scopeIndex;	/* index into the Scope vector for this scope        */
  int	 inputWidth;	/* width of the input to this scope                  */
  int	 maximumRows;	/* the maximum # of points to store (-1 if no limit) */
  double sampleTime;	/* the scope sample time                             */
  int	 modulus;	/* only store every modulus samples                  */

} ModelScopeInfo;



/*================*
 * ModelBlockInfo *
 *================*/
typedef struct ModelBlockInfo_tag {

  char	*name;		   /* the name of this block                         */
  int	n_outputs;	   /* the number of output ports for this block      */
  int	*blockIO_indices;  /* indices into the BlockIO vector for this       */
                           /*   block's outputs                              */
  int	*output_widths;	   /* array of output widths for each output port    */

} ModelBlockInfo;



/*=========================================================================*
 * Sizes_array_ty - used to access the sizes array, returned by s-function *
 * when flag=0                                                             *
 ==========================================================================*/
typedef enum {

  NumContStates_index,  /* number of continuous states                       */
  NumDiscStates_index,  /* number of discrete states                         */
  NumOutputs_index,     /* number of outputs                                 */
  NumInputs_index,      /* number of inputs                                  */
  Reserved_index,       /* reserved space                                    */
  DirFeedThru_index,    /* is there direct feed-through                      */
  NumSampleTimes_index, /* # of different sample times and/or time offsets   */
  NumInputArgs_index,   /* number of external matrices passed in             */

                        /* ------------------- Work vectors ---------------- */
  NumIWork_index,       /* size of integer work vector                       */
  NumRWork_index,       /* size of double precision work vector              */
  NumPWork_index,       /* size of pointer work vector                       */
  
                        /* ------------------- Special blocks -------------- */
  NumBlocks_index,      /* number of Blocks in the model                     */
  NumSFunctions_index,  /* number of S-Functions                             */
  NumScopes_index,      /* number of Scopes                                  */

                        /* ------------ Accelerator bookkeeping ------------ */
  NumBlockIO_index,     /* number of block outputs                           */
  NumBlockParams_index, /* number of block parameters                        */
  Checksum_index,       /* model checksum                                    */
  Paramchecksum_index,  /* parameter vector checksum                         */

  SIZES_LENGTH          /* dim of the sizes array == last entry in this enum */

} Sizes_array_ty;



/*==================================*
 * Structures with in the SimStruct *
 *==================================*/
#ifdef __STDC__
  /* Use incomplete type for function prototypes within SimStruct itself */
  typedef struct SimStruct_tag SimStruct;
#endif


struct _ssInputs {
  int    NumArgs;             /* number of input args       */
  Matrix **Args;              /* additional input arguments */
};


struct _ssVectors {
  double *RWork;              /* real work vector                            */
  int    *IWork;              /* integer work vector                         */
  void  **PWork;              /* pointer work vector                         */
  double *BlockIO;            /* block inputs/outputs                        */
  double *BlockParam;         /* block parameter vector  (local copy)        */
  double *DefaultParam;       /* Default parameter vector.                   */
                              /* Note: DefaultParam points to global storage;*/
                              /*       common to all instances of this model */
};


struct _ssEvents {
  double *SampleTimes;        /* interval times for discrete systems         */
  double *OffsetTimes;        /* skew times for discrete systems             */
  
  double *NextTimes;          /* next sample hit time                        */
  double *PresentTimes;       /* present sample hit time                     */
  int    *SampleHits;         /* sample hit events                           */
  int    *Counters;           /* sample hit counters                         */
  int    *SampleCount;        /* sample time in StepSize counts              */
  int    *OffsetCount;        /* how much to offset the count by             */
  int    *SampleTimeTaskIDs;  /* which task owns this sample rate            */
  int    *PerTaskSampleHits;  /* Sample hit events as viewed in each task    */
};


struct _ssModelMethods {

# ifdef ANSI_FUNCTION_PROTOTYPES

    void (*mdlInitializeSizes)(SimStruct *S);
    void (*mdlInitializeSampleTimes)(SimStruct *S);
    void (*mdlInitializeConditions)(double *x0, SimStruct *S);
    void (*mdlOutputs)(double *y, const double *x, const double *u, 
		       SimStruct *S, int id);
    void (*mdlUpdate)(double *x, const double *u, SimStruct *S, int id);
    void (*mdlDerivatives)(double *dx, const double *x, const double *u, 
			   SimStruct *S, int id);
    void (*mdlTerminate)(SimStruct *S);
    ModelBlockInfo * (*mdlBlockInfo)(void);
    ModelScopeInfo * (*mdlScopeInfo)(void);

# else

    void (*mdlInitializeSizes)();        /* initialize sizes array           */
    void (*mdlInitializeSampleTimes)();  /* initialize sample times          */
    void (*mdlInitializeConditions)();   /* initialize model parameters      */
    void (*mdlOutputs)();                /* fill output vector               */
    void (*mdlUpdate)();                 /* update the discrete states       */
    void (*mdlDerivatives)();            /* compute the derivatives          */
    void (*mdlTerminate)();              /* end of model housekeeping        */
    ModelBlockInfo * (*mdlBlockInfo)();  /* return block info vector         */
    ModelScopeInfo * (*mdlScopeInfo)();  /* return scope info                */

# endif
};


struct _ssStates {
  double *U;            /* input vector      */
  double *Y;            /* output vector     */
  double *X;            /* state vector      */
  double *dX;           /* derivative vector */
  double *Scopes;       /* scopes vector     */
};


struct _ssUtility {
  double *TempStore0;   /* storage vectors for RK integration methods */
  double *TempStore1;
  double *TempStore2;
  double *TempStore3;
  double *TempStore4;
  double *TempStore5;
  double *TempStore6;
  double *TempY;        /* Temporary storate for output vector        */
  double *TempX;        /* Temporary storage for state vector         */
  void *UserData;	/* user data                                  */
};


/*===========*
 * SimStruct *
 *===========*/
#ifndef __STDC__
  typedef
#endif
struct SimStruct_tag {

  double                  Version;             /* Version number             */
  char                    *ModelName;	       /* Name of the SIMULINK model */

  struct SimStruct_tag    *Parent;	       /* Parent SimStruct           */
  struct SimStruct_tag    *Root;	       /* Root level SimStruct       */
        
  int                     Sizes[SIZES_LENGTH]; /* Sizes array (returned when */
                                               /*   flag == 0)               */

  struct _ssInputs        Inputs;              /* User input arguments passed*/
                                               /*   to S-function            */

  struct _ssVectors       Vectors;             /* Various vectors (work,     */
                                               /*   block I/O, params)       */

  double                  T;                   /* The time                   */
  double                  TFinal;              /* Final model stop time      */
# ifdef NRT
    double                IntgStopTime;        /* Integration stop time      */
# endif
  double                  Tcount;              /* Flint counter for accurate */
                                               /*   time base                */
  double                  StepSize;            /* The integration step size  */
  int                     MinorTimeStepFlag;   /* Flag to indicate minor time*/
                                               /*   steps                    */
  
  struct _ssEvents        Events;              /* Contains arrays of         */
                                               /*   model time events        */

  struct _ssModelMethods  ModelMethods;        /* Model functions            */

  struct _ssStates        States;              /* Input, output, state,      */
                                               /*   derivative, etc. vectors */

  struct _ssUtility       Utility;             /* Storage for utilities      */
                                               /*   (e.g. integration)       */

  struct SimStruct_tag    **SFunctions;	       /* SimStruct's for S-Functions*/
}
#ifndef __STDC__
  SimStruct;
#else
  ;	/* Cannot redefine SimStruct (already defined as incomplete type) */
#endif



/*================================*
 * Function prototype for model.c *
 *================================*/
#ifndef MATLAB_MEX_FILE
# ifdef ANSI_FUNCTION_PROTOTYPES
    extern void MODEL_NAME(SimStruct *);
# else
    extern void MODEL_NAME();
# endif
#endif


/*===================================*
 * Function prototypes in simstruc.c *
 *===================================*/
#ifdef __STDC__

  extern SimStruct *ssCreateSimStruct(SimStruct *parentSS);
  extern int       ssInitSimStruct(SimStruct *S);
  extern void      ssInitSampleTimeTaskIDs(SimStruct *S);
  extern void      ssDestroySimStruct(SimStruct *S);
  extern void      ssIncrementT(SimStruct *S);
  extern void      ssSetGlobalT(SimStruct *S, double t);
  extern void      ssSetGlobalStepSize(SimStruct *S, double stepSize);
  extern void      ssUpdatePresentTimeEvents(SimStruct *S, int id);

#else

  extern SimStruct *ssCreateSimStruct();
  extern int       ssInitSimStruct();
  extern void      ssInitSampleTimeTaskIDs();
  extern void      ssDestroySimStruct();
  extern void      ssIncrementT();
  extern void      ssSetGlobalT();
  extern void      ssSetGlobalStepSize();
  extern void      ssUpdatePresentTimeEvents();

#endif



/*======================================*
 * SimStruct Get and Set Access methods *
 *======================================*/

/*-------------------------------- S->Version -------------------------------*/
#define ssGetVersion(S) \
          (S)->Version                                    /*   (double)      */
#define ssSetVersion(S,version) \
          (S)->Version = (version)
                     
/*-------------------------------- S->ModelName -----------------------------*/
#define ssGetModelName(S) \
          (S)->ModelName                                  /*   (char *)      */
#define ssSetModelName(S, modelName) \
          (S)->ModelName = (modelName)

/*-------------------------------- S->Parent --------------------------------*/
#define ssGetParentSS(S) \
          (S)->Parent                                     /*   (SimStruct *) */
#define ssSetParentSS(S,parent) \
          (S)->Parent = (parent)

/*-------------------------------- S->Root ----------------------------------*/
#define ssGetRootSS(S) \
          (S)->Root                                       /*   (SimStruct *) */
#define ssSetRootSS(S,root) \
          (S)->Root = (root)

/*-------------------------------- S->Sizes ---------------------------------*/
#define ssGetSizes(S) \
          (&(S)->Sizes[0])                                /*   (int *)       */

#define ssGetNumContStates(S) \
          (S)->Sizes[NumContStates_index]                 /*   (int)         */
#define ssGetNumDiscStates(S) \
          (S)->Sizes[NumDiscStates_index]                 /*   (int)         */
#define ssGetNumTotalStates(S) \
          (ssGetNumContStates(S) + ssGetNumDiscStates(S)) /*   (int)         */
#define ssGetNumOutputs(S) \
          (S)->Sizes[NumOutputs_index]                    /*   (int)         */
#define ssGetNumInputs(S) \
          (S)->Sizes[NumInputs_index]                     /*   (int)         */
#define ssGetReserved(S) \
          (S)->Sizes[Reserved_index]                      /*   (int)         */
#define ssIsDirectFeedThrough(S) \
          (S)->Sizes[DirFeedThru_index]                   /*   (int)         */
#define ssGetNumBlockIO(S) \
          (S)->Sizes[NumBlockIO_index]                    /*   (int)         */
#define ssGetNumBlockParams(S) \
          (S)->Sizes[NumBlockParams_index]                /*   (int)         */
#define ssGetChecksum(S) \
          (S)->Sizes[Checksum_index]                      /*   (int)         */
#define ssGetParamChecksum(S) \
          (S)->Sizes[Paramchecksum_index]                 /*   (int)         */
#define ssGetNumRWork(S) \
          (S)->Sizes[NumRWork_index]                      /*   (int)         */
#define ssGetNumIWork(S) \
          (S)->Sizes[NumIWork_index]                      /*   (int)         */
#define ssGetNumPWork(S) \
          (S)->Sizes[NumPWork_index]                      /*   (int)         */
#define ssGetNumInputArgs(S) \
          (S)->Sizes[NumInputArgs_index]                  /*   (int)         */
#define ssGetNumSampleTimes(S) \
          (S)->Sizes[NumSampleTimes_index]                /*   (int)         */
#define ssGetNumSFunctions(S) \
          (S)->Sizes[NumSFunctions_index]                 /*   (int)         */
#define ssGetNumScopes(S) \
          (S)->Sizes[NumScopes_index]                     /*   (int)         */
#define ssGetNumBlocks(S) \
          (S)->Sizes[NumBlocks_index]                     /*   (int)         */

#define ssSetNumContStates(S,numContStates) \
          (S)->Sizes[NumContStates_index]=(numContStates)
#define ssSetNumDiscStates(S,numDiscStates) \
          (S)->Sizes[NumDiscStates_index]=(numDiscStates)
#define ssSetNumOutputs(S,numOutputs) \
          (S)->Sizes[NumOutputs_index]=(numOutputs)
#define ssSetNumInputs(S,numInputs) \
          (S)->Sizes[NumInputs_index]=(numInputs)
#define ssSetReserved(S,reserved) \
          (S)->Sizes[Reserved_index]=(reserved)
#define ssSetDirectFeedThrough(S,dirFeedThru) \
          (S)->Sizes[DirFeedThru_index]=(dirFeedThru)
#define ssSetNumBlockIO(S,numBlockIO) \
          (S)->Sizes[NumBlockIO_index]=(numBlockIO)
#define ssSetNumBlockParams(S,numBlockParams) \
          (S)->Sizes[NumBlockParams_index]=(numBlockParams)
#define ssSetChecksum(S,checksum) \
          (S)->Sizes[Checksum_index]=(checksum)
#define ssSetParamChecksum(S,paramChecksum) \
          (S)->Sizes[Paramchecksum_index]=(paramChecksum)
#define ssSetNumRWork(S,numRWork) \
          (S)->Sizes[NumRWork_index]=(numRWork)
#define ssSetNumIWork(S,numIWork) \
          (S)->Sizes[NumIWork_index]=(numIWork)
#define ssSetNumPWork(S,numPWork) \
          (S)->Sizes[NumPWork_index]=(numPWork)
#define ssSetNumInputArgs(S,numInputArgs) \
          (S)->Sizes[NumInputArgs_index]=(numInputArgs)
#define ssSetNumSampleTimes(S,numSampleTimes) \
          (S)->Sizes[NumSampleTimes_index]=(numSampleTimes)
#define ssSetNumSFunctions(S,numSFuns) \
          (S)->Sizes[NumSFunctions_index] = (numSFuns)
#define ssSetNumScopes(S,numScopes) \
          (S)->Sizes[NumScopes_index] = (numScopes)
#define ssSetNumBlocks(S,numBlocks) \
          (S)->Sizes[NumBlocks_index] = (numBlocks)

/*-------------------------------- S->Inputs --------------------------------*/
#define ssGetNumArgs(S) \
          (S)->Inputs.NumArgs                             /*   (int)         */
#define ssGetArgPtr(S) \
          (S)->Inputs.Args                                /*   (Matrix **)   */
#define ssGetArg(S,argNum) \
          (S)->Inputs.Args[argNum]                        /*   (Matrix *)    */
#define ssSetNumArgs(S,numArgs) \
          (S)->Inputs.NumArgs = (numArgs)
#define ssSetArgPtr(S,args) \
          (S)->Inputs.Args = (args)
#define ssSetArg(S,argIdx,argMat) \
          (S)->Inputs.Args[argIdx] = (argMat)

/*-------------------------------- S->Vectors -------------------------------*/
#define ssGetRWork(S) \
          (S)->Vectors.RWork                              /*   (double *)    */
#define ssGetRWorkValue(S,rworkIdx) \
          (S)->Vectors.RWork[rworkIdx]                    /*   (double)      */
#define ssGetIWork(S) \
          (S)->Vectors.IWork                              /*   (int *)       */
#define ssGetIWorkValue(S,iworkIdx) \
          (S)->Vectors.IWork[iworkIdx]                    /*   (int)         */
#define ssGetPWork(S) \
          (S)->Vectors.PWork                              /*   (void **)     */
#define ssGetPWorkValue(S,pworkIdx) \
          (S)->Vectors.PWork[pworkIdx]                    /*   (void *)      */
#define ssGetBlockIO(S) \
          (S)->Vectors.BlockIO                            /*   (double *)    */
#define ssGetBlockIOValue(S,ioIdx) \
          (S)->Vectors.BlockIO[ioIdx]                     /*   (double)      */
#define ssGetBlockParam(S) \
          (S)->Vectors.BlockParam                         /*   (double *)    */
#define ssGetBlockParamValue(S,parmIdx) \
          (S)->Vectors.BlockParam[parmIdx]                /*   (double)      */
#define ssGetDefaultParam(S) \
          (S)->Vectors.DefaultParam                       /*   (double *)    */
#define ssGetDefaultParamValue(S,parmIdx) \
          (S)->Vectors.DefaultParam[parmIdx]              /*   (double)      */

#define ssSetRWork(S,rwork) \
          (S)->Vectors.RWork = (rwork)
#define ssSetRWorkValue(S,rworkIdx,rworkValue) \
          (S)->Vectors.RWork[rworkIdx] = (rworkValue)
#define ssSetIWork(S,iwork) \
          (S)->Vectors.IWork = (iwork)
#define ssSetIWorkValue(S,iworkIdx,iworkValue) \
          (S)->Vectors.IWork[iworkIdx] = (iworkValue)
#define ssSetPWork(S,pwork) \
          (S)->Vectors.PWork = (pwork)
#define ssSetPWorkValue(S,pworkIdx,pworkValue) \
          (S)->Vectors.PWork[pworkIdx] = (pworkValue)
#define ssSetBlockIO(S,io) \
          (S)->Vectors.BlockIO = (io)
#define ssSetBlockIOValue(S,ioIdx,ioValue) \
          (S)->Vectors.BlockIO[ioIdx] = (ioValue)
#define ssSetBlockParam(S,parmVector) \
          (S)->Vectors.BlockParam = (parmVector)
#define ssSetParamValue(S,parmIdx,parmValue) \
          (S)->Vectors.BlockParam[parmIdx] = (parmValue)
#define ssSetDefaultParam(S,parmVector) \
          (S)->Vectors.DefaultParam = (parmVector)
#define ssSetDefaultParamValue(S,parmIdx,parmValue) \
          (S)->Vectors.DefaultParam[parmIdx] = (parmValue)

/*-------------------------------- S->T -------------------------------------*/
#define ssGetT(S) \
          ssGetRootSS(S)->T                               /*   (double)      */
#define ssSetT(S,t) \
          ssGetRootSS(S)->T = (t)

/*-------------------------------- S->TFinal --------------------------------*/
#define ssGetTFinal(S) \
          ssGetRootSS(S)->TFinal                          /*   (double)      */
#define ssSetTFinal(S,tfinal) \
          ssGetRootSS(S)->TFinal = (tfinal)

/*-------------------------------- S->IntgStopTime --------------------------*/
#define ssGetIntgStopTime(S) \
          ssGetRootSS(S)->IntgStopTime                    /*   (double)      */
#define ssSetIntgStopTime(S,stoptime) \
          ssGetRootSS(S)->IntgStopTime = (stoptime)

/*-------------------------------- S->StepSize ------------------------------*/
#define ssGetStepSize(S) \
          ssGetRootSS(S)->StepSize                        /*   (double)      */
#define ssSetStepSize(S,stepSize) \
          ssGetRootSS(S)->StepSize=(stepSize)

/*-------------------------------- S->MinorTimeStepFlag ---------------------*/
#define ssSetMinorTimeStep(S,boolean) \
          ssGetRootSS(S)->MinorTimeStepFlag = (boolean)   /*   (int)         */

/*-------------------------------- S->Events --------------------------------*/
#define ssGetSampleTimeEventPtr(S) \
          (S)->Events.SampleTimes                         /*   (double *)    */
#define ssGetSampleTimeEvent(S,stNum) \
          (S)->Events.SampleTimes[stNum]                  /*   (double)      */
#define ssGetSampleTimeTaskIDPtr(S) \
          (S)->Events.SampleTimeTaskIDs                   /*   (int *)       */
#if TID_EQUALS_SAMPLE_TIME_INDEX
# define ssGetSampleTimeTaskID(S,stNum) \
          (stNum)                                         /*   (int)         */
#else
# define ssGetSampleTimeTaskID(S,stNum) \
          (S)->Events.SampleTimeTaskIDs[stNum]            /*   (int)         */
#endif
#define ssGetOffsetTimeEventPtr(S) \
          (S)->Events.OffsetTimes                         /*   (double *)    */
#define ssGetOffsetTimeEvent(S,offNum) \
          (S)->Events.OffsetTimes[offNum]                 /*   (double)      */
#define ssGetNextTimeEventPtr(S) \
          (S)->Events.NextTimes                           /*   (double *)    */
#define ssGetNextTimeEvent(S,offNum) \
          (S)->Events.NextTimes[offNum]                   /*   (double)      */
#define ssGetPresentTimeEventPtr(S) \
          (S)->Events.PresentTimes                        /*   (double *)    */
#define ssGetPresentTimeEvent(S,evtNum) \
          (S)->Events.PresentTimes[evtNum]                /*   (double)      */
#define ssGetSampleHitEventPtr(S) \
          (S)->Events.SampleHits                          /*   (int *)       */
#define ssGetCounterPtr(S) \
          (S)->Events.Counters                            /*   (int *)       */
#define ssGetCounter(S,evtNum) \
          (S)->Events.Counters[evtNum]                    /*   (int)         */
#define ssGetSampleCountPtr(S) \
          (S)->Events.SampleCount                         /*   (int *)       */
#define ssGetSampleCount(S,evtNum) \
          (S)->Events.SampleCount[evtNum]                 /*   (int)         */
#define ssGetOffsetCountPtr(S) \
          (S)->Events.OffsetCount                         /*   (int *)       */
#define ssGetOffsetCount(S,evtNum) \
          (S)->Events.OffsetCount[evtNum]                 /*   (int)         */
#define ssGetPerTaskSampleHitsPtr(S) \
          (S)->Events.PerTaskSampleHits                   /*   (int *)       */

#define ssSetSampleTimeEventPtr(S,events) \
          (S)->Events.SampleTimes = (events)
#define ssSetSampleTimeEvent(S,evtNum,event) \
          (S)->Events.SampleTimes[evtNum] = (event)
#define ssSetSampleTimeTaskIDPtr(S,tids) \
          (S)->Events.SampleTimeTaskIDs = (tids)
#define ssSetSampleTimeTaskID(S,stNum,tid) \
          (S)->Events.SampleTimeTaskIDs[stNum] = (tid)
#define ssSetOffsetTimeEventPtr(S,events) \
          (S)->Events.OffsetTimes = (events)
#define ssSetOffsetTimeEvent(S,evtNum,event) \
          (S)->Events.OffsetTimes[evtNum] = (event)
#define ssSetNextTimeEventPtr(S,events) \
          (S)->Events.NextTimes = (events)
#define ssSetNextTimeEvent(S,evtNum,event) \
          (S)->Events.NextTimes[evtNum] = (event)
#define ssSetPresentTimeEventPtr(S,events) \
          (S)->Events.PresentTimes = (events)
#define ssSetPresentTimeEvent(S,evtNum,event) \
          (S)->Events.PresentTimes[evtNum] = (event)
#define ssSetSampleHitEventPtr(S,events) \
          (S)->Events.SampleHits = (events)
#define ssSetSampleHitEvent(S,evtNum,event) \
          (S)->Events.SampleHits[evtNum] = (event)
#define ssSetCounterPtr(S,events) \
          (S)->Events.Counters = (events)
#define ssSetCounter(S,evtNum,event) \
          (S)->Events.Counters[evtNum] = (event)
#define ssSetSampleCountPtr(S,events) \
          (S)->Events.SampleCount = (events)
#define ssSetSampleCount(S,evtNum,event) \
          (S)->Events.SampleCount[evtNum] = (event)
#define ssSetOffsetCountPtr(S,events) \
          (S)->Events.OffsetCount = (events)
#define ssSetOffsetCount(S,evtNum,event) \
          (S)->Events.OffsetCount[evtNum] = (event)
#define ssSetPerTaskSampleHitsPtr(S, events) \
          (S)->Events.PerTaskSampleHits = (events)

/*-------------------------------- S->ModelMethods --------------------------*/
#define ssGetmdlInitializeSizes(S) \
          (S)->ModelMethods.mdlInitializeSizes            /*   (void(*)())   */
#define ssGetmdlInitializeSampleTimes(S) \
          (S)->ModelMethods.mdlInitializeSampleTimes      /*   (void(*)())   */
#define ssGetmdlInitializeConditions(S) \
          (S)->ModelMethods.mdlInitializeConditions       /*   (void(*)())   */
#define ssGetmdlOutputs(S) \
          (S)->ModelMethods.mdlOutputs                    /*   (void(*)())   */
#define ssGetmdlUpdate(S) \
          (S)->ModelMethods.mdlUpdate                     /*   (void(*)())   */
#define ssGetmdlDerivatives(S) \
          (S)->ModelMethods.mdlDerivatives                /*   (void(*)())   */
#define ssGetmdlTerminate(S) \
          (S)->ModelMethods.mdlTerminate                  /*   (void(*)())   */
#define ssGetmdlBlockInfo(S) \
          (S)->ModelMethods.mdlBlockInfo            /* (ModelBlockInfo(*)()) */
#define ssGetmdlScopeInfo(S) \
          (S)->ModelMethods.mdlScopeInfo            /* (ModelScopeInfo(*)()) */

#define ssSetmdlInitializeSizes(S,initSizes) \
          (S)->ModelMethods.mdlInitializeSizes = (initSizes)
#define ssSetmdlInitializeSampleTimes(S,initSampleTimes) \
          (S)->ModelMethods.mdlInitializeSampleTimes = \
            (initSampleTimes)
#define ssSetmdlInitializeConditions(S,initConds) \
          (S)->ModelMethods.mdlInitializeConditions = \
            (initConds)
#define ssSetmdlOutputs(S,outputs) \
          (S)->ModelMethods.mdlOutputs = (outputs)
#define ssSetmdlUpdate(S,update) \
          (S)->ModelMethods.mdlUpdate = (update)
#define ssSetmdlDerivatives(S,derivs) \
          (S)->ModelMethods.mdlDerivatives = (derivs)
#define ssSetmdlTerminate(S,housekeeping) \
          (S)->ModelMethods.mdlTerminate = (housekeeping)
#define ssSetmdlBlockInfo(S,blockInfo) \
          (S)->ModelMethods.mdlBlockInfo = (blockInfo)
#define ssSetmdlScopeInfo(S,scopeInfo) \
          (S)->ModelMethods.mdlScopeInfo = (scopeInfo)

/*-------------------------------- S->States --------------------------------*/
#define ssGetU(S) \
          (S)->States.U                                   /*   (double *)    */
#define ssGetY(S) \
          (S)->States.Y                                   /*   (double *)    */
#define ssGetX(S) \
          (S)->States.X                                   /*   (double *)    */
#define ssGetdX(S) \
          (S)->States.dX                                  /*   (double *)    */
#define ssGetScopes(S) \
          (S)->States.Scopes                              /*   (double *)    */
#define ssSetU(S,u) \
          (S)->States.U = (u)
#define ssSetY(S,y) \
          (S)->States.Y = (y)
#define ssSetX(S,x) \
          (S)->States.X = (x)
#define ssSetdX(S,dx) \
          (S)->States.dX = (dx)
#define ssSetScopes(S,scopes) \
          (S)->States.Scopes = (scopes)

/*-------------------------------- S->Utility -------------------------------*/
#define ssGetTempStore0(S) \
          (S)->Utility.TempStore0                         /*   (double *)    */
#define ssGetTempStore1(S) \
          (S)->Utility.TempStore1                         /*   (double *)    */
#define ssGetTempStore2(S) \
          (S)->Utility.TempStore2                         /*   (double *)    */
#define ssGetTempStore3(S) \
          (S)->Utility.TempStore3                         /*   (double *)    */
#define ssGetTempStore4(S) \
          (S)->Utility.TempStore4                         /*   (double *)    */
#define ssGetTempStore5(S) \
          (S)->Utility.TempStore5                         /*   (double *)    */
#define ssGetTempStore6(S) \
          (S)->Utility.TempStore6                         /*   (double *)    */
#define ssGetTempY(S) \
          (S)->Utility.TempY                              /*   (double *)    */
#define ssGetTempX(S) \
          (S)->Utility.TempX                              /*   (double *)    */
#define ssGetUserData(S) \
          (S)->Utility.UserData                           /*   (void *)      */

#define ssSetTempStore0(S,s0) \
          (S)->Utility.TempStore0 = (s0)
#define ssSetTempStore1(S,s1) \
          (S)->Utility.TempStore1 = (s1)
#define ssSetTempStore2(S,s2) \
          (S)->Utility.TempStore2 = (s2)
#define ssSetTempStore3(S,s3) \
          (S)->Utility.TempStore3 = (s3)
#define ssSetTempStore4(S,s4) \
          (S)->Utility.TempStore4 = (s4)
#define ssSetTempStore5(S,s5) \
          (S)->Utility.TempStore5 = (s5)
#define ssSetTempStore6(S,s6) \
          (S)->Utility.TempStore6 = (s6)
#define ssSetTempY(S,tempy) \
          (S)->Utility.TempY = (tempy)
#define ssSetTempX(S,tempx) \
          (S)->Utility.TempX = (tempx)
#define ssSetUserData(S,userData) \
          (S)->Utility.UserData = (userData)

/*-------------------------------- S->Utility -------------------------------*/
#define ssGetSFunctions(S) \
          (S)->SFunctions                               /* (SimStruct **)    */
#define ssGetSFunction(S,sfun) \
          ((S)->SFunctions[sfun])                       /* (SimStruct *)     */

#define ssSetSFunctions(S,SFunPtr) \
          (S)->SFunctions = (SFunPtr)
#define ssSetSFunction(S,sfunid,simStruc) \
          (S)->SFunctions[sfunid] = (simStruc)



/*===========================================================================*
 * SimStruct Is access methods and multitasking dependent Set access methods * 
 *===========================================================================*/
#define ssIsContinuousTask(S,id) \
          (1)

#define ssIsSampleHitEvent(S,evtNum,id) \
          (!ssIsMinorTimeStep(S) && (S)->Events.SampleHits[evtNum])

#define ssSetSampleHitEventInTask(S,evtNum,task,event)
          /* noop for non-multitasking case */

#define ssIsSpecialSampleHitEvent(S,evtNum,task,tid) \
          ssIsSampleHitEvent(S, evtNum, tid)

#define ssIsMinorTimeStep(S) \
          ssGetRootSS(S)->MinorTimeStepFlag



#ifndef MATLAB_MEX_FILE

# undef  ssIsSampleHitEvent
# define ssIsSampleHitEvent(S,evtNum,id) \
          (!ssIsMinorTimeStep(S) && \
	   ssGetRootSS(S)->Events.SampleHits[ssGetSampleTimeTaskID(S,evtNum)])

# ifdef MULTITASKING

#  undef  ssIsContinuousTask
#  define ssIsContinuousTask(S,id)                 ((id) == 0)

   /* note ssSetSampleHitEventInTask is used with only the root SimStruct */
#  undef  ssSetSampleHitEventInTask
#  define ssSetSampleHitEventInTask(S, evtNum, task, event) \
	    (S)->Events.PerTaskSampleHits[(evtNum) + \
              ((task) * (ssGetNumSampleTimes(S)))] = (event)

#  define ssIsSampleHitEventInTask(S, evtNum, id) \
	    ssGetRootSS(S)->Events.PerTaskSampleHits[ \
	      ssGetSampleTimeTaskID(S,evtNum) + \
                ((id) * (ssGetNumSampleTimes(ssGetRootSS(S))))]

#  undef  ssIsSpecialSampleHitEvent
#  define ssIsSpecialSampleHitEvent(S, evtNum, task, id) \
	    (ssGetSampleTimeTaskID(S, task) == (id)) && \
              !ssIsMinorTimeStep(S) && \
 	        ssIsSampleHitEventInTask(S, evtNum, id)

#  if defined_SIMULINK_NAME || defined_S_FUNCTION_NAME
     /* Only redefine for model itself or S-functions */
#   undef  ssIsSampleHitEvent
#   define ssIsSampleHitEvent(S, evtNum, id) \
             (ssGetSampleTimeTaskID(S,evtNum) == (id))
#  endif

# endif	/* MULTITASKING */
#endif /* !MATLAB_MEX_FILE */



/*=================================*
 * SimStruct "Call" Access methods *
 *=================================*/
#define ssCallmdlInitializeSizes(S) \
          (*ssGetmdlInitializeSizes(S))(S)

#define ssCallmdlInitializeSampleTimes(S) \
          (*ssGetmdlInitializeSampleTimes(S))(S)

#define ssCallmdlInitializeConditions(x,S) \
          (*ssGetmdlInitializeConditions(S))(x,S)

#define ssCallmdlOutputs(y,x,u,S,id) \
          (*ssGetmdlOutputs(S))(y,x,u,S,id)

#define ssCallmdlUpdate(x,u,S,id) \
          (*ssGetmdlUpdate(S))(x,u,S,id); \
  	  ssUpdatePresentTimeEvents(S,id)

#define ssCallmdlDerivatives(dx,x,u,S,id) \
          (*ssGetmdlDerivatives(S))(dx,x,u,S,id)

#define ssCallmdlTerminate(S) \
          (*ssGetmdlTerminate(S))(S)

#define ssCallmdlBlockInfo(S) \
          ((ssGetmdlBlockInfo(S)) ? (*ssGetmdlBlockInfo(S))() : \
                                    (ModelBlockInfo *) 0)

#define ssCallmdlScopeInfo(S) \
          ((ssGetmdlScopeInfo(S)) ? (*ssGetmdlScopeInfo(S))() : \
                                    (ModelScopeInfo *) 0)



/*===========================================================================*
 * SimStruct "S-Function" Access methods (dependent upon whether or not we   *
 * are building a MEX file).                                                 *
 *===========================================================================*/
#ifndef MATLAB_MEX_FILE

  /*
   * Macros are used to call an S-function block from the generated C code
   */

# define sfcnInitializeConditions(x0, s, bid) \
           ssCallmdlInitializeConditions(x0, s)

# define sfcnOutputs(y, x, u, s, tid, bid) \
           ssCallmdlOutputs(y, x, u, s, tid)

# define sfcnUpdate(x, u, s, tid, bid) \
           ssCallmdlUpdate(x, u, s, tid)

# define sfcnDerivatives(dx, x, u, s, tid, bid) \
           ssCallmdlDerivatives(dx, x, u, s, tid)

# define sfcnTerminate(s, bid) \
           ssCallmdlTerminate(s)

# define sfcnInitializeConditionsWithCopy(x0c, x0d, s, bid) \
           ssCallmdlInitializeConditions(ssGetX(s), s); \
	   memcpy(x0c,ssGetX(s),ssGetNumContStates(s)*sizeof(double)); \
	   memcpy(x0d,ssGetX(s)+ssGetNumContStates(s), \
                  ssGetNumDiscStates(s)*sizeof(double))

# define sfcnOutputsWithCopy(y, xc, xd, u, s, tid, bid) \
	   memcpy(ssGetX(s),xc,ssGetNumContStates(s)*sizeof(double)); \
	   memcpy(ssGetX(s)+ssGetNumContStates(s),xd,\
                  ssGetNumDiscStates(s)*sizeof(double)); \
	   ssCallmdlOutputs(y, ssGetX(s), u, s, tid)

# define sfcnUpdateWithCopy(xc, xd, u, s, tid, bid) \
	   memcpy(ssGetX(s),xc,ssGetNumContStates(s)*sizeof(double)); \
	   memcpy(ssGetX(s)+ssGetNumContStates(s),xd,\
                  ssGetNumDiscStates(s)*sizeof(double)); \
	   ssCallmdlUpdate(ssGetX(s), u, s, tid); \
	   memcpy(xc,ssGetX(s),ssGetNumContStates(s)*sizeof(double)); \
	   memcpy(xd,ssGetX(s)+ssGetNumContStates(s),\
                  ssGetNumDiscStates(s)*sizeof(double))

# define sfcnDerivativesWithCopy(dx, xc, xd, u, s, tid, bid) \
	   memcpy(ssGetX(s),xc,ssGetNumContStates(s)*sizeof(double)); \
	   memcpy(ssGetX(s)+ssGetNumContStates(s),xd,\
                  ssGetNumDiscStates(s)*sizeof(double)); \
	   ssCallmdlDerivatives(dx, ssGetX(s), u, s, tid)

# define sfcnUpdateWithOutputCall(x, u, y, s, tid, bid) \
	   ssCallmdlOutputs(y, x, u, s, tid); \
	   ssCallmdlUpdate(x, u, s, tid)

# define sfcnDerivativesWithOutputCall(dx, x, u, y, s, tid, bid) \
	   ssCallmdlOutputs(y, x, u, s, tid); \
	   ssCallmdlDerivatives(dx, x, u, s, tid)

# define sfcnUpdateWithCopyAndOutputCall(xc, xd, u, y, s, tid, bid) \
	   memcpy(ssGetX(s),xc,ssGetNumContStates(s)*sizeof(double)); \
	   memcpy(ssGetX(s)+ssGetNumContStates(s),xd,\
                  ssGetNumDiscStates(s)*sizeof(double)); \
	   ssCallmdlOutputs(y, ssGetX(s), u, s, tid); \
	   ssCallmdlUpdate(ssGetX(s), u, s, tid); \
	   memcpy(xc,ssGetX(s),ssGetNumContStates(s)*sizeof(double)); \
	   memcpy(xd,ssGetX(s)+ssGetNumContStates(s),\
                  ssGetNumDiscStates(s)*sizeof(double))

# define sfcnDerivativesWithCopyAndOutputCall(dx, xc, xd, u, y, s, tid, bid) \
	   memcpy(ssGetX(s),xc,ssGetNumContStates(s)*sizeof(double)); \
	   memcpy(ssGetX(s)+ssGetNumContStates(s),xd,\
                  ssGetNumDiscStates(s)*sizeof(double)); \
  	   ssCallmdlOutputs(y, ssGetX(s), u, s, tid); \
	   ssCallmdlDerivatives(dx, ssGetX(s), u, s, tid)

#else  /* !MATLAB_MEX_FILE */

  /*
   * Macros are used to update an S-function block when running as an
   * accelerated model
   */

# define FLAG_SIZES       0
# define FLAG_DERIVATIVES 1
# define FLAG_UPDATE      2
# define FLAG_OUTPUT      3
# define FLAG_TERMINATE   9

# define sfcnInitializeConditions(x0, s, blockIndex) \
	   mexEvaluateBlock(SIMULINK_NAME, blockIndex, FLAG_SIZES)

# define sfcnOutputs(y, x, u, s, tid, blockIndex) \
	   mexEvaluateBlock(SIMULINK_NAME, blockIndex, FLAG_OUTPUT)

# define sfcnUpdate(x, u, s, tid, blockIndex) \
	   mexEvaluateBlock(SIMULINK_NAME, blockIndex, FLAG_UPDATE)

# define sfcnDerivatives(dx, x, u, s, tid, blockIndex) \
	   mexEvaluateBlock(SIMULINK_NAME, blockIndex, FLAG_DERIVATIVES)

# define sfcnTerminate(s, blockIndex) \
	   mexEvaluateBlock(SIMULINK_NAME, blockIndex, FLAG_TERMINATE)

# define sfcnInitializeConditionsWithCopy(x0c, x0d, s, blockIndex) \
	   mexEvaluateBlock(SIMULINK_NAME, blockIndex, FLAG_SIZES)

# define sfcnOutputsWithCopy(y, xc, xd, u, s, tid, blockIndex) \
	   mexEvaluateBlock(SIMULINK_NAME, blockIndex, FLAG_OUTPUT)

# define sfcnUpdateWithCopy(xc, xd, u, s, tid, blockIndex) \
	   mexEvaluateBlock(SIMULINK_NAME, blockIndex, FLAG_UPDATE)

# define sfcnDerivativesWithCopy(dx, xc, xd, u, s, tid, blockIndex) \
	   mexEvaluateBlock(SIMULINK_NAME, blockIndex, FLAG_DERIVATIVES)

# define sfcnTerminate(s, blockIndex) \
	   mexEvaluateBlock(SIMULINK_NAME, blockIndex, FLAG_TERMINATE)

# define sfcnUpdateWithOutputCall(x, u, y, s, tid, blockIndex) \
	   mexEvaluateBlock(SIMULINK_NAME, blockIndex, FLAG_UPDATE)

# define sfcnDerivativesWithOutputCall(dx, x, u, y, s, tid, blockIndex) \
	   mexEvaluateBlock(SIMULINK_NAME, blockIndex, FLAG_DERIVATIVES)

# define sfcnUpdateWithCopyAndOutputCall(xc, xd, u, y, s, tid, blockIndex) \
	   mexEvaluateBlock(SIMULINK_NAME, blockIndex, FLAG_UPDATE)

# define sfcnDerivativesWithCopyAndOutputCall(dx,xc,xd,u,y,s,tid,blockIndex) \
	   mexEvaluateBlock(SIMULINK_NAME, blockIndex, FLAG_DERIVATIVES)

#endif /* !MATLAB_MEX_FILE */



#endif	/* __SIMSTRUC__ */

/* EOF: simstruc.h */
