/*
 * SMTRNSR   A SIMULINK real matrix transpose block.
 *
 *           Syntax:  [sys, x0] = sbuffer(t,x,u,flag,Asize)
 *
 *  Copyright 1995-2000 The MathWorks, Inc.
 *  $Revision: 1.12 $  $Date: 2000/06/14 14:28:01 $
 */

#define S_FUNCTION_NAME smtrnsr

#include "dsp_sim.h"

/*
 * Defines for easy access of the input parameters
 */
#define NUM_ARGS 1
#define ASIZE	 ssGetArg(S,0)

#ifdef MATLAB_MEX_FILE
#define MDL_CHECK_PARAMETERS
static void mdlCheckParameters(SimStruct *S) {
    const char *msg = NULL;

    if ((mxGetM(ASIZE) != 1) || (mxGetN(ASIZE) != 2)) {
        msg  = "The matrix size must be a 2-element row vector.";
        goto ERROR_EXIT;
    }

ERROR_EXIT:
    if (msg != NULL) {
        ssSetErrorStatus(S,msg);
    }
}
#endif


static void mdlInitializeSizes(SimStruct *S)
{
    int Aele;

    ssSetNumSFcnParams(S, NUM_ARGS);

#if defined(MATLAB_MEX_FILE)
    if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) {
        mdlCheckParameters(S);
        if (ssGetErrorStatus(S) != NULL) {
            return;
        }
    } else {
        return; /* Simulink will report a parameter mismatch error */
    }
#endif

    Aele = mxGetPr(ASIZE)[0] * mxGetPr(ASIZE)[1];

    ssSetNumContStates(    S, 0);
    ssSetNumDiscStates(    S, 0);
    ssSetNumInputs(        S, Aele);
    ssSetNumOutputs(       S, Aele);
    ssSetDirectFeedThrough(S, 1);
    ssSetNumSampleTimes(   S, 1);
    ssSetNumRWork(         S, 0);
    ssSetNumIWork(         S, 0);
    ssSetNumPWork(         S, 0);
    ssSetNumModes(         S, 0);
    ssSetNumNonsampledZCs( S, 0);
    ssSetOptions(          S, SS_OPTION_EXCEPTION_FREE_CODE);
}


static void mdlInitializeSampleTimes(SimStruct *S)
{
    /*
     * Note, blocks that are continuous in nature should have a single
     * sample time of 0.0
     */
    ssSetSampleTimeEvent(S, 0, INHERITED_SAMPLE_TIME);
    ssSetOffsetTimeEvent(S, 0, 0.0);
}


static void mdlInitializeConditions(real_T *x0, SimStruct *S)
{
#ifdef MATLAB_MEX_FILE
    if(ssGetNumInputs(S) != mxGetPr(ASIZE)[0] * mxGetPr(ASIZE)[1]) {
        ssSetErrorStatus(S, "Size of input is not consistent with block parameter.");
        return;
    }
#endif
}


static void mdlOutputs(real_T *y, const real_T *x, const real_T *u, 
                       SimStruct *S, int_T tid)
{
  /* Inputs are u, Outputs are y */
  int ii = *mxGetPr(ASIZE);     /* Arows */
  int jj = *(mxGetPr(ASIZE)+1); /* Acols */
  int i  = ii;

  /* Transpose matrix: */
  while(i-- != 0) {
    const real_T *uu = u++;
    int          j   = jj;
    while(j-- != 0) {
      *y++ = *uu;
      uu += ii;
    }
  }
}


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
