function [D1,D2,ElimFlag] = mtimesDelay(D1,D2,ScalarFlag)
% Delay management for D1*D2. On output, D1 contains the delays of the series
% connection. Note: The delays of D2 are not updated (not looked up again).

% Copyright 1986-2014 The MathWorks, Inc.
ElimFlag = false;
Delay = D1.Delay;
if ScalarFlag(1) || (~ScalarFlag(2) && utIsIOScaling(D1))
   % Scalar factor D1 or output scaling D1 with nonscalar D2: external delays
   % commute with D1 and can be pushed to the result's outputs
   % RE: Give priority to scalar factor, e.g., in diag([1 0 1]) * tf(1,[1 0])
   Delay.Input = D2.Delay.Input;
   Delay.Output = diag(getIODelay(D1,'total')) + D2.Delay.Output;
   Delay.IO = D2.Delay.IO;
elseif ScalarFlag(2) || utIsIOScaling(D2)
   % Scalar factor D2 or input scaling D2 with nonscalar D1: external delays
   % commute with D2 and can be pushed to the result's inputs
   Delay.Output = D1.Delay.Output;
   Delay.Input = diag(getIODelay(D2,'total')) + D1.Delay.Input;
   Delay.IO = D1.Delay.IO;
else
   % Absorb external delays along inner dimension into I/O delay matrix
   [ny,~] = size(D1.Delay.IO);
   [nin,nu] = size(D2.Delay.IO);
   Dm1 = D1.Delay.IO + repmat(D1.Delay.Input.',[ny 1]);
   Dm2 = D2.Delay.IO + repmat(D2.Delay.Output,[1 nu]);
   % D1*D2 is representable as a system with I/O delays if DxDy([Dm1;-Dm2'])=0
   Dm12 = [Dm1;-Dm2'];
   DxDy = diff(diff(Dm12,1,1),1,2);
   if nin==0,
      Dm = zeros(ny,nu);
   elseif norm(DxDy,1)<=1e3*eps*norm(Dm12,1)
      % Product is representable as LTI model with delays
      Dm = Dm1(:,ones(1,nu))+Dm2(ones(1,ny),:);
   else
      % Extract parts of Dm1,Dm2 satisfying DxDy([Dm1;-Dm2'])=0
      % and try eliminating remaining delays
      try
         a = min(Dm1,[],2);
         b = min(Dm2,[],1);
         Dm = a(:,ones(1,nu)) + b(ones(1,ny),:);
         D1 = elimDelay(D1,[],[],Dm1-a(:,ones(1,nin)));
         D2 = elimDelay(D2,[],[],Dm2-b(ones(1,nin),:));
         ElimFlag = true;
      catch  %#ok<*CTCH>
         ctrlMsgUtils.error('Control:combination:InternalDelaysConvert2SS')
      end
   end
   Delay.Input = D2.Delay.Input;
   Delay.Output = D1.Delay.Output;
   Delay.IO = Dm;
end
D1.Delay = Delay;