function D = tf(Dnum,Dden,Ts)
% Build SISO dynamic LFT model for TF(NUM,DEN,Ts) given static models of 
% the row vectors NUM and DEN.

%   Author(s): P. Gahinet
%   Copyright 2009-2017 The MathWorks, Inc.
[~,lnum] = iosize(Dnum);
[~,lden] = iosize(Dden);
den1 = getsubsys(Dden,1,1,'smin');  % leading denominator coefficient

if allfinite(Dnum.IC) && allfinite(Dden.IC)
   if double(den1)==0 || lnum>lden
      % Requires den(1)~=0 and length(num)<=length(den)
      error(message('Control:lftmodel:tf3'))
   elseif lden==1
      % Static
      Da = ltipack.lftdataM([],ltipack.LFTBlockWrapper.emptyBlockList());
      D = dss(Da,[],[],mtimes(Dnum,inv(Dden)),[],Ts);
   else
      nx = lden-1;
      if lnum<lden && isequal(den1.IC,1)
         % Strictly proper with monic denominator: Use companion realization
         IC = Dden.IC;   [rs,cs] = size(IC);
         AB = ltipack.lftdataM([-IC(1,2:lden) 1 -IC(1,lden+1:cs) ; ...
            eye(nx-1) zeros(nx-1,cs-nx+1) ; ...
            IC(2:rs,2:lden) zeros(rs-1,1) IC(2:rs,lden+1:cs)],Dden.Blocks);
         IC = Dnum.IC;   [rs,cs] = size(IC);
         CD = ltipack.lftdataM([zeros(rs,lden-lnum-1) IC(:,1:lnum) zeros(rs,1) IC(:,lnum+1:cs)],...
            Dnum.Blocks);
         ABCD = iocat(1,AB,CD);
      else
         % Bi-proper or non-monic: Use inversion-free formula to avoid unnecessary block duplication
         IC = Dden.IC;   [~,cs] = size(IC);
         M1 = ltipack.lftdataM([[zeros(nx,1) eye(nx) zeros(nx,cs-nx-1)] ; IC],Dden.Blocks);
         IC = Dnum.IC;   [rs,cs] = size(IC);
         M2 = ltipack.lftdataM([[eye(nx) zeros(nx,cs+1-lnum)] ; zeros(rs,lden-lnum) IC],Dnum.Blocks);
         ABCD = mtimes(M2,inv(M1),false(1,2));
      end
      % Build dynamic LFT model
      IC = ABCD.IC;
      [rs,cs] = size(IC);
      Dss = ltipack.ssdata(IC(1:nx,1:nx),IC(1:nx,nx+1:cs),...
         IC(nx+1:rs,1:nx),IC(nx+1:rs,nx+1:cs),[],Ts);
      D = ltipack.lftdataSS(Dss,ABCD.Blocks);
   end
else
   Dss = ltipack.ssdata([],zeros(0,1),zeros(1,0),NaN,[],Ts);
   D = ltipack.lftdataSS(Dss,ltipack.LFTBlockWrapper.emptyBlockList());
end
