function rootfinding

opt = 3;
if opt==1
    % simple example - converges for both bisection/Newton.
    f = @(x) exp(x)-2;
    fp = @(x) exp(x);
    xroot = log(2);
    
elseif opt==2    
    % function with zero derivative at the root
    % - bisection can't find change in sign
    % - Newton slows

    f = @(x) x.^2;
    fp = @(x) 2*x;
    xroot = 0;
    
elseif opt==3    
    % example showing Newton is sensitive to the starting guess
    % - f'(x^*) = 0, f''(x^*) != 0
    % - if 1/3 < x0 != 1/2, converge but slow
    % - if x0 < 1/3, failure
    % - if x0 = 1/2, converges in two iterates!
    %
    % bisection also fails due to multiple roots
    
    f = @(x) x.*(1-x).^2;
    fp = @(x) -2*x.*(1 - x) + (1-x).^2;
    xroot = 1;
end

% plot function
x = linspace(-2,2,1000);
plot(x,f(x),'b-','linewidth',2)
hold on
plot(x,x*0,'r--','linewidth',2)
grid on
set(gca,'fontsize',15)
pause
close

%% bisection

tol = 1e-14;
a = -1.1;
b =  1.5;

[x,iter,xhist] = bisection(f,a,b,tol);

semilogy(abs(xroot-xhist),'.-')
hold on
semilogy(2*2.^(-(1:length(xhist))),'x--');

%% regula falsi

[x,iter,xhist] = regulafalsi(f,a,b,tol);
semilogy(abs(xroot-xhist),'.-')

%% newton

x0 = .33;
[x,iter,xhist] = newton(f,fp,x0,tol);
semilogy(tol+abs(xroot-xhist),'o-')

legend('Bisection','Bisection rate','Regula Falsi','Newton')
set(gca,'fontsize',15)

return


function [c,k,chist] = bisection(f,a,b,tol)

maxit = 25;
if f(a)*f(b)>0
    disp('There may not be a root in this interval');
    c = nan(maxit,1);
    k = nan(maxit,1); 
    chist = nan(maxit,1);
    return
end

c = 0.5*(a+b);
k = 1;
chist = [];
while abs(f(c))>tol  && k < maxit 
    fprintf('Bisection error/f(x) at iterate %3d: %20.14f %10.7e\n', k, c, f(c));    
    if f(c)*f(a)<0
        b = c;
    else
        a = c;
    end
    c = 0.5*(a+b);
    chist(k) = c;
    k = k+1;
end
fprintf('\n');

return



function [c,k,xhist] = regulafalsi(f,a,b,tol)

maxit = 25;

fa = f(a);
fb = f(b); % evaluate f at the bracket endpoints
k = 0; 
fc = inf; % initialize loop control variables
while (abs(fc)>tol) && (k < maxit)        
    c = (a*fb - b*fa)/(fb-fa); % generate new root estimate
    fc = f(c); % evaluate function at new root estimate
    
    if fa*fc < 0
        b=c; fb=fc; % update new bracket
    else
        a=c; fa=fc; 
    end    
    k = k+1;    
    xhist(k) = c;
end



function [x0,k,xhist] = newton(f,fp,x0,tol)

maxit = 50;

k = 1;
while (abs(f(x0))>tol && (k<maxit))
    fprintf('Newton error/f(x) at iterate %3d: %20.14f %10.7e\n', k, x0, f(x0));    
    x0 = x0 - f(x0)/fp(x0);    
    xhist(k) = x0;       
    k = k+1;
end

xhist(k) = x0;

return



