function [val, sizes] = evalUserFuns(func, x, sizes, IsConstraint, funcName)
%EVALUSERFUNS Evaluate user function "func" at point "x".
%   If "IsConstraint" is true, then func returns 4 outputs
%       [c, ceq, gc, gceq] which are stored in val{1}, val{2}, val{3}, and
%           val{4}
%   If "IsConstraint" is false, then func returns 2 outputs
%       [f, g] which are stored in val{1} and val{2}

%   Copyright 2023 The MathWorks, Inc.

% Reshape X into the size required by the user-functions
x = reshape(x,sizes.xShape);

evalME = MException(message('optim:checkGradients:EvaluationError'));
if IsConstraint % Evaluate constraint
    try
        [c,ceq,gc,gceq] = func(x);
    catch userFcn_ME
        if strcmp(userFcn_ME.identifier, 'MATLAB:maxlhs') || strcmp(userFcn_ME.identifier, 'MATLAB:TooManyOutputs') % Less than 4 outputs from 'func'
            error(message('optim:checkGradients:InsufficientOutput', funcName, funcName, 4));
        end
        userFcn_ME = addCause(userFcn_ME,evalME);
        rethrow(userFcn_ME)
    end
    sizes.mNonlinIneq = numel(c);
    sizes.mNonlinEq = numel(ceq);
    val = {c, ceq, gc, gceq};
else % Evaluate objective
    try
        [f, g] = func(x);
    catch userFcn_ME
        if strcmp(userFcn_ME.identifier, 'MATLAB:maxlhs') || strcmp(userFcn_ME.identifier, 'MATLAB:TooManyOutputs') % Less than 2 outputs from 'func'
            error(message('optim:checkGradients:InsufficientOutput', funcName, funcName, 2));
        end
        userFcn_ME = addCause(userFcn_ME,evalME);
        rethrow(userFcn_ME)
    end
    sizes.mNonlinIneq = 0;
    sizes.mNonlinEq = 0;

    sizes.nFun = numel(f);
    val = {f, g};
end
