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

%   Copyright 2003-2023 The MathWorks, Inc.

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

% Calculate the S-parameters: S = (Z*Kinv+K)\(Z*Kinv-K)
% see Young, Digital Signal Integrity, (4.13)
[K,Kinv] = referenceImpedanceArrays(z_params,z0);
zKinv = pagemtimes(z_params,Kinv);
s_params = pagemldivide(zKinv+K,zKinv-K);
