function SSsys = ss(varargin)
%SS  Create state-space models or convert LTI model to state space.
%       
%   You can create a state-space model by: 
%    SYS = SS(A,B,C,D)       Continuous-time model
%    SYS = SS(A,B,C,D,T)     Discrete-time model with sampling time T
%                            (Set T=-1 if undetermined)
%    SYS = SS                Default empty SS object
%    SYS = SS(D)             Static gain matrix
%    SYS = SS(A,B,C,D,LTI)   State-space model with LTI properties 
%                            inherited from the system LTI (can be 
%                            SS, TF, or ZPK)
%   All the above syntaxes may be followed by Property/Value pairs.  
%   (Type "help ltiprops" for details on assignable properties). 
%   Setting D=0 is interpreted as the zero matrix of adequate 
%   dimensions.  The output SYS is an SS object.
%
%   SYS_SS = SS(SYS)  converts an arbitrary LTI model SYS to state space,
%   i.e., computes a state-space realization SYS_SS of SYS.
%
%   See also   SET, SSDATA, DSS, TF, ZPK.

% Note:
%      SYS_SS = SS(SYS,METHOD)  allows users to supply their own 
%      state-space realization algorithm via the string METHOD.
%      For instance,
%           SS(sys,'myway')
%      executes
%           [a,b,c,d] = myway(sys.num,sys.den)
%      to perform the conversion to state space.  User-specified functions 
%      should follow this syntax.


%      Author(s): P. Gahinet, 5-1-96
%      Copyright (c) 1986-97 by The MathWorks, Inc.
%      $Revision: 1.6 $  $Date: 1997/04/09 00:29:46 $

% Effect on other properties: keep all LTI parent fields

sys = varargin{1};
if isa(sys,'tf'),   
  % Normal call
  ni = nargin;
  if ni>2,
     error('Conversion TF to SS: too many input arguments.');
  elseif ~isproper(sys),
     error('Improper system: conversion to state space not possible');
  elseif ni==2 & ~isstr(varargin{2}),
     error('Conversion TF to SS: second argument must be a string');
  end
else
  % Syntax ss(a,b,c,d,lti) with lti of class TF
  nlti = 0;
  for i=1:length(varargin),
     arg = varargin{i};
     nlti = nlti + isa(arg,'lti');
     if isa(arg,'tf'),
        varargin{i} = arg.lti;
     end
  end
  if nlti > 1, 
    error('SS cannot be called with several LTI arguments');
  end
  SSsys = ss(varargin{:});
  return
end

% Extract components
num = sys.num;
den = sys.den;
[Out,In] = size(num);

% Quick exit in simple cases
if In*Out==0,
   % Empty system
   SSsys = ss([],[],[],zeros(Out,In),sys.lti);  
   return
elseif ni==2,
   % User-supplied conversion method
   [a,b,c,d] = feval(varargin{2},num,den);
   SSsys = ss(a,b,c,d,sys.lti);   
   return
end
   
% Normalize leading denominator coefficient to 1
for i=1:Out*In,
   d1 = den{i}(1);
   den{i} = den{i}/d1;
   num{i} = num{i}/d1;
end

% Handle various cases
if Out*In==1 | isequal(den{:}),
  % Common denominator
  trpose = (Out<In);
  if trpose, num = num'; end
  [a,b,c,d] = comden(num,den{1});
  balflag = 0;  % No further balancing needed

elseif min(In,Out)==1,   
  % SIMO or MISO
  trpose = (Out<In);
  poles = cell(max(In,Out),1);
  for k=1:In*Out,
     poles{k} = mroots(den{k});
  end
  [a,b,c,d] = simoreal(num(:),den(:),polpart(poles));
  balflag = 1;

else
  % General MIMO: can proceed either by column-wise concatenation 
  % of SIMO realizations, or by row-wise concatenation of MISO
  % realizations.  First determine which approach yields the lowest 
  % order
  poles = cell(Out,In);
  for k=1:In*Out,
     poles{k} = mroots(den{k});
  end

  % Column-wise degree
  [pmap,cdeg] = polpart(poles);

  % Row-wise degree
  [rmap,rdeg] = polpart(poles');

  if rdeg<cdeg,
    % Transpose since this yields a lower order
    trpose = 1;  num = num';  den = den';  pmap = rmap;
  else
    trpose = 0;  
  end
  [a,b,c,d] = simoreal(num,den,pmap);
  balflag = 1;

end


% Transpose back if necessary
% Re: Use .' to be correct for complex systems
if trpose,
  btmp = b;
  a = a.';   b = c.';   c = btmp.';   d = d.';
end

SSsys = ss(a,b,c,d,sys.lti);

% Perform additional balancing if appropriate
if balflag, 
   SSsys = ssbal(SSsys);
end

% end ../@tf/ss.m


