%% $RCSfile: smatrxcat.ttlc,v $ %% File : smatrxcat.tlc generated from smatrxcat.ttlc revsion 1.3 %% $Date: 2000/08/09 14:48:37 $ %% %% Steve Conahan %% Copyright 1990-2000 The MathWorks, Inc. %% %% Abstract: Matrix Concatenation %% %implements smatrxcat "C" %% Function: BlockInstanceSetup =============================================== %% %% Abstract: %% Rename the S-Function parameters for easy reference. %% %function BlockInstanceSetup(block, system) void %% %assign OUTPORT = 0 %assign OUT_COMPLEX = LibBlockOutputSignalIsComplex(OUTPORT) %% This gives the real data type name, no matter if input is real or complex: %assign OUT_DTYPE_NAME = ... LibBlockOutputSignalDataTypeName(OUTPORT,"%") %% %assign HORIZONTAL = 1 %assign CAT_METHOD = SFcnParamSettings.CatMethod %% %if (CAT_METHOD == HORIZONTAL) %% Number of ROWS is constant for all input and output ports %assign outDims = LibBlockOutputSignalDimensions(OUTPORT) %assign CONST_HORIZROWS_OR_VERTCOLS = outDims[0] %else %% Number of COLUMNS is constant for all input and output ports %assign numOutDims = LibBlockOutputSignalNumDimensions(OUTPORT) %assign outDims = LibBlockOutputSignalDimensions(OUTPORT) %assign CONST_HORIZROWS_OR_VERTCOLS = (numOutDims == 2) ? outDims[1] : 1 %endif %% (CAT_METHOD == HORIZONTAL) %% %% If the output is complex, determine if ALL inputs are complex %% (for code generation optimizations). %% %if OUT_COMPLEX %assign realInputDetected = 0 %foreach inpCnt = NumDataInputPorts %assign realInputDetected = ... realInputDetected || ( !LibBlockInputSignalIsComplex(inpCnt) ) %endforeach %else %assign realInputDetected = 1 %endif %% OUT_COMPLEX %% %if realInputDetected %assign ALL_INPUTS_COMPLEX = 0 %else %assign ALL_INPUTS_COMPLEX = 1 %endif %% realInputDetected %% %% NOTE: The following only works for SL built-in types %% (i.e. not for custom types) %assign outDtypeId = LibBlockOutputSignalDataTypeId(OUTPORT) %assign numBytesPerRealElmt = SLibGetDataTypeSizeFromId(outDtypeId) %assign numBytesPerCplxElmt = 2 * numBytesPerRealElmt %% %assign block = block + OUTPORT + OUT_COMPLEX + OUT_DTYPE_NAME + ... outDims + numBytesPerRealElmt + numBytesPerCplxElmt %assign block = block + HORIZONTAL + CAT_METHOD %assign block = block + CONST_HORIZROWS_OR_VERTCOLS + ALL_INPUTS_COMPLEX %endfunction %% BlockInstanceSetup %% Function: Outputs ========================================================== %% %function Outputs(block, system) Output %% /* * Matrix Concatenation: % %if (NumDataInputPorts > 1) %if (CAT_METHOD == HORIZONTAL) % %else % %endif %% (CAT_METHOD == HORIZONTAL) %else % %endif %% (NumDataInputPorts > 1) %endfunction %% Outputs %% Function: GenerateCopyCode ============================================= %% %function GenerateCopyCode(block) Output %% %% One input port - check and see if we share I/O or not %% %assign in_place = (LibBlockInputSignalBufferDstPort(0) == OUTPORT) %% %if in_place %% NOTE this comment begins at the very start of the Outputs function %% (i.e. "/* Matrix Concatenation...") * No code required: input port and output port buffers shared. */ %else %if OUT_COMPLEX %% NOTE this comment begins at the very start of the Outputs function %% (i.e. "/* Matrix Concatenation...") * One input, complex, data type: %. */ %assign numBytesPerInputMatrix = ... LibBlockInputSignalWidth(0) * numBytesPerCplxElmt %else %% NOTE this comment begins at the very start of the Outputs function %% (i.e. "/* Matrix Concatenation...") * One input, real, data type: %. */ %assign numBytesPerInputMatrix = ... LibBlockInputSignalWidth(0) * numBytesPerRealElmt %endif %% OUT_COMPLEX %% %assign y = LibBlockOutputSignalAddr(OUTPORT, "", "", 0) %assign u = LibBlockInputSignalAddr(0,"","",0) (void) memcpy( (byte_T *)%, (byte_T *)%, % ); ... /* [%x%] */ %% %endif %% in_place %endfunction %% GenerateCopyCode %% Function: GenerateHorizCatCode ============================================= %% %function GenerateHorizCatCode(block) Output %% %% There are two cases to consider: %% %% Easy case (all inputs same complexity) -> %% Render a bunch of memcpy statements (no loops required). %% %% Mixed case (some inputs real, some inputs complex) -> %% Render a combination of either memcpy %% statements, or loops based on input port complexity. Worst case %% for N-1 ports real and 1 port complex is that we render %% N-1 for-loops. Must check each input complexity as we go. %% %if !OUT_COMPLEX || ALL_INPUTS_COMPLEX % %else % %endif %endfunction %% GenerateHorizCatCode %% Function: GenerateVertCatCode ============================================== %% %function GenerateVertCatCode(block) Output %% %% Vertical Concatenation: %% %% There are two cases to consider: %% %% Easier case -> All inputs same complexity. %% Mixed case -> Some inputs real, some inputs complex. %% %if !OUT_COMPLEX || ALL_INPUTS_COMPLEX % %else % %endif %endfunction %% GenerateVertCatCode %% Function: GenHorizCatSameComplexity ======================================== %% %function GenHorizCatSameComplexity(block) Output %if OUT_COMPLEX %% NOTE this comment begins at the very start of the Outputs function %% (i.e. "/* Matrix Concatenation...") * Horizontal matrix concatenation, * % inputs, complex, data type: %. */ %assign numBytesPerElmt = numBytesPerCplxElmt %else %% NOTE this comment begins at the very start of the Outputs function %% (i.e. "/* Matrix Concatenation...") * Horizontal matrix concatenation, * % inputs, real, data type: %. */ %assign numBytesPerElmt = numBytesPerRealElmt %endif %% OUT_COMPLEX %% %assign byteCount = 0 %assign y = LibBlockOutputSignalAddr(OUTPORT, "", "", 0) %foreach portNum = NumDataInputPorts %assign numBytesPerInputMatrix = ... LibBlockInputSignalWidth(portNum) * numBytesPerElmt %assign inDims = LibBlockInputSignalDimensions(portNum) %assign colDim = LibBlockInputSignalWidth(portNum) / inDims[0] %% Note: in the unoriented input case, can't use inDims[1] %% to determine number of columns %assign u = LibBlockInputSignalAddr(portNum, "", "",0) %assign comment = "/* Input %: [%x%] */" %if (byteCount > 0) (void) memcpy( ((byte_T *)(%)) + %, (byte_T *)%, % ); % %else (void) memcpy( ((byte_T *)(%)), (byte_T *)%, % ); % %endif %assign byteCount = byteCount + numBytesPerInputMatrix %endforeach %endfunction %% GenHorizCatSameComplexity %% Function: GenHorizCatDifferentComplexity =================================== %% %function GenHorizCatDifferentComplexity(block) Output %% NOTE this comment begins at the very start of the Outputs function %% (i.e. "/* Matrix Concatenation...") * Horizontal matrix concatenation, * % inputs, real and complex, data type: %. */ %assign dTypeId = LibBlockOutputSignalDataTypeId(0) %assign zero = SLibGetFormattedValueFromId(dTypeId, 0) %assign outByteCount = 0 %foreach portNum = NumDataInputPorts %assign y = LibBlockOutputSignalAddr(OUTPORT, "", "", 0) %assign u = LibBlockInputSignalAddr(portNum, "", "",0) %if LibBlockInputSignalIsComplex(portNum) %% %% Complex input, complex output %% %assign numBytesPerInputMatrix = ... LibBlockInputSignalWidth(portNum) * numBytesPerCplxElmt %assign inDims = LibBlockInputSignalDimensions(portNum) %assign colDim = LibBlockInputSignalWidth(portNum) / inDims[0] %% %% Note: in the unoriented input case, can't use inDims[1] %% to determine number of columns %assign dimStr = "[%x%]" /* Input %: [%x%], complex */ %if (outByteCount > 0) (void) memcpy( ((byte_T *)(%)) + %, (byte_T *)%, % ); %else (void) memcpy( (byte_T *)%, (byte_T *)%, % ); %endif %% %assign outByteCount = outByteCount + numBytesPerInputMatrix %% %else %% %% Real input, complex output %% %% Note: in the unoriented input case, can't use inDims[1] %% to determine number of columns %assign inDims = LibBlockInputSignalDimensions(portNum) %assign colDim = LibBlockInputSignalWidth(portNum) / inDims[0] /* Input %: [%x%], real */ { %if (LibBlockInputSignalWidth(portNum) > 1) int_T cnt; for ( cnt = 0; cnt < %; cnt++ ) { /* * Copy real input sample bytes to real part of output, * zeroize imaginary part */ %if (outByteCount > 0) (void) memcpy( ((byte_T *)(%)) ... + (cnt * %) + %, ((byte_T *)(%)) + ... (cnt * %), % ); %% NOTE: The following only works for SL built-in types %% (i.e. not for custom types) %if ((dTypeId == tSS_DOUBLE) || (dTypeId == tSS_SINGLE)) *(% *)(((char *) %) ... + (cnt * %) ... + %) = %; %else (void) memset( ((byte_T *)(%)) ... + (cnt * %) ... + %, ... 0, % ); %endif %else (void) memcpy( ((byte_T *)(%)) ... + (cnt * %), ((byte_T *)(%)) ... + (cnt * %), % ); %% NOTE: The following only works for SL built-in types %% (i.e. not for custom types) %if ((dTypeId == tSS_DOUBLE) || (dTypeId == tSS_SINGLE)) *(% *)(((char *)%) ... + (cnt * %) + %) ... = %; %else (void) memset( ((byte_T *)(%)) ... + (cnt * %) + %, ... 0, % ); %endif %endif } /* end cnt */ %% Increment output bytes for next element %assign outByteCount = outByteCount + ... (numBytesPerCplxElmt * LibBlockInputSignalWidth(portNum)) %else /* * Copy real input sample bytes to real part of output, * zeroize imaginary part */ %if (outByteCount > 0) (void) memcpy( ((byte_T *)(%)) + %, (byte_T *)%, % ); %% NOTE: The following only works for SL built-in types %% (i.e. not for custom types) %if ((dTypeId == tSS_DOUBLE) || (dTypeId == tSS_SINGLE)) *(% *)(((char *)%) ... + % + %) ... = %; %else (void) memset( ((byte_T *)(%)) + % ... + %, ... 0, % ); %endif %% Increment output bytes for next element %assign outByteCount = outByteCount + numBytesPerCplxElmt %else (void) memcpy( (byte_T *)%, (byte_T *)%, % ); %% NOTE: The following only works for SL built-in types %% (i.e. not for custom types) %if ((dTypeId == tSS_DOUBLE) || (dTypeId == tSS_SINGLE)) *(% *)(((char *)%) ... + %) = %; %else (void) memset( ((byte_T *)(%)) + %, ... 0, % ); %endif %% Increment output bytes for next element %assign outByteCount = outByteCount + numBytesPerCplxElmt %endif %endif %% (LibBlockInputSignalWidth(portNum) > 1) } %endif %% complex vs. real input %endforeach %% portNum %endfunction %% GenHorizCatDifferentComplexity %% Function: GenVertCatSameComplexity ======================================== %% %function GenVertCatSameComplexity(block) Output %if OUT_COMPLEX %% NOTE this comment begins at the very start of the Outputs function %% (i.e. "/* Matrix Concatenation...") * Vertical matrix concatenation, * % inputs, complex, data type: %. */ %assign numBytesPerElmt = numBytesPerCplxElmt %else %% NOTE this comment begins at the very start of the Outputs function %% (i.e. "/* Matrix Concatenation...") * Vertical matrix concatenation, * % inputs, real, data type: %. */ %assign numBytesPerElmt = numBytesPerRealElmt %endif %% OUT_COMPLEX { %assign byteCount = 0 %assign y = LibBlockOutputSignalAddr(OUTPORT, "", "", 0) %if (CONST_HORIZROWS_OR_VERTCOLS > 1) const int_T nCols = %; int_T colNum; for ( colNum = 0; colNum < nCols; colNum++ ) { %% %% Calculate total number of bytes per output column for use below %assign totNumOutColBytes = 0 %foreach portNum = NumDataInputPorts %assign inDims = LibBlockInputSignalDimensions(portNum) %assign colBytes = inDims[0] * numBytesPerElmt %assign totNumOutColBytes = totNumOutColBytes + colBytes %endforeach %% NumDataInputPorts %% %foreach portNum = NumDataInputPorts %assign u = LibBlockInputSignalAddr(portNum, "", "",0) %assign inDims = LibBlockInputSignalDimensions(portNum) %assign colDim = LibBlockInputSignalWidth(portNum) / inDims[0] %assign colBytes = inDims[0] * numBytesPerElmt %assign dimStr = "[%x%], % bytes per col" %assign comment = "/* Input %: % */" %if (CONST_HORIZROWS_OR_VERTCOLS > 1) %if (byteCount > 0) (void) memcpy( ((byte_T *)(%)) ... + (colNum * %) + %, ((byte_T *)(%)) ... + (colNum * %), % ); % %else (void) memcpy( ((byte_T *)(%)) ... + (colNum * %), ((byte_T *)(%)) ... + (colNum * %), % ); % %endif %else %if (byteCount > 0) (void) memcpy( ((byte_T *)(%)) ... + (colNum * %) + %, (byte_T *)(%), % ); % %else (void) memcpy( ((byte_T *)(%)) ... + (colNum * %), (byte_T *)(%), % ); % %endif %endif %% (CONST_HORIZROWS_OR_VERTCOLS > 1) %assign byteCount = byteCount + colBytes %endforeach %% input port number } %else %foreach portNum = NumDataInputPorts %assign u = LibBlockInputSignalAddr(portNum, "", "",0) %assign inDims = LibBlockInputSignalDimensions(portNum) %assign colDim = LibBlockInputSignalWidth(portNum) / inDims[0] %assign colBytes = inDims[0] * numBytesPerElmt %assign dimStr = "[%x%], % bytes per col" %assign comment = "/* Input %: % */" %if (CONST_HORIZROWS_OR_VERTCOLS > 1) %if (byteCount > 0) (void) memcpy( ((byte_T *)(%)) + %, ((byte_T *)(%)) ... + (colNum * %), % ); % %else (void) memcpy( (byte_T *)(%), ((byte_T *)(%)) ... + (colNum * %), % ); % %endif %else %if (byteCount > 0) (void) memcpy( ((byte_T *)(%)) + %, (byte_T *)(%), % ); % %else (void) memcpy( (byte_T *)(%), (byte_T *)(%), % ); % %endif %endif %% (CONST_HORIZROWS_OR_VERTCOLS > 1) %assign byteCount = byteCount + colBytes %endforeach %% input port number %endif %% (CONST_HORIZROWS_OR_VERTCOLS > 1) } %endfunction %% GenVertCatSameComplexity %% Function: GenVertCatDifferentComplexity ==================================== %% %function GenVertCatDifferentComplexity(block) Output %% NOTE this comment begins at the very start of the Outputs function %% (i.e. "/* Matrix Concatenation...") * Vertical matrix concatenation, * % inputs, real and complex, data type: %. */ %assign dTypeId = LibBlockOutputSignalDataTypeId(0) %assign zero = SLibGetFormattedValueFromId(dTypeId, 0) { int_T outputByteCount = 0; %% %if (CONST_HORIZROWS_OR_VERTCOLS > 1) %assign totOutColBytes = NumDataInputPorts * ... CONST_HORIZROWS_OR_VERTCOLS * numBytesPerCplxElmt const int_T nCols = %; int_T colNum; for ( colNum = 0; colNum < nCols; colNum++ ) { %endif %% (CONST_HORIZROWS_OR_VERTCOLS > 1) %% %assign y = LibBlockOutputSignalAddr(OUTPORT, "", "", 0) %foreach portNum = NumDataInputPorts %assign u = LibBlockInputSignalAddr(portNum, "", "",0) %assign inDims = LibBlockInputSignalDimensions(portNum) %assign colDim = LibBlockInputSignalWidth(portNum) / inDims[0] %if LibBlockInputSignalIsComplex(portNum) %% %% Complex input, complex output %% %assign colBytes = inDims[0] * numBytesPerCplxElmt %assign dimStr = "[%x%], complex," + ... " % bytes per col" /* Input %: % */ %if (CONST_HORIZROWS_OR_VERTCOLS > 1) (void) memcpy( ((byte_T *)(%)) + outputByteCount, ((byte_T *)(%)) + (colNum * %), % ); %else (void) memcpy( ((byte_T *)(%)) + outputByteCount, (byte_T *)%, % ); %endif %% (CONST_HORIZROWS_OR_VERTCOLS > 1) %% INCREMENT BYTE COUNT FROM THE (COMPLEX) MEMCPY outputByteCount += %; %else %% %% Real input, complex output %% %assign colBytes = inDims[0] * numBytesPerRealElmt %if (inDims[0] > 1) %assign dimStr = "[%x%], real," + ... " % bytes per col" /* Input %: % */ { int_T cnt; for ( cnt = 0; cnt < %; cnt++ ) { /* * Copy real input sample bytes to real part of output, * zeroize imaginary part */ %if (CONST_HORIZROWS_OR_VERTCOLS > 1) (void) memcpy( ((byte_T *)(%)) + outputByteCount, ((byte_T *)(%)) + (colNum * %) ... + (cnt * %), % ); %% INCREMENT BYTE COUNT FROM THE REAL PART MEMCPY outputByteCount += %; %% NOTE: The following only works for SL built-in types %% (i.e. not for custom types) %if ((dTypeId == tSS_DOUBLE) || (dTypeId == tSS_SINGLE)) *(% *)(((char *)%) + outputByteCount) ... = %; %else (void) memset( ((byte_T *)(%)) + outputByteCount, ... 0, % ); %endif %else (void) memcpy( ((byte_T *)(%)) + outputByteCount, ((byte_T *)(%)) ... + (cnt * %), % ); %% INCREMENT BYTE COUNT FROM THE REAL PART MEMCPY outputByteCount += %; %% NOTE: The following only works for SL built-in types %% (i.e. not for custom types) %if ((dTypeId == tSS_DOUBLE) || (dTypeId == tSS_SINGLE)) *(% *)(((char *)%) + outputByteCount) ... = %; %else (void) memset( ((byte_T *)(%)) + outputByteCount, ... 0, % ); %endif %endif %% (CONST_HORIZROWS_OR_VERTCOLS > 1) %% INCREMENT BYTE COUNT FROM THE ZEROIZATION OF IMAG PART outputByteCount += %; } } %else %assign dimStr = "[%x%], real," + ... " % bytes per col" /* Input %: % * Copy real input sample bytes to real part of output, * zeroize imaginary part */ %if (CONST_HORIZROWS_OR_VERTCOLS > 1) (void) memcpy( ((byte_T *)(%)) + outputByteCount, ((byte_T *)%) + (colNum * %), % ); outputByteCount += %; %% NOTE: The following only works for SL built-in types %% (i.e. not for custom types) %if ((dTypeId == tSS_DOUBLE) || (dTypeId == tSS_SINGLE)) *(% *)(((char *)%) + outputByteCount) ... = %; %else (void) memset( ((byte_T *)(%)) + outputByteCount, ... 0, % ); %endif %else (void) memcpy( ((byte_T *)(%)) + outputByteCount, (byte_T *)%, % ); outputByteCount += %; %% NOTE: The following only works for SL built-in types %% (i.e. not for custom types) %if ((dTypeId == tSS_DOUBLE) || (dTypeId == tSS_SINGLE)) *(% *)(((byte_T *)(%)) + outputByteCount) ... = %; %else (void) memset( ((byte_T *)(%)) + outputByteCount, ... 0, % ); %endif %endif %% (CONST_HORIZROWS_OR_VERTCOLS > 1) %% INCREMENT BYTE COUNT FROM THE ZEROIZATION OF IMAG PART %% [AVOID EXTRA UNUSED LINE OF CODE FOR FINAL INCREMENT] %if ((portNum+1) < NumDataInputPorts) outputByteCount += %; %endif %endif %% (inDims[0] > 1) %endif %% complex vs. real input %endforeach %% input port number %% %if (CONST_HORIZROWS_OR_VERTCOLS > 1) } %endif } %endfunction %% GenVertCatDifferentComplexity %% [EOF] smatrxcat.ttlc