function fsys = frdfun(fun,sys)
% FRDFUN   Applies function to frequency response data.
%
%   FSYS = FRDFUN(FUN,SYS) applies the function FUN to the FRD model SYS.
%   The function FUN must take a single matrix and return a scalar, vector, 
%   or matrix of fixed size across frequency. The function is applied to
%   the frequency response value at each frequency and the results are 
%   collected in the output FRD model FSYS. When SYS is GENFRD or UFRD, 
%   it is first converted to FRD.
%
%   Example: Compute an FRD model whose data is the magnitude of 
%   the frequency response in SYS.
%      fsys = frdfun(@abs,sys)
%
%   Example: Return the peak gain of the frequency response as
%   a function of frequency.
%      gpeak = frdfun(@norm,sys)
%
%   Example: Zero out the off-diagonal part of the 3x3 FRD model SYS.
%      fun = @(m) diag(diag(m));
%      sysdiag = frdfun(@fun,sys)
%
%   See also FRD.

%   Copyright 2019 The MathWorks, Inc.
if ~(ischar(fun) || isstring(fun) || isa(fun, 'function_handle'))
   error(message('Control:transformation:frdfun3'))
end
try
   % Apply function to data
   fsys = frdfun_(@(x) localFEVAL(fun,x),sys);
catch ME
   throw(ME)
end
% Metadata
if isequal(fsys.IOSize_,sys.IOSize_)
   % Preserve I/O metadata
   fsys.Name_ = '';  fsys.Notes_ = strings(0,1);  fsys.UserData = [];
else
   % Clear everything
   fsys = resetMetaData(fsys);
end

%----------------
function y = localFEVAL(fun,x)
try
   y = feval(fun,x);
catch ME
   error(message('Control:transformation:frdfun4',ME.message))
end