function z_params = s2z(s_params,z0)
%S2Z Convert S-parameters to Z-parameters
%   Z_PARAMS = S2Z(S_PARAMS, Z0) converts the scattering parameters
%   S_PARAMS into the impedance parameters Z_PARAMS.
%
%   S_PARAMS is a complex NxNxM array of M N-port S-parameters. Z0 is the
%   reference impedance, the default is 50 ohms. The output Z_PARAMS is a
%   complex NxNxM array of M N-port Z-parameters.
%
%   Z0 is specified as one of the following:
%   - Scalar used for all ports and frequencies
%   - Vector of length size(S_PARAMS,1), for per-port impedances
%   - Vector of length size(S_PARAMS,3), for per-frequency impedances
%
%   If size(S_PARAMS,1) == size(S_PARAMS,3) == numel(Z0), then Z0
%   specifies per-port impedances, unless Z0 is a 3-D array.
%
%   See also Z2S, S2Y, S2H, S2ABCD, Y2Z, H2Z, ABCD2Z

%   Copyright 2003-2023 The MathWorks, Inc.

arguments
    s_params {mustBeNumeric,mustBeNonempty,mustBeNonNan, ...
        rf.internal.mustBeVectorOrNxNxM}
    z0 {mustBeNumeric,mustBeNonempty,mustBeFinite, ...
        rf.internal.mustBeRealValued, ...
        rf.internal.mustBeDataSized(z0,s_params)} = 50
end
if isvector(s_params)
    s_params = reshape(s_params,1,1,[]);
end

% Calculate the Z-parameters: Z = K*(I+S)*inv(I-S)*K
% see Young, Digital Signal Integrity, (4.14)
I = eye(size(s_params,1));
K = referenceImpedanceArrays(s_params,z0);
z_params = pagemtimes(pagemrdivide(pagemtimes(K,I+s_params),I-s_params),K);
