/*
 * SDSPDOTP S-Function to compute dot product (multiply-accumulate)
 *
 *  D. Orofino, 12-97
 *  Copyright (c) 1995-98 by The MathWorks, Inc.
 *  $Revision: 1.3 $  $Date: 2000/01/25 00:13:41 $
 */

#define S_FUNCTION_NAME sdspdotp
#define S_FUNCTION_LEVEL 2

#include "simstruc.h"

#define NUM_PARAMS (0)


static void mdlInitializeSizes(SimStruct *S)
{
    ssSetNumSFcnParams(S,  NUM_PARAMS);
    if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) return;

   /* Inputs: */
    if (!ssSetNumInputPorts(S, 2)) return;
    ssSetInputPortWidth(S, 0, DYNAMICALLY_SIZED);
    ssSetInputPortWidth(S, 1, DYNAMICALLY_SIZED);
    ssSetInputPortDirectFeedThrough(S, 0, 1);
    ssSetInputPortDirectFeedThrough(S, 1, 1);

    /* Outputs: */
    if (!ssSetNumOutputPorts(S,1)) return;
    ssSetOutputPortWidth(S, 0, 1);

    ssSetNumSampleTimes(S, 1);
    ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE |
                 SS_OPTION_USE_TLC_WITH_ACCELERATOR);
}


static void mdlInitializeSampleTimes(SimStruct *S)
{
    ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
    ssSetOffsetTime(S, 0, 0.0);
}


static void mdlOutputs(SimStruct *S, int_T tid)
{
	/* 
	 * Compute dot-product for real input data
	 */
	real_T s = 0.0;  /* sum */

	/* Multiply-accumulate: */
	{
	    InputRealPtrsType uptr = ssGetInputPortRealSignalPtrs(S,0);
	    InputRealPtrsType vptr = ssGetInputPortRealSignalPtrs(S,1);
	    int_T             N    = ssGetInputPortWidth(S,0);

	    while(N-- > 0) {
		s += **uptr++ * **vptr++;
	    }
	}

	/* Write result: */
	{
	    real_T *y = ssGetOutputPortRealSignal(S,0);
	    *y = s;
	}
}


static void mdlTerminate(SimStruct *S)
{
}


static void CheckandSetPorts(
    SimStruct *S,
    int_T      port,
    int_T      PortWidth
) {
    static char_T *in_err  = "Input ports must have identical widths";

    int_T w[2];  /* port widths, [input0 input1] */

    ssSetInputPortWidth(S,port,PortWidth);

    w[0] = ssGetInputPortWidth(S,0);
    w[1] = ssGetInputPortWidth(S,1);

    if (w[0] != -1) {
        /* Input port 0 known - copy input port width: */
        ssSetInputPortWidth(S, 1, w[0]);
        return;
    } else {
        /* Input port 1 known - copy input port width: */
        ssSetInputPortWidth(S, 0, w[1]);
    }
}

#if defined(MATLAB_MEX_FILE)
# define MDL_SET_INPUT_PORT_WIDTH
 static void mdlSetInputPortWidth(SimStruct *S, int_T port,
                                    int_T inputPortWidth)
{
    CheckandSetPorts(S,port,inputPortWidth);
}

# define MDL_SET_OUTPUT_PORT_WIDTH
static void mdlSetOutputPortWidth(SimStruct *S, int_T port,
                                     int_T outputPortWidth)
{
    /* ssSetOutputPortWidth(S,port,PortWidth); */

    /* This should never occur! */
    ssSetErrorStatus(S, "Error setting output port width.");
}
#endif


#ifdef	MATLAB_MEX_FILE  
#include "simulink.c"    
#else
#include "cg_sfun.h"     
#endif
