function [b,fval,exitflag,output] = fzero(FunFcnIn,x,options,varargin)
%FZERO Scalar nonlinear zero finding.
% X = FZERO(FUN,X0) tries to find a zero of the function FUN near X0,
% if X0 is a scalar. It first finds an interval containing X0 where the
% function values of the interval endpoints differ in sign, then searches
% that interval for a zero. FUN accepts real scalar input X and returns
% a real scalar function value F, evaluated at X. The value X returned
% by FZERO is near a point where FUN changes sign (if FUN is continuous),
% or NaN if the search fails.
%
% X = FZERO(FUN,X0), where X0 is a vector of length 2, assumes X0 is an
% interval where the sign of FUN(X0(1)) differs from the sign of FUN(X0(2)).
% An error occurs if this is not true. Calling FZERO with an interval
% guarantees FZERO will return a value near a point where FUN changes
% sign.
%
% X = FZERO(FUN,X0), where X0 is a scalar value, uses X0 as a starting
% guess. FZERO looks for an interval containing a sign change for FUN and
% containing X0. If no such interval is found, NaN is returned.
% In this case, the search terminates when the search interval
% is expanded until an Inf, NaN, or complex value is found. Note: if
% the option FunValCheck is 'on', then an error will occur if an NaN or
% complex value is found.
%
% X = FZERO(FUN,X0,OPTIONS) minimizes with the default optimization
% parameters replaced by values in the structure OPTIONS, an argument
% created with the OPTIMSET function. See OPTIMSET for details. Used
% options are Display, TolX, FunValCheck, and OutputFcn. Use OPTIONS = []
% as a place holder if no options are set.
%
% [X,FVAL]= FZERO(FUN,...) returns the value of the objective function,
% described in FUN, at X.
%
% [X,FVAL,EXITFLAG] = FZERO(...) returns an EXITFLAG that describes the
% exit condition of FZERO. Possible values of EXITFLAG and the corresponding
% exit conditions are
%
% 1 FZERO found a zero X.
% -1 Algorithm terminated by output function.
% -3 NaN or Inf function value encountered during search for an interval
% containing a sign change.
% -4 Complex function value encountered during search for an interval
% containing a sign change.
% -5 FZERO may have converged to a singular point.
%
% [X,FVAL,EXITFLAG,OUTPUT] = FZERO(...) returns a structure OUTPUT
% with the number of function evaluations in OUTPUT.funcCount, the
% algorithm name in OUTPUT.algorithm, the number of iterations to
% find an interval (if needed) in OUTPUT.intervaliterations, the
% number of zero-finding iterations in OUTPUT.iterations, and the
% exit message in OUTPUT.message.
%
% Examples
% FUN can be specified using @:
% X = fzero(@sin,3)
% returns pi.
% X = fzero(@sin,3,optimset('disp','iter'))
% returns pi, uses the default tolerance and displays iteration information.
%
% FUN can also be an anonymous function:
% X = fzero(@(x) sin(3*x),2)
%
% If FUN is parameterized, you can use anonymous functions to capture the
% problem-dependent parameters. Suppose you want to solve the equation given
% in the function MYFUN, which is parameterized by its second argument A. Here
% MYFUN is an M-file function such as
%
% function f = myfun(x,a)
% f = cos(a*x);
%
% To solve the equation for a specific value of A, first assign the value to A.
% Then create a one-argument anonymous function that captures that value of A
% and calls MYFUN with two arguments. Finally, pass this anonymous function to
% FZERO:
%
% a = 2; % define parameter first
% x = fzero(@(x) myfun(x,a),0.1)
%
% Limitations
% X = fzero(@(x) abs(x)+1, 1)
% returns NaN since this function does not change sign anywhere on the
% real axis (and does not have a zero as well).
% X = fzero(@tan,2)
% returns X near 1.5708 because the discontinuity of this function near the
% point X gives the appearance (numerically) that the function changes sign at X.
%
% See also ROOTS, FMINBND, FUNCTION_HANDLE.
% Copyright 1984-2004 The MathWorks, Inc.
% $Revision: 5.33.4.8 $ $Date: 2004/07/05 17:01:32 $
% This algorithm was originated by T. Dekker. An Algol 60 version,
% with some improvements, is given by Richard Brent in "Algorithms for
% Minimization Without Derivatives", Prentice-Hall, 1973. A Fortran
% version is in Forsythe, Malcolm and Moler, "Computer Methods
% for Mathematical Computations", Prentice-Hall, 1976.
% Initialization
fcount = 0;
iter = 0;
intervaliter = 0;
exitflag = 1;
procedure = ' ';
defaultopt = struct('Display','notify','TolX',eps,'FunValCheck','off','OutputFcn',[]);
% If just 'defaults' passed in, return the default options in X
if nargin==1 && nargout <= 1 && isequal(FunFcnIn,'defaults')
b = defaultopt;
return
end
if nargin < 2,
error('MATLAB:fzero:NotEnoughInputs',...
'FZERO requires at least two input arguments');
end
% initialization
if nargin < 3,
options = [];
end
% Check for non-double inputs
if ~isa(x,'double')
error('MATLAB:fzero:NonDoubleInput', ...
'FZERO only accepts inputs of data type double.')
end
tol = optimget(options,'TolX',defaultopt,'fast');
funValCheck = strcmp(optimget(options,'FunValCheck',defaultopt,'fast'),'on');
printtype = optimget(options,'Display',defaultopt,'fast');
switch printtype
case 'notify'
trace = 1;
case {'none', 'off'}
trace = 0;
case 'iter'
trace = 3;
case 'final'
trace = 2;
otherwise
trace = 1;
end
% Handle the output
outputfcn = optimget(options,'OutputFcn',defaultopt,'fast');
if isempty(outputfcn)
haveoutputfcn = false;
else
haveoutputfcn = true;
% Convert to function handle as needed.
outputfcn = fcnchk(outputfcn,length(varargin));
end
% Convert to function handle as needed.
[FunFcn,msg] = fcnchk(FunFcnIn,length(varargin));
if ~isempty(msg)
error('MATLAB:fzero:InvalidFUN',msg)
end
% We know fcnchk succeeded if we got to here
if isa(FunFcn,'inline')
if isa(FunFcnIn,'inline')
Ffcnstr = inputname(1); % name of inline object such as f where f=inline('x*2');
if isempty(Ffcnstr) % inline('sin(x)')
Ffcnstr = formula(FunFcn); % Grab formula, no argument name
end
Ftype = 'inline object';
else % not an inline originally (string expression).
Ffcnstr = FunFcnIn; % get the string expression
Ftype = 'expression';
end
elseif isa(FunFcn,'function_handle') % function handle
Ffcnstr = func2str(FunFcn); % get the name passed in
Ftype = 'function_handle';
else % Not converted, must be m-file or builtin
Ffcnstr = FunFcnIn; % get the name passed in
Ftype = 'function';
end
% Add a wrapper function to check for Inf/NaN/complex values
if funValCheck
% Add a wrapper function, CHECKFUN, to check for NaN/complex values without
% having to change the calls that look like this:
% f = funfcn(x,varargin{:});
% x is the first argument to CHECKFUN, then the user's function,
% then the elements of varargin. To accomplish this we need to add the
% user's function to the beginning of varargin, and change funfcn to be
% CHECKFUN.
varargin = {FunFcn, varargin{:}};
FunFcn = @checkfun;
end
% Initialize the output function.
if haveoutputfcn
[xOutputfcn, optimValues, stop] = callOutputFcn(outputfcn,[],'init',fcount,iter,intervaliter, ...
[],procedure,[],[],[],[],varargin{:});
if stop
[b,fval,exitflag,output] = cleanUpInterrupt(xOutputfcn,optimValues);
if trace > 0
disp(output.message)
end
return;
end
end
if (~i