function [G,C,nu,ny] = getFeedbackPath(G,C)
% Identifies feedback paths in interconnection of G and C.
%
% When specified for both, the I/O names of G and C are assumed to specify 
% how G and C are connected to each other. This function reorders the inputs
% and outputs of G and C so that the interconnection looks like:
%
%                  +--------+
%            ----->|        |----->
%                  |   G    |
%            +---->|        |-----+
%            |     +--------+     |
%         u  |                    | y
%            |     +--------+     |
%            +-----|        |<----+
%                  |   C    |
%            <-----|        |<-----
%                  +--------+
%
% The integers NU and NY specify the widths of the feedback signals u and y.

%   Author(s): P. Gahinet
%   Copyright 1986-2011 The MathWorks, Inc.
unnamedG = (all(strcmp(G.u,'')) && all(strcmp(G.y,'')));
unnamedC = (all(strcmp(C.u,'')) && all(strcmp(C.y,'')));
if unnamedG || unnamedC
   % Assume interconnection is just LFT(G,C) with no external I/Os
   [ny,nu] = iosize(G);
   if ~isequal(iosize(C),[nu ny])
      ctrlMsgUtils.error('Controllib:utility:feedback1');
   end
   if unnamedG && unnamedC
      G.u = 'u';   G.y = 'y';  C.y = 'u';  C.u = 'y';
   elseif unnamedG
      % G inherits I/O names from C
      G.u = C.y;  G.y = C.u;
   else
      % C inherits I/O names from G
      C.y = G.u;  C.u = G.y;
   end
else
   % Locate I/Os with matching names
   [iuG,iyC] = localFindMatchingNames(G.u,C.y);
   [iyG,iuC] = localFindMatchingNames(G.y,C.u);
   if isempty(iuG) || isempty(iyG)
      ctrlMsgUtils.error('Controllib:utility:feedback2');
   end
   nu = numel(iuG);   ny = numel(iyG);
   % Move u,y channels to the bottom in G
   [p,m] = iosize(G);
   itop = 1:p;  ibot = itop(iyG);  itop(:,iyG) = [];
   jtop = 1:m;  jbot = jtop(iuG);  jtop(:,iuG) = [];
   G = G([itop,ibot],[jtop,jbot]);
   % Move u,y channels to the top in C
   [p,m] = iosize(C);
   ibot = 1:p;  itop = ibot(iyC);  ibot(:,iyC) = [];
   jbot = 1:m;  jtop = jbot(iuC);  jbot(:,iuC) = [];
   C = C([itop,ibot],[jtop,jbot]);
end


function [iA,iB] = localFindMatchingNames(A,B)
% Computes indices iA,iB such that A(iA) = B(iB) and iA is sorted in
% ascending order
[~,iA,iB] = intersect(A,B);
[iA,is] = sort(iA);
iB = iB(is);