classdef HW6_Solution_RootFinding < handle
    %HW6_Solution_RootFinding Finds roots using Newton or Secant Method
    %   Detailed explanation goes here
    
    properties
        X0               % Starting point
        X1               % Second starting point fopr Secant Method
        X_root           % The zero point
        F                % Function
        F_p              % Derivative of function
        TolF=.01;        % Tolerence in Function
        TolX=.01;        % Tolerence in X
        X                % Vector of positions
        Method;          % A string set to 'Newton' or 'Secant' by methods
    end
    
    methods
        
        % Newton Solver
        function newtonMethod(obj)
            
            %Record the method used in a property
            obj.Method='Newton';
            
            %Set the first position in vector to the X0 property
            obj.X(1)=obj.X0;
            
            
            %Setup intial values so our while loop runs at least once. 
            dX=2*obj.TolX;
            dF=2*obj.TolF;
            
            %Initialize counter variable. This will be index of 
            % current X value.  
            ii=1;
            
            %This loop updates X using Newton's method until both
            %Tolerance conditions are met. 
            while (dX>obj.TolX)||(dF>obj.TolF)
                
                %Grab current X value from the vector
                CurrentX=obj.X(ii);
                
                %Calculate the new one using Newton's method:
                % X -> X + f(x)/f'(x)
                NewX=CurrentX-obj.F(CurrentX)/obj.F_p(CurrentX);
                
                %Difference between current and new X value
                dX=abs(CurrentX-NewX);
                
                %Difference between current and new Function value
                dF=abs( obj.F(CurrentX)-obj.F(NewX));
                
                %Update index to make new X the current X. 
                ii=ii+1;
                
                %Put new X into our vector
                obj.X(ii)=NewX;
            end
            
            %The last element of our vector is the found point. 
            obj.X_root=obj.X(end);
            
        end
        
         
                
        % Secant Solver
        function secantMethod(obj)
            
            %Record the method used in a property
            obj.Method='Secant';
            
            %Set the first two positions in vector to the X0,X1 property
            obj.X(1)=obj.X0;
            obj.X(2)=obj.X1;
            
            %Setup intial values so our while loop runs at least once. 
            dX=2*obj.TolX;
            dF=2*obj.TolF;
            
            %Initialize counter variable. This will be index of 
            % current X value.  We start at 2 since we need a previous
            % value
            ii=2;
            
            %This loop updates X using Newton's method until both
            %Tolerance conditions are met. 
            while (dX>obj.TolX)||(dF>obj.TolF)
                
                %Grab current and previous X value from the vector
                CurrentX=obj.X(ii);
                PrevX=obj.X(ii-1);

                %Calculate the new one using Secant method:
                % X -> X + f(x)/f'(x)
                % Where f'(x) is approximated by
                % (f(x_current)-f(x_prev))/(x_current-x_prev)
                NewX = CurrentX - obj.F(CurrentX)*(CurrentX - PrevX)/(obj.F(CurrentX)-obj.F(PrevX));
                
                %Difference between current and new X value
                dX=abs(CurrentX-NewX);
                
                %Difference between current and new Function value
                dF=abs( obj.F(CurrentX)-obj.F(NewX));
                
                %Update index to make new X the current X. 
                ii=ii+1;
                
                %Put new X into our vector
                obj.X(ii)=NewX;
            end
            
            %The last element of our vector is the found point. 
            obj.X_root=obj.X(end);
        end
        
     
        function plotUpdates(obj)
            
            %Create an empty figure
            figure;
            
            %This makes all plots add to the current figure
            hold on

            %This plots all of the line segments showing jumps
            %from current X to new X. 
            for ii=1:length(obj.X)-1
                
                %Get x and y values for line segment
                x_start=obj.X(ii);
                x_end=obj.X(ii+1);
                y_start=obj.F(obj.X(ii));
                y_end=obj.F(obj.X(ii+1));
                
                %plot the line segments.  'hr' lets us set the legend- see
                %below
                hr=plot([x_start, x_end],[y_start, y_end],'r','linewidth',2);
                
                %create the text to plot at the begining of line segment
                s=sprintf('X%d',ii-1);
                
                %This puts text on the plot
                text(x_start,y_start,s)
            end
            
            %Plot function
            
            %get a good looking start and end value for plot
            xmin=min(obj.X);
            xmax=max(obj.X);
            interval=xmax-xmin;
            
            %Create the x-points for plotting
            xvec=linspace(xmin-interval/2,xmax+interval+2);
            
            %acutally plot the function
            h=plot(xvec,obj.F(xvec),'b');
            
            %plot a dashed line at y=0
            plot(xvec,xvec*0,'k--')
            
            %label plots - always!
            xlabel('X')
            ylabel('f(X)')
            
            %Set the text to be diplayed in the legend
            h.DisplayName='Function';
            
            %get the correct text for the method and make a string
            s=sprintf('%s Updates',obj.Method)
            hr.DisplayName=s;
                        
            % A vertical dashed line at our zero
            plot([obj.X_root,obj.X_root],[obj.F(xmin),obj.F(xmax)],'k--')   
            
            % Marking our found zero with a star
            hroot=plot(obj.X_root,obj.F(obj.X_root),'p',...         
                'MarkerFaceColor',[0,0.25,0.5],...
                'MarkerEdgeColor','y',...
                'MarkerSize',12);
            
            %Set the text to be diplayed in the legend
            hroot.DisplayName='Found Root';
            
            %Diplay legend in plot. 
            legend([h,hr,hroot])

        end
        
    end
    
end

