%%
%%dspfixptlib.tlc-HelperfunctionsforDSPSystemToolboxFixed-PointCcodegeneration
%%
%%Copyright1995-2008TheMathWorks,Inc.
%%
 
%if EXISTS("_DSPFIXPTLIB_") == 0
%assign _DSPFIXPTLIB_ = 1
 
%%===========================================================================
%%PUBLICfunctiondefinitions(libraryAPI)arelocatedinthissection
%%===========================================================================
 
%%--------------------------------------------------------------
%%LISTOFPUBLICFUNCTIONS
%%
%%ASSIGNMENT("Out=Inp"):
%%
%%DSPFixptLibEquals(Out,Inp,RndSat)
%%
%%[NOTE:Complexandrealandmixedtypessupported.]
%%
%%
%%NEGATEorUNARYMINUS("Out=-Inp"):
%%
%%DSPFixptNegate(Out,Inp,RndSat)
%%
%%[NOTE:Complexandrealandmixedtypessupported.]
%%
%%
%%COMPLEXCONJUGATE("Out=conj(Inp)"):
%%
%%DSPFixptLibConjugate(Out,Inp,RndSat)
%%
%%[NOTE:Complexandrealandmixedtypessupported.]
%%
%%
%%POSITIVEACCUMULATION("Acc+=Inp"):
%%
%%DSPFixptLibPlusEquals(Acc,Inp,RndSat)
%%
%%[NOTE:Complexandrealandmixedtypessupported.]
%%
%%
%%NEGATIVEACCUMULATION("Acc-=Inp"):
%%
%%DSPFixptLibMinusEquals(Acc,Inp,RndSat)
%%
%%[NOTE:Complexandrealandmixedtypessupported.]
%%
%%
%%COMPLEXMULTIPLIES
%%
%%("Acc=In1*In2"):
%%
%%DSPFixptLibCplxTimes(Acc,In1,In2,PrdOut,RndSat)
%%
%%[NOTE:ResultisreturnedinAcc.
%%Acc,In1,andIn2mustallbeCOMPLEX,
%%PrdOutmustbeREAL.]
%%
%%("Acc*=Inp"):
%%
%%DSPFixptLibCplxTimesEquals(Acc,Inp,PrdOut,RndSat)
%%
%%[NOTE:ResultisreturnedinAcc.
%%AccandInpmustbeCOMPLEX,
%%PrdOutmustbeREAL.]
%%
%%
%%REALORMIXED-COMPLEXITYMULTIPLIES
%%
%%("PrdOut=In1*In2"):
%%
%%DSPFixptLibTimes(PrdOut,In1,In2,RndSat)
%%
%%[NOTE:ResultisreturnedinPrdOut.
%%IfbothIn1andIn2arereal,thenPrdOutmustbereal.
%%IfoneofIn1orIn2iscomplex,thenPrdOutmustbecomplex.
%%ThisfunctionwillERRORifbothIn1ANDIn2arecomplex.
%%InsteaduseDSPFixptLibCplxTimesforthatcase(seeabove).]
%%
%%("PrdOut*=Inp"):
%%
%%DSPFixptLibTimesEquals(PrdOut,Inp,RndSat)
%%
%%[NOTE:ResultisreturnedinPrdOut.
%%Inpmustbereal,PrdOutmayberealORcomplex.
%%ThisfunctionwillERRORifbothInpANDPrdOutarecomplex.
%%InsteaduseDSPFixptLibCplxTimesEqualsforthatcase(seeabove).]
%%
%%
%%NORM:
%%
%%DSPFixptLibNorm(Acc,In,PrdOut,RndSat)
%%
%%("PrdOut=In.re*In.re;
%%Acc=PrdOut;
%%PrdOut=In.im*In.im;
%%Acc+=PrdOut;"):
%%
%%[NOTE:Inmayberealorcomplex.
%%AccandPrdOutmustbereal]
%%
%%
%%DIVIDE:
%%
%%DSPFixptLibDivide(quot,num,den,RndSat)
%%
%%[NOTE:Numerator(num)mayberealorcomplex.
%%Denominator(den)mustbereal]
%%
%%
%%MULTIPLY-AND-ACCUMULATE:
%%FixptMAC(acc,"+=",prod,u1,u2,RndSat)-->"prod=u1*u2;acc+=prod;"
%%FixptMAC(acc,"-=",prod,u1,u2,RndSat)-->"prod=u1*u2;acc-=prod;"
%%FixptMAC(acc,"=",prod,u1,u2,RndSat)-->"prod=u1*u2;acc=prod;"
%%
%%[NOTE:Complexandrealandmixedtypessupported.]
%%
%%
%%GENERALSETUPINSTRUCTIONSFORREQUIREDARGUMENTS
%%
%%Anexampleofsomethingsthatyoumighttypeto
%%setupargumentsbeforeusingthelibraryfunctions:
%%
%%%assigncplx=1
%%%assigninDT=FixPt_GetInputDataType(INPORT)
%%%createrecordInp{labelLibBlockInputSignal(INPORT,"","","0");...
%%dTypeRecinDT;...
%%isComplexcplx}
%%%createrecordInp_i{labelLibBlockInputSignal(INPORT,"i","","0");...
%%dTypeRecinDT;...
%%isComplexcplx}
%%%assignoutDT=FixPt_GetOutputDataType(OUTPORT)
%%%createrecordOut{labelLibBlockOutputSignal(OUTPORT,"","",0);...
%%dTypeRecoutDT;...
%%isComplexcplx}
%%%assignaccDT=FixPt_GetParameterDataType(ACCUM_DATA_TYPE,0,0)
%%%createrecordAcc{labelaccLabel;...
%%dTypeRecaccDT;...
%%isComplexcplx}
%%%createrecordRndSat{roundingModeFixPtRoundingMode;...
%%overflowModeFixPtSaturationMode}
%%etc...
%%--------------------------------------------------------------
 
 
%%Function:DSPFixptLibEquals============================
%%
%%Abstract:
%%
%%Generatesinlinefixed-pointCcodeequivalentto"=".
%%
%%Exampleusage:
%%
%%%<DSPFixptLibEquals(Out,Acc,RndSat)>
%%%<DSPFixptLibEquals(Out,Inp_i,RndSat)>
%%%<DSPFixptLibEquals(Acc,Inp,RndSat)>
%%
%function DSPFixptLibEquals(Out, Inp, RndSat) Output
  %if ((Out.label != Inp.label) || (Out.isComplex != Inp.isComplex) || (Out.dTypeRec != Inp.dTypeRec))
    %if (Out.isComplex)
      %assign OutReLabel = Out.label + ".re"
      %assign OutImLabel = Out.label + ".im"
      %if (Inp.isComplex)
        %% COMPLEX algorithm
        %assign InpReLabel = Inp.label + ".re"
        %assign InpImLabel = Inp.label + ".im"
        /* %<Out.label> = %<Inp.label> */
        %<FixPt_Fix2FixAlwaysOutput(OutReLabel, Out.dTypeRec, InpReLabel, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
        %<FixPt_Fix2FixAlwaysOutput(OutImLabel, Out.dTypeRec, InpImLabel, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
      %else
        %% COMPLEX-REAL mixed algorithm
        %<FixPt_Fix2FixAlwaysOutput(OutReLabel, Out.dTypeRec, Inp.label, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
        %<OutImLabel> = %<FixPt_GetGroundValueOrNameFromDataTypeRec(Out.dTypeRec, TLC_FALSE)>;
      %endif
    %elseif (Inp.isComplex == 0)
      %% REAL algorithm
      %<FixPt_Fix2FixAlwaysOutput(Out.label, Out.dTypeRec, Inp.label, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %else
      %% REAL = COMPLEX (?)
      %error "DSPFixptLibEquals: assignment of a complex value into a real variable not supported."
    %endif
  %endif
%endfunction %% DSPFixptLibEquals
 
 
%%Function:DSPFixptNegate============================
%%
%%Abstract:
%%
%%Generatesinlinefixed-pointCcodeequivalenttounary"-".
%%
%%Exampleusage:
%%
%%%<DSPFixptNegate(Out,Inp,RndSat)>
%%
%function DSPFixptNegate(Out, Inp, RndSat) Output
  %% First set output to zero, then negate below via accumulate negative
  %<Out.label> = %<FixPt_GetGroundValueOrNameFromDataTypeRec(Out.dTypeRec, Out.isComplex)>;
  %%
  %if (Out.isComplex)
    %assign OutReLabel = Out.label + ".re"
    %assign OutImLabel = Out.label + ".im"
  %endif
  %%
  %if (Inp.isComplex)
    %%
    %assign InpReLabel = Inp.label + ".re"
    %assign InpImLabel = Inp.label + ".im"
    %%
    %if (Out.isComplex)
      %% COMPLEX I/O
      /* %<Out.label> = -(%<Inp.label>) */
      %<FixPt_AccumNeg_Easy(OutReLabel, Out.dTypeRec, InpReLabel, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
      %<FixPt_AccumNeg_Easy(OutImLabel, Out.dTypeRec, InpImLabel, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %else
      %% COMPLEX INPUT, REAL OUTPUT -> ERROR
      %error "DSPFixptNegate: storing the negative of a complex value in a real variable is not supported."
    %endif
  %else
    %if (Out.isComplex)
      %% REAL INPUT, COMPLEX OUTPUT
      %<FixPt_AccumNeg_Easy(OutReLabel, Out.dTypeRec, Inp.label, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %else
      %% REAL I/O
      %<FixPt_AccumNeg_Easy(Out.label, Out.dTypeRec, Inp.label, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %endif
  %endif
%endfunction %% DSPFixptNegate
 
 
%%Function:DSPFixptLibConjugate============================
%%
%%Abstract:
%%
%%Generatesinlinefixed-pointCcodeequivalentto"conj".
%%
%%Exampleusage:
%%
%%%<DSPFixptLibConjugate(Out,Inp,RndSat)>
%%
%function DSPFixptLibConjugate(Out, Inp, RndSat) Output
  %if (Inp.isComplex)
    %if (Out.isComplex)
      %%
      %assign InpReLabel = Inp.label + ".re"
      %assign InpImLabel = Inp.label + ".im"
      %assign OutReLabel = Out.label + ".re"
      %assign OutImLabel = Out.label + ".im"
      %%
      /* %<Out.label> = conj(%<Inp.label>) */
      %<FixPt_Fix2FixAlwaysOutput(OutReLabel, Out.dTypeRec, InpReLabel, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
      %<OutImLabel> = %<FixPt_GetGroundValueOrNameFromDataTypeRec(Out.dTypeRec, TLC_FALSE)>;
      %<FixPt_AccumNeg_Easy(OutImLabel, Out.dTypeRec, InpImLabel, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %else
      %error "DSPFixptLibConjugate: storing the conjugate of a complex value in a real variable is not supported."
    %endif
  %else
    %% Input is real -> output can be real or complex
    %<DSPFixptLibEquals(Out,Inp,RndSat)>
  %endif
%endfunction %% DSPFixptLibConjugate
 
 
%%Function:DSPFixptLibPlusEquals============================
%%
%%Abstract:
%%
%%Generatesinlinefixed-pointCcodeequivalentto"+=".
%%
%%Exampleusage:
%%
%%%<DSPFixptLibPlusEquals(Out,Inp,RndSat)>
%%%<DSPFixptLibPlusEquals(Acc,Inp,RndSat)>
%%
%function DSPFixptLibPlusEquals(Acc, Inp, RndSat) Output
  %if (Acc.isComplex)
    %if (Inp.isComplex)
      %% COMPLEX algorithm
      /* %<Acc.label> += %<Inp.label> */
      %<DSPFixptLibCplxPlusEquals(Acc, Inp, RndSat)>/
    %else
      %% COMPLEX-REAL mixed algorithm
      %<DSPFixptLibCplxRealPlusEquals(Acc, Inp, RndSat)>/
    %endif
  %elseif (Inp.isComplex == 0)
    %% REAL algorithm
    %<DSPFixptLibRealPlusEquals(Acc, Inp, RndSat)>/
  %else
    %% REAL += COMPLEX (?)
    %error "DSPFixptLibPlusEquals: assignment of a complex value into a real variable not supported."
  %endif
%endfunction %% DSPFixptLibPlusEquals
 
 
%%Function:DSPFixptLibMinusEquals============================
%%
%%Abstract:
%%
%%Generatesinlinefixed-pointCcodeequivalentto"-=".
%%
%%Exampleusage:
%%
%%%<DSPFixptLibMinusEquals(Out,Inp,RndSat)>
%%%<DSPFixptLibMinusEquals(Acc,Inp,RndSat)>
%%
%function DSPFixptLibMinusEquals(Acc, Inp, RndSat) Output
  %if (Acc.isComplex)
    %if (Inp.isComplex)
      %% COMPLEX algorithm
      /* %<Acc.label> -= %<Inp.label> */
      %<DSPFixptLibCplxMinusEquals(Acc, Inp, RndSat)>/
    %else
      %% COMPLEX-REAL mixed algorithm
      %<DSPFixptLibCplxRealMinusEquals(Acc, Inp, RndSat)>/
    %endif
  %elseif (Inp.isComplex == 0)
    %% REAL algorithm
    %<DSPFixptLibRealMinusEquals(Acc, Inp, RndSat)>/
  %else
    %% REAL -= COMPLEX (?)
    %error "DSPFixptLibMinusEquals: assignment of a complex value into a real variable not supported."
  %endif
%endfunction %% DSPFixptLibMinusEquals
 
 
%%Function:DSPFixptLibTimesEquals============================
%%
%%Abstract:
%%
%%Generatesinlinefixed-pointCcodeequivalentto"*=".
%%
%%ResultisreturnedinPrdOut.
%%Inpmustbereal,PrdOutmayberealORcomplex.
%%ThisfunctionwillERRORifbothInpANDPrdOutarecomplex.
%%
%%Exampleusage:
%%
%%DSPFixptLibTimesEquals(PrdOut,Inp,RndSat)
%%
%function DSPFixptLibTimesEquals(PrdOut, Inp, RndSat) Output
  %if (PrdOut.isComplex)
    %if (Inp.isComplex)
      %% COMPLEX algorithm not supported here
      %error "DSPFixptLibTimesEquals: incorrect usage. Use DSPFixptLibCplxTimesEquals instead."
    %else
      %% COMPLEX-REAL mixed algorithm
      %<DSPFixptLibCplxRealTimesEquals(PrdOut, Inp, RndSat)>
    %endif
  %elseif (Inp.isComplex == 0)
    %% REAL algorithm (both input and output REAL)
    %<DSPFixptLibRealTimesEquals(PrdOut, Inp, RndSat)>
  %else
    %% REAL *= COMPLEX (?)
    %error "DSPFixptLibTimesEquals: assignment of a complex value into a real variable not supported."
  %endif
%endfunction %% DSPFixptLibTimesEquals
 
 
%%Function:DSPFixptLibTimes============================
%%
%%Abstract:
%%
%%Generatesinlinefixed-pointCcodeequivalentto"*".
%%
%%Exampleusage:
%%
%%DSPFixptLibTimes(PrdOut,In1,In2,RndSat)
%%
%function DSPFixptLibTimes(PrdOut, In1, In2, RndSat) Output
  %if (PrdOut.isComplex)
    %if ((In1.isComplex) && (In2.isComplex))
      %% COMPLEX algorithm not supported here
      %error "DSPFixptLibTimes: incorrect usage. Use DSPFixptLibCplxTimes instead."
    %elseif (In1.isComplex)
      %% COMPLEX-REAL mixed inputs algorithm
      %% Just swap the order of In1 and In2
      %% and reuse "DSPFixptLibCplxRealCplxTimes"
      %<DSPFixptLibCplxRealCplxTimes(PrdOut, In2, In1, RndSat)>
    %elseif (In2.isComplex)
      %% REAL-COMPLEX mixed inputs algorithm
      %<DSPFixptLibCplxRealCplxTimes(PrdOut, In1, In2, RndSat)>
    %else
      %% REAL * REAL -> COMPLEX output
      %<DSPFixptLibRealTimes(PrdOut, In1, In2, RndSat)>
      %assign OutImLabel = PrdOut.label + ".im"
      %% Assuming bias == true "0" here
      %<OutImLabel> = %<FixPt_GetGroundValueOrNameFromDataTypeRec(Out.dTypeRec, TLC_FALSE)>;
    %endif
  %else %% REAL OUTPUT
    %if ((In1.isComplex == 0) && (In2.isComplex == 0))
      %% REAL OUT = REAL INP1 * REAL INP2
      %<DSPFixptLibRealTimes(PrdOut, In1, In2, RndSat)>
    %else
      %% REAL = (COMPLEX * COMPLEX) or
      %% REAL = (COMPLEX * REAL ) or
      %% REAL = (REAL * COMPLEX)
      %error "DSPFixptLibTimes: assignment of a complex value into a real variable not supported."
    %endif
  %endif
%endfunction %% DSPFixptLibTimes
 
 
%%Function:DSPFixptLibCplxTimesEquals========================
%%
%%Abstract:
%%
%%GeneratesinlineCOMPLEXfixed-pointCcodeequivalentto"*=".
%%
%%ResultisreturnedinAcc.
%%AccandInpmustbeCOMPLEX,
%%PrdOutmustbeREAL.
%%
%function DSPFixptLibCplxTimesEquals(Acc, Inp, PrdOut, RndSat) Output
  %if ( PrdOut.isComplex || ((Acc.isComplex != 1) || (Inp.isComplex != 1)) )
    %error "DSPFixptLibCplxTimesEquals: PrdOut must be real. Acc and Inp must be complex."
  %else
    %<DSPFixptLibCplxTimes(Acc, Acc, Inp, PrdOut, RndSat)>
  %endif
%endfunction %% DSPFixptLibCplxTimesEquals
 
 
%%Function:DSPFixptLibCplxTimes========================
%%
%%Abstract:
%%
%%GeneratesinlineCOMPLEXfixed-pointCcodeequivalentto"*",
%%wherethe"l-value"(Acc)andthe"r-values"(In1andIn2)areallcomplex.
%%
%%ResultisreturnedinAcc.
%%Acc,In1,andIn2mustallbeCOMPLEX,
%%PrdOutmustbeREAL.
%%
%function DSPFixptLibCplxTimes(Acc, In1, In2, PrdOut, RndSat) Output
%if ( PrdOut.isComplex || ((Acc.isComplex != 1) || (In1.isComplex != 1) || (In2.isComplex != 1)) )
    %error "DSPFixptLibCplxTimes: PrdOut must be real. Acc, In1, and In2 must be complex."
%else
  %assign AccLabelRe = Acc.label + ".re"
  %assign AccLabelIm = Acc.label + ".im"
  %assign In1LabelRe = In1.label + ".re"
  %assign In1LabelIm = In1.label + ".im"
  %assign In2LabelRe = In2.label + ".re"
  %assign In2LabelIm = In2.label + ".im"
  %%
  %% "okToUseAccAsPrdOutTemp" is set to 1 ("true") for any of the following cases:
  %%
  %% - USING SAME ACCUMULATOR AND PRODUCT DATA TYPES ON CODE GEN TARGET
  %%
  %% - USING DIFFERENT ACC AND PROD TYPES, BUT NO EXTRA FIXPT CASTING REQUIRED
  %% (i.e. Acc word length > Prod word length, and same scaling characteristics)
  %%
  %% Otherwise, it is 0 ("false").
  %%
  %% Note: "ActualBits" is the word length of the variable ON THE TARGET.
  %% "RequiredBits" is the SIMULATED word length. That is,
  %% "RequiredBits" is NOT NECESSARILY the target's "bucket size".
  %% The "RequiredBits" could be smaller than the bucket size.
  %% We are using the "RequiredBits" to determine if we can "re-use"
  %% the accumulator below in place of an intermediate product output
  %% step (save extra casting before sum/difference caluculation).
  %% This is necessary to properly handle any possible word length truncation
  %% during the assignment of the product type into the accum type before sum.
  %% We don't want to do this optimization if we might "lose bits" in the process.
  %%
  %assign AccWordLength = Acc.dTypeRec.RequiredBits
  %assign PrdOutWordLength = PrdOut.dTypeRec.RequiredBits
  %assign AccWL_GTE_PrdWL = (AccWordLength >= PrdOutWordLength)
  %assign AccLSBScaling = Acc.dTypeRec.FixedExp
  %assign PrdOutLSBScaling = PrdOut.dTypeRec.FixedExp
  %assign AccScl_EQ_PrdScl = (AccLSBScaling == PrdOutLSBScaling)
  %%
  %assign okToUseAccAsPrdOutTemp = (AccWL_GTE_PrdWL && AccScl_EQ_PrdScl) %% No extra casting needed
  %%
  %if ((Acc.label != In1.label) && (Acc.label != In2.label))
    %%
    %% None of the I/O to this function are shared (NOT in-place)
    %%
    %% --- [ACC REAL PART COMPUTATION] ---
    %if (okToUseAccAsPrdOutTemp)
      %% Acc.re = (PrdOutDataType)(In1.re * In2.re)
      %<FixPt_Multiply(AccLabelRe, PrdOut.dTypeRec, In1LabelRe, In1.dTypeRec, In2LabelRe, In2.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %else
      %% USING DIFFERENT ACCUMULATOR AND PRODUCT DATA TYPES
      %% PrdOut = In1.re * In2.re
      %<FixPt_Multiply(PrdOut.label, PrdOut.dTypeRec, In1LabelRe, In1.dTypeRec, In2LabelRe, In2.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
      %% Acc.re = PrdOut
      %<FixPt_Fix2FixAlwaysOutput(AccLabelRe, Acc.dTypeRec, PrdOut.label, PrdOut.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %endif %% okToUseAccAsPrdOutTemp
    %% PrdOut = In1.im * In2.im
    %<FixPt_Multiply(PrdOut.label, PrdOut.dTypeRec, In1LabelIm, In1.dTypeRec, In2LabelIm, In2.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %% Acc.re -= PrdOut
    %<FixPt_AccumNeg_Easy(AccLabelRe, Acc.dTypeRec, PrdOut.label, PrdOut.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %%
    %% --- [ACC IMAG PART COMPUTATION] ---
    %if (okToUseAccAsPrdOutTemp)
      %% Acc.im = (PrdOutDataType)(In1.re * In2.im)
      %<FixPt_Multiply(AccLabelIm, PrdOut.dTypeRec, In1LabelRe, In1.dTypeRec, In2LabelIm, In2.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %else
      %% USING DIFFERENT ACCUMULATOR AND PRODUCT DATA TYPES
      %% PrdOut = In1.re * In2.im
      %<FixPt_Multiply(PrdOut.label, PrdOut.dTypeRec, In1LabelRe, In1.dTypeRec, In2LabelIm, In2.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
      %% Acc.im = PrdOut
      %<FixPt_Fix2FixAlwaysOutput(AccLabelIm, Acc.dTypeRec, PrdOut.label, PrdOut.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %endif %% okToUseAccAsPrdOutTemp
    %% PrdOut = In1.im * In2.re
    %<FixPt_Multiply(PrdOut.label, PrdOut.dTypeRec, In1LabelIm, In1.dTypeRec, In2LabelRe, In2.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %% Acc.im += PrdOut
    %<FixPt_AccumPos_Easy(AccLabelIm, Acc.dTypeRec, PrdOut.label, PrdOut.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %%
  %else
    %%
    %% IN-PLACE complex multiply (In1 and/or In2 same as Acc)
    %%
    %%xxx add in-place code here (fix!)
    %error "dspfixptlib: in-place complex multiply not presently implemented."
  %endif %% in-place (In1 and/or In2 with Acc output)
%endif %% check TLC fcn arguments
%endfunction %% DSPFixptLibCplxTimes
 
 
%%===========================================================================
%%"PRIVATE"functiondefinitionsarelocatedinthissection
%%===========================================================================
 
 
%%------------------
%%PLUSEQUALS("+=")
%%------------------
 
%%Function:DSPFixptLibRealPlusEquals============================
%%
%%Abstract:
%%
%%GeneratesinlineREALfixed-pointCcodeequivalentto"+=".
%%
%%Assumesrecordsrepresentedby"Inp"and"Acc"arereal.
%%
%function DSPFixptLibRealPlusEquals(Acc, Inp, RndSat) Output
    %% Acc += Inp
    %<FixPt_AccumPos_Easy(Acc.label, Acc.dTypeRec, Inp.label, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
%endfunction %% DSPFixptLibRealPlusEquals
 
 
%%Function:DSPFixptLibCplxPlusEquals============================
%%
%%Abstract:
%%
%%GeneratesinlineCOMPLEXfixed-pointCcodeequivalentto"+=".
%%
%%Assumesrecordsrepresentedby"Inp"and"Acc"arecomplex.
%%
%function DSPFixptLibCplxPlusEquals(Acc, Inp, RndSat) Output
    %%
    %% Acc.re += Inp.re
    %%
    %assign InpReLabel = Inp.label + ".re"
    %assign AccReLabel = Acc.label + ".re"
    %<FixPt_AccumPos_Easy(AccReLabel, Acc.dTypeRec, InpReLabel, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %%
    %% Acc.im += Inp.im
    %%
    %assign InpImLabel = Inp.label + ".im"
    %assign AccImLabel = Acc.label + ".im"
    %<FixPt_AccumPos_Easy(AccImLabel, Acc.dTypeRec, InpImLabel, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %%
%endfunction %% DSPFixptLibCplxPlusEquals
 
 
%%Function:DSPFixptLibCplxRealPlusEquals========================
%%
%%Abstract:
%%
%%GeneratesinlineCOMPLEXfixed-pointCcodeequivalentto"+=",where
%%the"l-value"(Acc)iscomplexandthe"r-value"(Inp)isreal.
%%
%%Assumesrecord"Acc"iscomplex.
%%
%%Assumesrecord"Inp"isreal.
%%
%function DSPFixptLibCplxRealPlusEquals(Acc, Inp, RndSat) Output
    %%
    %% Acc.re += Inp
    %%
    %assign AccReLabel = Acc.label + ".re"
    %<FixPt_AccumPos_Easy(AccReLabel, Acc.dTypeRec, Inp.label, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %%
    %% (note that Acc.im is not modified in this implementation)
%endfunction %% DSPFixptLibCplxRealPlusEquals
 
 
%%-------------------
%%MINUSEQUALS("-=")
%%-------------------
 
%%Function:DSPFixptLibRealMinusEquals============================
%%
%%Abstract:
%%
%%GeneratesinlineREALfixed-pointCcodeequivalentto"-=".
%%
%%Assumesrecordsrepresentedby"Inp"and"Acc"arereal.
%%
%function DSPFixptLibRealMinusEquals(Acc, Inp, RndSat) Output
    %% Acc -= Inp
    %<FixPt_AccumNeg_Easy(Acc.label, Acc.dTypeRec, Inp.label, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
%endfunction %% DSPFixptLibRealMinusEquals
 
 
%%Function:DSPFixptLibCplxMinusEquals============================
%%
%%Abstract:
%%
%%GeneratesinlineCOMPLEXfixed-pointCcodeequivalentto"-=".
%%
%%Assumesrecordsrepresentedby"Inp"and"Acc"arecomplex.
%%
%function DSPFixptLibCplxMinusEquals(Acc, Inp, RndSat) Output
    %%
    %% Acc.re -= Inp.re
    %%
    %assign InpReLabel = Inp.label + ".re"
    %assign AccReLabel = Acc.label + ".re"
    %<FixPt_AccumNeg_Easy(AccReLabel, Acc.dTypeRec, InpReLabel, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %%
    %% Acc.im -= Inp.im
    %assign InpImLabel = Inp.label + ".im"
    %assign AccImLabel = Acc.label + ".im"
    %<FixPt_AccumNeg_Easy(AccImLabel, Acc.dTypeRec, InpImLabel, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %%
%endfunction %% DSPFixptLibCplxMinusEquals
 
 
%%Function:DSPFixptLibCplxRealMinusEquals========================
%%
%%Abstract:
%%
%%GeneratesinlineCOMPLEXfixed-pointCcodeequivalentto"-=",where
%%the"l-value"(Acc)iscomplexandthe"r-value"(Inp)isreal.
%%
%%Assumesrecord"Acc"iscomplex.
%%
%%Assumesrecord"Inp"isreal.
%%
%function DSPFixptLibCplxRealMinusEquals(Acc, Inp, RndSat) Output
    %%
    %% Acc.re -= Inp
    %%
    %assign AccReLabel = Acc.label + ".re"
    %<FixPt_AccumNeg_Easy(AccReLabel, Acc.dTypeRec, Inp.label, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %%
    %% (note that Acc.im is not modified in this implementation)
%endfunction %% DSPFixptLibCplxRealMinusEquals
 
 
%%-------------------
%%TIMESEQUALS("*=")
%%-------------------
 
%%Function:DSPFixptLibCplxRealTimesEquals========================
%%
%%Abstract:
%%
%%Generatesinlinemixed-complexityfixed-pointCcodeequivalentto"*=".
%%
%%Assumesrecord"PrdOut"iscomplex.
%%Assumesrecord"In"isreal.
%%
%function DSPFixptLibCplxRealTimesEquals(PrdOut, Inp, RndSat) Output
  %% PrdOut.re *= Inp
  %assign PrdOutReLabel = PrdOut.label + ".re"
  %<FixPt_Multiply(PrdOutReLabel, PrdOut.dTypeRec, PrdOutReLabel, PrdOut.dTypeRec, Inp.label, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
  %% PrdOut.im *= Inp
  %assign PrdOutImLabel = PrdOut.label + ".im"
  %<FixPt_Multiply(PrdOutImLabel, PrdOut.dTypeRec, PrdOutImLabel, PrdOut.dTypeRec, Inp.label, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
%endfunction %% DSPFixptLibCplxRealTimesEquals
 
 
%%Function:DSPFixptLibRealTimesEquals========================
%%
%%Abstract:
%%
%%GeneratesinlineREALfixed-pointCcodeequivalentto"*=".
%%
%%Assumesrecords"PrdOut"and"In"arebothreal.
%%
%function DSPFixptLibRealTimesEquals(PrdOut, Inp, RndSat) Output
  %% PrdOut *= Inp
  %<FixPt_Multiply(PrdOut.label, PrdOut.dTypeRec, PrdOut.label, PrdOut.dTypeRec, Inp.label, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
%endfunction %% DSPFixptLibRealTimesEquals
 
 
%%-------------------
%%TIMES("*")
%%-------------------
 
%%Function:DSPFixptLibCplxRealCplxTimes========================
%%
%%Abstract:
%%
%%Generatesinlinemixedcomplexityfixed-pointCcodeequivalentto"*",
%%wherethe"l-value"(PrdOut)iscomplex,andthe"r-values"(In1andIn2)
%%arerealandcomplex(respectively).
%%
%%Assumesrecord"PrdOut"iscomplex.
%%Assumesrecord"In1"isreal.
%%Assumesrecord"In2"iscomplex.
%%
%function DSPFixptLibCplxRealCplxTimes(PrdOut, In1, In2, RndSat) Output
  %% PrdOut.re = In1 * In2.re
  %assign PrdOutReLabel = PrdOut.label + ".re"
  %assign In2Relabel = In2.label + ".re"
  %<FixPt_Multiply(PrdOutReLabel, PrdOut.dTypeRec, In1.label, In1.dTypeRec, In2Relabel, In2.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
  %% PrdOut.im = In1 * In2.im
  %assign PrdOutImLabel = PrdOut.label + ".im"
  %assign In2Imlabel = In2.label + ".im"
  %<FixPt_Multiply(PrdOutImLabel, PrdOut.dTypeRec, In1.label, In1.dTypeRec, In2Imlabel, In2.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
%endfunction %% DSPFixptLibCplxRealCplxTimes
 
 
%%Function:DSPFixptLibRealTimes========================
%%
%%Abstract:
%%
%%GeneratesinlineREALfixed-pointCcodeequivalentto"*",
%%wherethe"l-value"(PrdOut)isreal,andthe"r-values"(In1andIn2)
%%arebothreal.
%%
%%Assumesrecords"PrdOut","In1",and"In2"areallreal.
%%
%function DSPFixptLibRealTimes(PrdOut, In1, In2, RndSat) Output
  %% PrdOut = In1 * In2
  %<FixPt_Multiply(PrdOut.label, PrdOut.dTypeRec, In1.label, In1.dTypeRec, In2.label, In2.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
%endfunction %% DSPFixptLibRealTimes
 
 
%%-------------------------------
%%MULTIPLYANDACCUMULATE("MAC")
%%-------------------------------
 
 
%%FunctionFixptMAC(accRec,opStr,prodRec,u1Rec,u2Rec,rndSatRec)============================
%%
%%Computestheproductu1*u2andstoresitintoaccbasedonopStr:
%%Generatedcodefollowsthisparadigm:
%%prod=u1*u2;
%%
%%opStr:"+="-->acc+=prod
%%opStr:"-="-->acc-=prod
%%opStr:"="-->acc=prod
%%
%%Abstract:
%%
%%Generatesinlinefixed-pointCcodeforamultiply-and-accumulateunit.
%%
%%Exampleusage:
%%
%%%<FixptMAC(Acc,"+=",Prod,u1,u2,RndSat)>(Generates"Prod=u1*u2;Acc+=Prod;")
%%%<FixptMAC(Acc,"-=",Prod,u1,u2,RndSat)>(Generates"Prod=u1*u2;Acc-=Prod;")
%%%<FixptMAC(Acc,"=",Prod,u1,u2,RndSat)>(Generates"Prod=u1*u2;Acc=Prod;")
%%
%%prodRec:real(ifcomplex,onlyrealpartisused)
%%u1Rec:canberealorcomplex
%%u2Rec:canberealorcomplex
%%
%%accRec:shouldbeof"accumulator"datatype
%%realorcomplexwhenu1andu2arebothreal(acc.imisunaltered)
%%mustbecomplexwheneitheru1oru2arecomplex
%%
%%Notes:
%%[1]accRec,u1Rec,u2Rec,prodRecmustbeTLC"records"thatcontain
%%thefollowingfields:
%%blahRec.label-->the"name"ofthevariabletouse
%%blahRec.dTypeRec-->thedatatyperecordassociatedwiththevariable
%%blahRec.isComplex-->Flagtoindicatecomplexity(0or1)
%%
%%[2]rndSatRecmustbeaTLCrecordthatcontains:
%%rndSatRec.roundingMode-->theroundingmodetobeusedinoperations
%%rndSatRec.overflowMode-->theoverflowmodetobeusedinoperations
%%
%function FixptMAC(accRec, opStr, prodRec, u1Rec, u2Rec, rndSatRec) Output
  %% Create operator list:
  %assign opMACPlusEquals = 1
  %assign opMACMinusEquals = 2
  %assign opMACEquals = 3
  %if ISEQUAL(opStr,"+=")
    %% Generate code for acc += prod
    %assign opMAC = opMACPlusEquals
  %elseif ISEQUAL(opStr,"-=")
    %% Generate code for acc -= prod
    %assign opMAC = opMACMinusEquals
  %elseif ISEQUAL(opStr,"=")
    %% Generate code for acc = prod
    %assign opMAC = opMACEquals
  %else
    %error "Invalid operation string passed to FixptMAC function. Valid choices are '+=', '-=', and '='"
    %return
  %endif
  %assign accLabel = accRec.label
  %assign accDTRec = accRec.dTypeRec
  %assign accIsComplex = accRec.isComplex
  %assign accIsReal = !(accIsComplex)
  %if (accIsComplex)
    %assign accReLabel = accLabel + ".re"
    %assign accImLabel = accLabel + ".im"
  %endif
  %%
  %assign u1Label = u1Rec.label
  %assign u1DTRec = u1Rec.dTypeRec
  %assign u1IsComplex = u1Rec.isComplex
  %assign u1IsReal = !(u1IsComplex)
  %if (u1IsComplex)
    %assign u1ReLabel = u1Label + ".re"
    %assign u1ImLabel = u1Label + ".im"
  %endif
  %%
  %assign u2Label = u2Rec.label
  %assign u2DTRec = u2Rec.dTypeRec
  %assign u2IsComplex = u2Rec.isComplex
  %assign u2IsReal = !(u2IsComplex)
  %if (u2IsComplex)
    %assign u2ReLabel = u2Label + ".re"
    %assign u2ImLabel = u2Label + ".im"
  %endif
  %%
  %assign prodLabel = prodRec.label
  %assign prodDTRec = prodRec.dTypeRec
  %if prodRec.isComplex
    %% The product variable can be real always. However, if calling function
    %% passes in a complex product variable, use only the real part:
    %assign prodLabel = prodRec.label + ".re"
  %else
  %endif
  %%
  %assign rndMode = rndSatRec.roundingMode
  %assign satMode = rndSatRec.overflowMode
  %%
  %% Three cases:
  %% 1: u1 and u2 are both real
  %% 2: u1 is real, u2 is complex OR u1 is complex, u2 is real
  %% 3: u1 and u2 are both complex
  %if (u1IsReal && u2IsReal)
    %% Case 1: u1 and u2 are both real
    %% Generate code that looks like this:
    %% opStr: "+=" opStr: "-=" opStr: "="
    %% ------------- ------------- -------------
    %% prod = u1 * u2; prod = u1 * u2; prod = u1 * u2;
    %% acc += prod; acc -= prod; acc = prod;
    %% Accumulator can be real, but if a complex accumulator variable is passed
    %% in, use only the real part.
    %if (accIsComplex)
      %assign accLabel = accReLabel
    %endif
    %% Generate code for prod = u1 * u2
    %<FixPt_Multiply(prodLabel, prodDTRec, u1Label, u1DTRec, u2Label, u2DTRec, rndMode, satMode)>/
    %switch opMAC
      %case opMACPlusEquals
        %% Generate code for acc += prod
        %<FixPt_AccumPos_Easy(accLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
        %break
      %case opMACMinusEquals
        %% Generate code for acc -= prod
        %<FixPt_AccumNeg_Easy(accLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
        %break
      %case opMACEquals
        %% Generate code for acc = prod
        %<FixPt_Fix2FixAlwaysOutput(accLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
        %if (accIsComplex)
          %% If acc is complex, use only the real part and set the imag part to zero
          %<accImLabel> = %<FixPt_GetGroundValueOrNameFromDataTypeRec(accDTRec, TLC_FALSE)>;
        %endif
        %break
    %endswitch
  %else
    %% acc must be complex when either u1 or u2 (or both) are complex
    %% therefore, error out if acc is real
    %if accIsReal
      %error "Accumulator must be complex when multiplying and accumulating complex numbers using the FixptMAC function"
    %endif
    %% Generate generic high-level comment describing what's about to follow:
    /* prod = %<u1Rec.label> * %<u2Rec.label> */
    /* acc %<opStr> prod */
    %if ((u1IsReal && u2IsComplex) || (u1IsComplex && u2IsReal))
      %% Case 2: mixed-complexity case
      %% Generate code that looks like this:
      %% opStr: "+=" opStr: "-=" opStr: "="
      %% ------------- ------------- -------------
      %% prod = u1 * u2.re; prod = u1 * u2.re; prod = u1 * u2.re;
      %% acc.re += prod; acc.re -= prod; acc.re = prod;
      %% prod = u1 * u2.im; prod = u1 * u2.im; prod = u1 * u2.im;
      %% acc.im += prod; acc.im -= prod; acc.im = prod;
      %% If u1 is complex, swap with u2:
      %if (u1IsComplex)
        %assign u1DTRec = u2Rec.dTypeRec
        %assign u1Label = u2Label
        %assign u2DTRec = u1Rec.dTypeRec
        %assign u2ReLabel = u1ReLabel
        %assign u2ImLabel = u1ImLabel
      %endif
      %% Now use the variables in TLC functions below:
      %switch opMAC
        %case opMACPlusEquals
          %% Generate code for prod = u1 * u2.re;
          %<FixPt_Multiply(prodLabel, prodDTRec, u1Label, u1DTRec, u2ReLabel, u2DTRec, rndMode, satMode)>/
          %% Generate code for acc.re += prod;
          %<FixPt_AccumPos_Easy(accReLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
          %% Generate code for prod = u1 * u2.im;
          %<FixPt_Multiply(prodLabel, prodDTRec, u1Label, u1DTRec, u2ImLabel, u2DTRec, rndMode, satMode)>/
          %% Generate code for acc.im += prod;
          %<FixPt_AccumPos_Easy(accImLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
          %break
        %case opMACMinusEquals
          %% Generate code for prod = u1 * u2.re;
          %<FixPt_Multiply(prodLabel, prodDTRec, u1Label, u1DTRec, u2ReLabel, u2DTRec, rndMode, satMode)>/
          %% Generate code for acc.re -= prod;
          %<FixPt_AccumNeg_Easy(accReLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
          %% Generate code for prod = u1 * u2.im;
          %<FixPt_Multiply(prodLabel, prodDTRec, u1Label, u1DTRec, u2ImLabel, u2DTRec, rndMode, satMode)>/
          %% Generate code for acc.im -= prod;
          %<FixPt_AccumNeg_Easy(accImLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
          %break
        %case opMACEquals
          %% Generate code for prod = u1 * u2.re;
          %<FixPt_Multiply(prodLabel, prodDTRec, u1Label, u1DTRec, u2ReLabel, u2DTRec, rndMode, satMode)>/
          %% Generate code for acc.re = prod;
          %<FixPt_Fix2FixAlwaysOutput(accReLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
          %% Generate code for prod = u1 * u2.im;
          %<FixPt_Multiply(prodLabel, prodDTRec, u1Label, u1DTRec, u2ImLabel, u2DTRec, rndMode, satMode)>/
          %% Generate code for acc.im = prod;
          %<FixPt_Fix2FixAlwaysOutput(accImLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
          %break
      %endswitch
    %else
      %% Case 3: u1 and u2 are both complex
      %%
      %% In sfunction we write
      %% acc += in1 * in2
      %% in1 * in2 returns a temporary object (tmpAcc) of accumulator data type (for complex u1, u2)
      %% After that, we add tmpAcc to acc
      %% acc += tmpAcc
      %%
      %% In order to generate code having same numerical results as simulation, we need a tmpAcc
      %% in the generated code. Since the order of (addition and subtraction) does not matter in
      %% "Wrap" arithmetic, we only need this tmpAcc for "Saturate" arithmetic.
      %%
      %% Generate code that looks like this (for satMode = "Wrap"):
      %% opStr: "+=" opStr: "-=" opStr: "="
      %% ------------- ------------- -------------
      %% prod = u1.re * u2.re; prod = u1.re * u2.re; prod = u1.re * u2.re;
      %% acc.re += prod; acc.re -= prod; acc.re = prod;
      %% prod = u1.im * u2.im; prod = u1.im * u2.im; prod = u1.im * u2.im;
      %% acc.re -= prod; acc.re += prod; acc.re -= prod;
      %% prod = u1.re * u2.im; prod = u1.re * u2.im; prod = u1.re * u2.im;
      %% acc.im += prod; acc.im -= prod; acc.im = prod;
      %% prod = u1.im * u2.re; prod = u1.im * u2.re; prod = u1.im * u2.re;
      %% acc.im += prod; acc.im -= prod; acc.im += prod;
      %%
      %% Generate code that looks like this (for satMode = "Saturate"):
      %% opStr: "+=" opStr: "-=" opStr: "="
      %% ------------- ------------- -------------
      %% prod = u1.re * u2.re; prod = u1.re * u2.re; Same As Above
      %% tmpAcc = prod; tmpAcc = prod;
      %% prod = u1.im * u2.im; prod = u1.im * u2.im;
      %% tmpAcc -= prod; tmpAcc -= prod;
      %% acc.re += tmpAcc; acc.re -= tmpAcc;
      %% prod = u1.re * u2.im; prod = u1.re * u2.im;
      %% tmpAcc = prod; tmpAcc = prod;
      %% prod = u1.im * u2.re; prod = u1.im * u2.re;
      %% tmpAcc += prod; tmpAcc += prod;
      %% acc.im += tmpAcc.im; acc.im -= tmpAcc.im;
      %%
      %switch opMAC
        %case opMACPlusEquals
          %if (satMode == "Wrap")
            %% Generate code for prod = u1.re * u2.re;
            %<FixPt_Multiply(prodLabel, prodDTRec, u1ReLabel, u1DTRec, u2ReLabel, u2DTRec, rndMode, satMode)>/
            %% Generate code for acc.re += prod;
            %<FixPt_AccumPos_Easy(accReLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
            %% Generate code for prod = u1.im * u2.im;
            %<FixPt_Multiply(prodLabel, prodDTRec, u1ImLabel, u1DTRec, u2ImLabel, u2DTRec, rndMode, satMode)>/
            %% Generate code for acc.re -= prod;
            %<FixPt_AccumNeg_Easy(accReLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
            %% Generate code for prod = u1.re * u2.im;
            %<FixPt_Multiply(prodLabel, prodDTRec, u1ReLabel, u1DTRec, u2ImLabel, u2DTRec, rndMode, satMode)>/
            %% Generate code for acc.im += prod;
            %<FixPt_AccumPos_Easy(accImLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
            %% Generate code for prod = u1.im * u2.re;
            %<FixPt_Multiply(prodLabel, prodDTRec, u1ImLabel, u1DTRec, u2ReLabel, u2DTRec, rndMode, satMode)>/
            %% Generate code for acc.im += prod;
            %<FixPt_AccumPos_Easy(accImLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
          %else
            %copyrecord tmpAccRec accRec
            %assign tmpAccRec.label = accRec.label + "Tmp"
            %assign tmpAccRec.isComplex = 0
            {
              %<accDTRec.Name> %<tmpAccRec.label>;
              %% prod = u1.re * u2.re;
              %% tmpAcc = prod;
              %% prod = u1.im * u2.im;
              %% tmpAcc -= prod;
              %% acc.re += tmpAcc.re;
              %<FixPt_Multiply(prodLabel, prodDTRec, u1ReLabel, u1DTRec, u2ReLabel, u2DTRec, rndMode, satMode)>/
              %<FixPt_Fix2FixAlwaysOutput(tmpAccRec.label, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
              %<FixPt_Multiply(prodLabel, prodDTRec, u1ImLabel, u1DTRec, u2ImLabel, u2DTRec, rndMode, satMode)>/
              %<FixPt_AccumNeg_Easy(tmpAccRec.label, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
              %<FixPt_AccumPos_Easy(accReLabel, accDTRec, tmpAccRec.label, accDTRec, rndMode, satMode)>/
              %% prod = u1.re * u2.im;
              %% tmpAcc = prod;
              %% prod = u1.im * u2.re;
              %% tmpAcc += prod;
              %% acc.im += tmpAcc.im;
              %<FixPt_Multiply(prodLabel, prodDTRec, u1ReLabel, u1DTRec, u2ImLabel, u2DTRec, rndMode, satMode)>/
              %<FixPt_Fix2FixAlwaysOutput(tmpAccRec.label, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
              %<FixPt_Multiply(prodLabel, prodDTRec, u1ImLabel, u1DTRec, u2ReLabel, u2DTRec, rndMode, satMode)>/
              %<FixPt_AccumPos_Easy(tmpAccRec.label, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
              %<FixPt_AccumPos_Easy(accImLabel, accDTRec, tmpAccRec.label, accDTRec, rndMode, satMode)>/
            }
          %endif
          %break
        %case opMACMinusEquals
          %if (satMode == "Wrap")
            %% Generate code for prod = u1.re * u2.re;
            %<FixPt_Multiply(prodLabel, prodDTRec, u1ReLabel, u1DTRec, u2ReLabel, u2DTRec, rndMode, satMode)>/
            %% Generate code for acc.re -= prod;
            %<FixPt_AccumNeg_Easy(accReLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
            %% Generate code for prod = u1.im * u2.im;
            %<FixPt_Multiply(prodLabel, prodDTRec, u1ImLabel, u1DTRec, u2ImLabel, u2DTRec, rndMode, satMode)>/
            %% Generate code for acc.re += prod;
            %<FixPt_AccumPos_Easy(accReLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
            %% Generate code for prod = u1.re * u2.im;
            %<FixPt_Multiply(prodLabel, prodDTRec, u1ReLabel, u1DTRec, u2ImLabel, u2DTRec, rndMode, satMode)>/
            %% Generate code for acc.im -= prod;
            %<FixPt_AccumNeg_Easy(accImLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
            %% Generate code for prod = u1.im * u2.re;
            %<FixPt_Multiply(prodLabel, prodDTRec, u1ImLabel, u1DTRec, u2ReLabel, u2DTRec, rndMode, satMode)>/
            %% Generate code for acc.im -= prod;
            %<FixPt_AccumNeg_Easy(accImLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
          %else
            %copyrecord tmpAccRec accRec
            %assign tmpAccRec.label = accRec.label + "Tmp"
            %assign tmpAccRec.isComplex = 0
            {
              %<accDTRec.Name> %<tmpAccRec.label>;
              %% prod = u1.re * u2.re;
              %% tmpAcc = prod;
              %% prod = u1.im * u2.im;
              %% tmpAcc -= prod;
              %% acc.re -= tmpAcc.re;
              %<FixPt_Multiply(prodLabel, prodDTRec, u1ReLabel, u1DTRec, u2ReLabel, u2DTRec, rndMode, satMode)>/
              %<FixPt_Fix2FixAlwaysOutput(tmpAccRec.label, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
              %<FixPt_Multiply(prodLabel, prodDTRec, u1ImLabel, u1DTRec, u2ImLabel, u2DTRec, rndMode, satMode)>/
              %<FixPt_AccumNeg_Easy(tmpAccRec.label, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
              %<FixPt_AccumNeg_Easy(accReLabel, accDTRec, tmpAccRec.label, accDTRec, rndMode, satMode)>/
              %% prod = u1.re * u2.im;
              %% tmpAcc = prod;
              %% prod = u1.im * u2.re;
              %% tmpAcc += prod;
              %% acc.im -= tmpAcc.im;
              %<FixPt_Multiply(prodLabel, prodDTRec, u1ReLabel, u1DTRec, u2ImLabel, u2DTRec, rndMode, satMode)>/
              %<FixPt_Fix2FixAlwaysOutput(tmpAccRec.label, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
              %<FixPt_Multiply(prodLabel, prodDTRec, u1ImLabel, u1DTRec, u2ReLabel, u2DTRec, rndMode, satMode)>/
              %<FixPt_AccumPos_Easy(tmpAccRec.label, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
              %<FixPt_AccumNeg_Easy(accImLabel, accDTRec, tmpAccRec.label, accDTRec, rndMode, satMode)>/
            }
          %endif
          %break
        %case opMACEquals
          %% Generate code for prod = u1.re * u2.re;
          %<FixPt_Multiply(prodLabel, prodDTRec, u1ReLabel, u1DTRec, u2ReLabel, u2DTRec, rndMode, satMode)>/
          %% Generate code for acc.re = prod;
          %<FixPt_Fix2FixAlwaysOutput(accReLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
          %% Generate code for prod = u1.im * u2.im;
          %<FixPt_Multiply(prodLabel, prodDTRec, u1ImLabel, u1DTRec, u2ImLabel, u2DTRec, rndMode, satMode)>/
          %% Generate code for acc.re -= prod;
          %<FixPt_AccumNeg_Easy(accReLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
          %% Generate code for prod = u1.re * u2.im;
          %<FixPt_Multiply(prodLabel, prodDTRec, u1ReLabel, u1DTRec, u2ImLabel, u2DTRec, rndMode, satMode)>/
          %% Generate code for acc.im = prod;
          %<FixPt_Fix2FixAlwaysOutput(accImLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
          %% Generate code for prod = u1.im * u2.re;
          %<FixPt_Multiply(prodLabel, prodDTRec, u1ImLabel, u1DTRec, u2ReLabel, u2DTRec, rndMode, satMode)>/
          %% Generate code for acc.im += prod;
          %<FixPt_AccumPos_Easy(accImLabel, accDTRec, prodLabel, prodDTRec, rndMode, satMode)>/
          %break
      %endswitch
    %endif
  %endif
%endfunction %% FixptMAC
 
%%Function:DSPFixptLibDivide========================
%%
%%Abstract:
%%
%%GeneratesinlineREALorCOMPLEXfixed-pointCcodeequivalentto
%%quot=num/den
%%
%%Record"den"mustbereal.
%%Records"num"and"quot"couldbecomplex
%%
%function DSPFixptLibDivide(quot, num, den, RndSat) Output
  %if (den.isComplex)
    %error "DSPFixptLibDivide: complex denominator is not supported."
  %endif
  %if ((num.isComplex) && !(quot.isComplex) )
    %error "DSPFixptLibDivide: quotient must be complex when numerator is complex."
  %endif
  %if (num.isComplex)
    %assign quotReLabel = quot.label + ".re"
    %assign quotImLabel = quot.label + ".im"
    %assign numReLabel = num.label + ".re"
    %assign numImLabel = num.label + ".im"
    %%
    /* %<quotReLabel> = %<numReLabel> / %<den.label> */
    %<FixPt_Division(quotReLabel,quot.dTypeRec,numReLabel,num.dTypeRec,den.label,den.dTypeRec,RndSat.roundingMode,RndSat.overflowMode)>/
    %%
    /* %<quotImLabel> = %<numImLabel> / %<den.label> */
    %<FixPt_Division(quotImLabel,quot.dTypeRec,numImLabel,num.dTypeRec,den.label,den.dTypeRec,RndSat.roundingMode,RndSat.overflowMode)>/
  %else
    %%
    /* %<quot.label> = %<num.label> / %<den.label> */
    %<FixPt_Division(quot.label,quot.dTypeRec,num.label,num.dTypeRec,den.label,den.dTypeRec,RndSat.roundingMode,RndSat.overflowMode)>/
  %endif
%endfunction %% DSPFixptLibDivide
 
%%Function:DSPFixptLibDivide2========================
%%
%%Abstract:
%%similaroperationasDSPFixpt::DSPFixptDivide.
%%GeneratesinlineREALorCOMPLEXfixed-pointCcodeequivalentto
%%quot=num/den
%%usefulforDSPfactorizationandsolverblocks
%%
%%Records"num"and"quot"couldbecomplex
%%Record"den"couldbeRealorComplex,
%%butitisalwaystreatedasaRealNumber,itsimaginarypartisignored.
%%
%%So,thereare4complexitycombinations,R-Real,C-Complex
%%QuotNumoperations
%%RRquot=num/den.re
%%CRquot.re=num/den.re,quot.im=0
%%RCquot=num.re/den.re,num.imisignored
%%CCquot.re=num.re/den.re,quot.im=num.im/den.re
%%
%function DSPFixptLibDivide2(quot, num, den, RndSat) Output
  %if (den.isComplex)
    %% only real part of the denominator is considered
    %assign denReLabel = den.label + ".re"
  %else
    %assign denReLabel = den.label
  %endif
  %%
  %if (num.isComplex)
    %assign numReLabel = num.label + ".re"
    %assign numImLabel = num.label + ".im"
    %%
    %if (quot.isComplex)
      %assign quotReLabel = quot.label + ".re"
      %assign quotImLabel = quot.label + ".im"
      /* %<quotReLabel> = %<numReLabel> / %<denReLabel> */
      %<FixPt_Division(quotReLabel,quot.dTypeRec,numReLabel,num.dTypeRec,denReLabel,den.dTypeRec,RndSat.roundingMode,RndSat.overflowMode)>/
      %%
      /* %<quotImLabel> = %<numImLabel> / %<denReLabel> */
      %<FixPt_Division(quotImLabel,quot.dTypeRec,numImLabel,num.dTypeRec,denReLabel,den.dTypeRec,RndSat.roundingMode,RndSat.overflowMode)>/
    %else %%quot is Real
      /* %<quot.label> = %<numReLabel> / %<denReLabel> */
      %<FixPt_Division(quot.label,quot.dTypeRec,numReLabel,num.dTypeRec,denReLabel,den.dTypeRec,RndSat.roundingMode,RndSat.overflowMode)>/
    %endif
    %%
  %else
    %% num is Real
    %if (quot.isComplex)
      %assign quotReLabel = quot.label + ".re"
      %assign quotImLabel = quot.label + ".im"
      /* %<quotReLabel> = %<num.label> / %<denReLabel> */
      %<FixPt_Division(quotReLabel,quot.dTypeRec,num.label,num.dTypeRec,denReLabel,den.dTypeRec,RndSat.roundingMode,RndSat.overflowMode)>/
      %<quotImLabel> = %<FixPt_GetGroundValueOrNameFromDataTypeRec(quot.dTypeRec, TLC_FALSE)>;
      %%
    %else %% quot is real
      /* %<quot.label> = %<num.label> / %<denReLabel> */
      %<FixPt_Division(quot.label,quot.dTypeRec,num.label,num.dTypeRec,denReLabel,den.dTypeRec,RndSat.roundingMode,RndSat.overflowMode)>/
    %endif
    %%
  %endif
%endfunction %% DSPFixptLibDivide2
 
%%Function:DSPFixptLibNorm========================
%%
%%Abstract:
%%
%%GeneratesinlineREALorCOMPLEXfixed-pointCcodeequivalentto
%%
%%Iniscomplex:
%%PrdOut=In.re*In.re;
%%Acc=PrdOut;
%%PrdOut=In.im*In.im;
%%Acc+=PrdOut;
%%
%%Inisreal:
%%PrdOut=In*In;
%%Acc=PrdOut;
%%
%%Records"Acc"and"PrdOut"mustbereal.
%%Record"In"couldbecomplexorreal
%%
%function DSPFixptLibNorm(Acc, In, PrdOut, RndSat) Output
  %if (Acc.isComplex)
    %error "DSPFixptLibNorm: Acc record must be real."
  %endif
  %if (PrdOut.isComplex)
    %error "DSPFixptLibNorm: PrdOut record must be real."
  %endif
  /* %<Acc.label> = norm(%<In.label>) */
  %if (In.isComplex)
    %assign InLabelRe = In.label + ".re"
    %assign InLabelIm = In.label + ".im"
    %<FixPt_Multiply(PrdOut.label, PrdOut.dTypeRec, InLabelRe, In.dTypeRec, InLabelRe, In.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %<FixPt_Fix2FixAlwaysOutput(Acc.label, Acc.dTypeRec, PrdOut.label, PrdOut.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %<FixPt_Multiply(PrdOut.label, PrdOut.dTypeRec, InLabelIm, In.dTypeRec, InLabelIm, In.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %<FixPt_AccumPos_Easy(Acc.label, Acc.dTypeRec, PrdOut.label, PrdOut.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
  %else
    %<FixPt_Multiply(PrdOut.label, PrdOut.dTypeRec, In.label, In.dTypeRec, In.label, In.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
    %<FixPt_Fix2FixAlwaysOutput(Acc.label, Acc.dTypeRec, PrdOut.label, PrdOut.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
  %endif
%endfunction %% DSPFixptLibNorm
 
%%Function:DSPFixptRealAbs============================
%%
%%Abstract:
%%
%%Generatesinlinefixed-pointCcodeequivalenttoabsolute.
%%Out=abs(Inp),realinputandoutput
%%
%%Exampleusage:
%%
%%%<DSPFixptRealAbs(Out,Inp,RndSat)>
%%
%function DSPFixptRealAbs(Out, Inp, RndSat) Output
   %%
   %assign isMultiWordInput = FixPt_DataTypeIsMultiWord(Inp.dTypeRec)
   %%
   %if isMultiWordInput
     %% Multi-word less-than comparison
     {
       %assign boolDT = DataTypes.DataType[tSS_BOOLEAN]
       %<boolDT.NativeType> isNegative;
       %assign grndValueOrName = FixPt_GetGroundValueOrNameFromDataTypeRec(Inp.dTypeRec, TLC_FALSE)
       %<FixPt_MultiWordCompLT("isNegative", boolDT, Inp.label, Inp.dTypeRec, grndValueOrName, Inp.dTypeRec, "Simplest", "Saturate")>/
       if (isNegative) {
   %else
     %% Single-word less-than comparison
     if (%<Inp.label> < 0) {
   %endif
       /* Negate the (negative) value */
       %<Out.label> = %<FixPt_GetGroundValueOrNameFromDataTypeRec(Out.dTypeRec, TLC_FALSE)>;
       %<FixPt_AccumNeg_Easy(Out.label, Out.dTypeRec, Inp.label, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
     } else {
       /* Assign the (non-negative) value */
       %<FixPt_Fix2FixAlwaysOutput(Out.label, Out.dTypeRec, Inp.label, Inp.dTypeRec, RndSat.roundingMode, RndSat.overflowMode)>/
     }
   %if isMultiWordInput
     %% End brace for above temp var defines
     }
   %endif
   %%
%endfunction %%DSPFixptRealAbs
 
%endif %% _DSPFIXPTLIB_
 
%%[EOF]spcfixptlib.tlc