%% Newton Method Root Solver
% Authors: Shen Ge and Stefan San Miguel
% Purpose:
% Allows user to approximate a real root using Newton's Method. 
% User is prompted for a function and their initial guesses for the root.
% The program then completes iterations until the
% root is found or until max number of iterations, whichever is first,
% rounded to the nearest three decimal places.
% NOTE:
% Cannot be used when the derivative of the function is 0.

clear;
clc;
close all;
format long
syms x

%% CONSTANTS
% User Inputs / Calculation parameters
f(x) = input('Please enter a expression for f(x):'); % User enters a function.
d(x) = diff(f(x)); % derivative of function
guess = input('Please enter initial guess of root: ');
steps = input('Please enter maximum allowed number of iterations: ');
err = .001;

% Figure / animation parameters
min = guess-10;
max = guess+10;
step = 0.01;
pausetime = 0.5; 
xplot = min : step : max;
ftitle = 15;       
faxis = 15; 

% Data chart & figure
fprintf('\n\n Iteration      Est. Root')
figure('units','normalized','outerposition',[0 0 .5 .8])

num = double(subs(f,x,guess));
i = 1;
while abs(num)>err
    % Symbolic function value & values
    num = subs(f,x,guess); % value at original function (also numerator)
    den = subs(d,x,guess); % value at derivative (also denominator)
    tan = num+den*(xplot-guess); % tangent line values
    
    % Check whether derivative (denominator) value is 0 at guess
    if den == 0
        fprintf('\n')
        fprintf('Method cannot be used since derivative is 0 at estimated value.') 
        break
    end
    
    % Next guessed value
    guess = guess - double(num)/double(den);
    
    % Reset graph
    pause(pausetime)
    clf('reset')
    
    % Plot initial diagram of function and tangent line
    hold on;
    plot(xplot,f(xplot),'k','LineWidth',3);
    plot(xplot,tan,':b','LineWidth',3);
    % Plot old guessed value & new function value at the guess 
    plot(guess,num,'o','MarkerSize',10,'MarkerEdgeColor','k','MarkerFaceColor','red')
    plot(guess,f(guess),'o','MarkerSize',10,'MarkerEdgeColor','k','MarkerFaceColor','yellow');
    
    axis([min, max, -10,10]);
    grid on
   
    title('Iterations on f(x) - Newtons Method','fontsize',ftitle)  
    Labels = legend('f(x)','Tangent Line',' f(old estimate)','f(new estimate)');
    set(Labels,'location','northwest')
    set(Labels,'fontsize', 15);

    fprintf('\n %2i %20f', i, guess) 
    
    % Set max iteration number
    if i > steps
        break
    end
    i = i+1;
end

if i <= steps && den ~= 0
    fprintf('\n \n The approximated root is %3f after %1i iterations\n', guess, i-1) 
elseif den == 0 % Newton's method failed due to denominator being 0
    fprintf(' Newton''s method failed.\n')
else % need to iterate more
    fprintf('\nNot enough number of iterations to be accurate within error range of %1i. Set a higher iteration number.\n',err)
end        
fprintf('\n')
