function y = sosfilt(SOS, x)
% Embedded MATLAB Library function.
%
% Limitations:
% No known limitations.

% $INCLUDE(DOC) toolbox/eml/lib/dsp/sosfilt.m $
% Copyright 2002-2004 The MathWorks, Inc.
% $Revision: 1.1.6.5 $  $Date: 2004/08/10 01:33:57 $

eml_assert(nargin > 1, 'error', 'Not enough input arguments.');
eml_assert(isfloat(SOS), 'error', ['Function ''sosfilt'' is not defined for values of class ''' class(SOS) '''.']);

if ((size(SOS,1) > 1) && (size(SOS,2)>1))
    eml_assert(size(SOS, 2) == 6,'error','Size of SOS matrix must be Mx6.');
else
    eml_assert(length(SOS(:)) == 6,'error','Size of SOS matrix must be Mx6.');
end

RTN = 0;
eml_ignore('d = pwd;');
eml_ignore('cd(fullfile(matlabroot,''toolbox'',''signal'',''signal''));');
eml_ignore([...
    ' y = sosfilt(SOS,x);',10 ...
]);
eml_ignore('RTN = 1;');
eml_ignore('cd(d);');
if RTN, return; end

if isempty(x)
    % when input is empty, output is the same as input.
    y = x;
else
    if (size(x,1) == 1) && (size(x,2) > 1) % x is a row vector
        xused = x.';
    else
        xused = x;
    end
    numSamps = size(xused,1);
    numChans = size(xused,2);
    outCplx = ~(isreal(xused) && isreal(SOS));
    switch class(xused)
        case 'single'
            eml_cdecl(yused, 'single', outCplx, size(xused));
        case 'double'
            eml_cdecl(yused, 'double', outCplx, size(xused));
    end

    if ((size(SOS,1) > 1) && (size(SOS,2)>1))
        numSections = size(SOS, 1);
        % size of state vector 'z' is numSection*2.
        if (outCplx)
            z = complex(zeros(numChans*numSections*2, 1),zeros(numChans*numSections*2, 1));
        else
            z = zeros(numChans*numSections*2, 1);
        end

        SOSBQ5 = SOS(:,[1 2 3 5 6]);
        for i = 1:numSections
            if (SOS(i,4) ~= 1)
              SOSBQ5(i,:) = SOSBQ5(i,:) ./ SOS(i,4);
            end
        end
        SOSused = SOSBQ5.';
        switch class(xused)
            case 'single'
                if (isreal(SOS) && isreal(xused))
                    cc.MWDSP_BQ5_DF2T_1fpf_Nsos_RR(xused,eml_wref(yused),z, eml_wref(SOSused), numSamps, numChans, numSections);
                elseif (~isreal(SOS) && isreal(xused))
                    cc.MWDSP_BQ5_DF2T_1fpf_Nsos_RC(xused,eml_wref(yused),z, eml_wref(SOSused), numSamps, numChans, numSections);
                elseif (isreal(SOS) && ~isreal(xused))
                    cc.MWDSP_BQ5_DF2T_1fpf_Nsos_CR(xused,eml_wref(yused),z, eml_wref(SOSused), numSamps, numChans, numSections);
                else
                    cc.MWDSP_BQ5_DF2T_1fpf_Nsos_CC(xused,eml_wref(yused),z, eml_wref(SOSused), numSamps, numChans, numSections);
                end
            case 'double'
                if (isreal(SOS) && isreal(xused))
                    cc.MWDSP_BQ5_DF2T_1fpf_Nsos_DD(xused,eml_wref(yused),z, eml_wref(SOSused), numSamps, numChans, numSections);
                elseif (~isreal(SOS) && isreal(xused))
                    cc.MWDSP_BQ5_DF2T_1fpf_Nsos_DZ(xused,eml_wref(yused),z, eml_wref(SOSused), numSamps, numChans, numSections);
                elseif (isreal(SOS) && ~isreal(xused))
                    cc.MWDSP_BQ5_DF2T_1fpf_Nsos_ZD(xused,eml_wref(yused),z, eml_wref(SOSused), numSamps, numChans, numSections);
                else
                    cc.MWDSP_BQ5_DF2T_1fpf_Nsos_ZZ(xused,eml_wref(yused),z, eml_wref(SOSused), numSamps, numChans, numSections);
                end
        end
    else
      if (outCplx)
        z = complex(zeros(numChans*2, 1),zeros(numChans*2, 1));
      else
        z = zeros(numChans*2, 1);
      end
      SOSBQ5 = SOS([1 2 3 5 6]);
      if (SOS(4) ~= 1)
        SOSBQ5 = SOSBQ5 ./ SOS(4);
      end

      switch class(xused)
            case 'single'
                if (isreal(SOS) && isreal(xused))
                    cc.MWDSP_BQ5_DF2T_1fpf_1sos_RR(xused,eml_wref(yused),z, eml_wref(SOSBQ5), numSamps, numChans);
                elseif (~isreal(SOS) && isreal(xused))
                    cc.MWDSP_BQ5_DF2T_1fpf_1sos_RC(xused,eml_wref(yused),z, eml_wref(SOSBQ5), numSamps, numChans);
                elseif (isreal(SOS) && ~isreal(xused))
                    cc.MWDSP_BQ5_DF2T_1fpf_1sos_CR(xused,eml_wref(yused),z, eml_wref(SOSBQ5), numSamps, numChans);
                else
                    cc.MWDSP_BQ5_DF2T_1fpf_1sos_CC(xused,eml_wref(yused),z, eml_wref(SOSBQ5), numSamps, numChans);
                end
            case 'double'
                if (isreal(SOS) && isreal(xused))
                    cc.MWDSP_BQ5_DF2T_1fpf_1sos_DD(xused,eml_wref(yused),z, eml_wref(SOSBQ5), numSamps, numChans);
                elseif (~isreal(SOS) && isreal(xused))
                    cc.MWDSP_BQ5_DF2T_1fpf_1sos_DZ(xused,eml_wref(yused),z, eml_wref(SOSBQ5), numSamps, numChans);
                elseif (isreal(SOS) && ~isreal(xused))
                    cc.MWDSP_BQ5_DF2T_1fpf_1sos_ZD(xused,eml_wref(yused),z, eml_wref(SOSBQ5), numSamps, numChans);
                else
                    cc.MWDSP_BQ5_DF2T_1fpf_1sos_ZZ(xused,eml_wref(yused),z, eml_wref(SOSBQ5), numSamps, numChans);
                end
        end
    end
    if (size(x,1) == 1) && (size(x,2) > 1) % x is a row vector
        y = yused.';
    else
        y = yused;
    end

end
