function [D,SingularFlag] = inv(D)
% Computes inv(D) for FINITE D.

%   Copyright 2020-2023 The MathWorks, Inc.
[a,b1,b2,c1,c2,d11,d12,d21,d22,e] = getBlockData(D);
nu = size(d11,2); % d11 is square
nfd = size(d22,1);
nx = size(a,1);
u0 = D.u0;  y0 = D.y0;
% Swap input and output offsets
D.u0 = [y0(1:nu,:);D.u0(nu+1:end,:)];
D.y0 = [u0(1:nu,:);D.y0(nu+1:end,:)];

% Inverse of delays is not causal
if any(D.Delay.Input) || any(D.Delay.Output)
   error(message('Control:transformation:inv1'))
end

if nx==0 && nfd==0
   % Static case: invert D
   d11i = matlab.internal.math.nowarn.inv(d11);
   if allfinite(d11i)
      D.d = d11i;
      SingularFlag = false;
   else
      D = createGain(D,NaN(nu));
      SingularFlag = true;
   end
else
   % Build implicit model of inverse
   Znu = zeros(nu,'like',a);
   ai = [a b1;c1 d11];
   ei = ltipack.util.blkdiag(e,Znu);
   p = dmperm((ai~=0) | (ei~=0));
   if any(p==0)
      % Pencil Ai-s*Ei is structurally singular
      if nfd>0
         % Inverse has anti-delays
         error(message('Control:transformation:inv1'))
      else
         % D is normal-rank deficient, inverse is not finite
         D = createGain(D,NaN(nu));
         SingularFlag = true;
      end
   else
      % Augment state vector to [x;u]
      Inu = eye(nu,'like',a);
      D.a = ai;
      D.e = ei;
      D.b = [zeros(nx,nu,'like',a) b2; -Inu d12];
      D.c = [zeros(nu,nx,'like',a) Inu;c2 d21];
      D.d = ltipack.util.blkdiag(Znu,d22);
      D.x0 = [D.x0 ; u0(1:nu,:)];
      D.dx0 = [D.dx0 ; zeros(nu,1)];
      D.Scaled = false;
      SingularFlag = false;
   end
end

