function varargout = Rootfinding(varargin)
% ROOTFINDING Application M-file for Rootfinding.fig
%    FIG = ROOTFINDING launch Rootfinding GUI.
%    ROOTFINDING('callback_name', ...) invoke the named callback.

% Last Modified by GUIDE v2.5 21-Sep-2004 14:21:10

if nargin == 0  % LAUNCH GUI

	fig = openfig(mfilename,'reuse');

	% Generate a structure of handles to pass to callbacks, and store it. 
	handles = guihandles(fig);
    % Initialization of fcn_data = [indexfcn,a,b,c1,c2]
    handles.indexfcn = 1;
    handles.const_a = 0;
    handles.const_b = 2;
    handles.const_c1 = 1;
    handles.const_c2 = .5;
    handles.fcn_data = [handles.indexfcn, handles.const_a, handles.const_b, handles.const_c1, handles.const_c2]; 
    % Initialization of itert_data = [eps,itmax]
    handles.const_eps = .001;
    handles.const_itmax = 10;
    handles.itert_data = [handles.const_eps, handles.const_itmax]; 
%    handles
	guidata(fig, handles);

	if nargout > 0
		varargout{1} = fig;
	end

elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK

	try
		if (nargout)
			[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard
		else
			feval(varargin{:}); % FEVAL switchyard
		end
	catch
		disp(lasterr);
	end

end


%| ABOUT CALLBACKS:
%| GUIDE automatically appends subfunction prototypes to this file, and 
%| sets objects' callback properties to call them through the FEVAL 
%| switchyard above. This comment describes that mechanism.
%|
%| Each callback subfunction declaration has the following form:
%| <SUBFUNCTION_NAME>(H, EVENTDATA, HANDLES, VARARGIN)
%|
%| The subfunction name is composed using the object's Tag and the 
%| callback type separated by '_', e.g. 'slider2_Callback',
%| 'figure1_CloseRequestFcn', 'axis1_ButtondownFcn'.
%|
%| H is the callback object's handle (obtained using GCBO).
%|
%| EVENTDATA is empty, but reserved for future use.
%|
%| HANDLES is a structure containing handles of components in GUI using
%| tags as fieldnames, e.g. handles.figure1, handles.slider2. This
%| structure is created at GUI startup using GUIHANDLES and stored in
%| the figure's application data using GUIDATA. A copy of the structure
%| is passed to each callback.  You can store additional information in
%| this structure at GUI startup, and you can change the structure
%| during callbacks.  Call guidata(h, handles) after changing your
%| copy to replace the stored original so that subsequent callbacks see
%| the updates. Type "help guihandles" and "help guidata" for more
%| information.
%|
%| VARARGIN contains any extra arguments you have passed to the
%| callback. Specify the extra arguments by editing the callback
%| property in the inspector. By default, GUIDE sets the property to:
%| <MFILENAME>('<SUBFUNCTION_NAME>', gcbo, [], guidata(gcbo))
%| Add any extra arguments after the last argument, before the final
%| closing parenthesis.


% --------------------------------------------------------------------
function varargout = FcnPopup_Callback(h, eventdata, handles, varargin)

indexfcn = get(h,'Value');
handles.indexfcn = indexfcn;
handles.fcn_data = [handles.indexfcn, handles.const_a, handles.const_b, handles.const_c1, handles.const_c2];
guidata(h,handles); % Save the handles structure after adding data
%disp('FcnPopup')

% --------------------------------------------------------------------
function varargout = LeftEndEditText_Callback(h, eventdata, handles, varargin)

const_a = eval(get(handles.LeftEndEditText,'string'));
handles.const_a = const_a;
handles.fcn_data = [handles.indexfcn, handles.const_a, handles.const_b, handles.const_c1, handles.const_c2];
guidata(h,handles); % Save the handles structure after adding data
Rootfinding('FcnPopup_Callback',handles.FcnPopup,[],guidata(handles.FcnPopup))
%disp('LeftEndEditText')

% --------------------------------------------------------------------
function varargout = RightEndEditText_Callback(h, eventdata, handles, varargin)

const_b = eval(get(handles.RightEndEditText,'string'));
handles.const_b = const_b;
handles.fcn_data = [handles.indexfcn, handles.const_a, handles.const_b, handles.const_c1, handles.const_c2];
guidata(h,handles); % Save the handles structure after adding data
Rootfinding('FcnPopup_Callback',handles.FcnPopup,[],guidata(handles.FcnPopup))
%disp('RightEndEditText')

% -------------------------------------------------------------------
function varargout = Constant_c1_EditText_Callback(h, eventdata, handles, varargin)

const_c1 = eval(get(handles.Constant_c1_EditText,'string'));
handles.const_c1 = const_c1;
handles.fcn_data = [handles.indexfcn, handles.const_a, handles.const_b, handles.const_c1, handles.const_c2];
guidata(h,handles); % Save the handles structure after adding data
Rootfinding('FcnPopup_Callback',handles.FcnPopup,[],guidata(handles.FcnPopup))
%disp('Constant_c1_EditText')

% --------------------------------------------------------------------
function varargout = Constant_c2_EditText_Callback(h, eventdata, handles, varargin)

const_c2 = eval(get(handles.Constant_c2_EditText,'string'));
handles.const_c2 = const_c2;
handles.fcn_data = [handles.indexfcn, handles.const_a, handles.const_b, handles.const_c1, handles.const_c2];
guidata(h,handles); % Save the handles structure after adding data
Rootfinding('FcnPopup_Callback',handles.FcnPopup,[],guidata(handles.FcnPopup))
%disp('Constant_c2_EditText')

% --------------------------------------------------------------------
function varargout = PlotPushbutton_Callback(h, eventdata, handles, varargin)

f_data = handles.fcn_data;
indexfcn = f_data(1);
a = f_data(2);
b = f_data(3);
c1 = f_data(4);
c2 = f_data(5);
x = a:(b-a)/100:b;
y = fcn(x,f_data);
axes(handles.axes1)
plot(x,y)
grid on

% --------------------------------------------------------------------
function varargout = ChooseToleranceEditText_Callback(h, eventdata, handles, varargin)

const_eps = eval(get(handles.ChooseToleranceEditText,'string'));
handles.const_eps = const_eps;
handles.itert_data = [handles.const_eps, handles.const_itmax];
guidata(h,handles);
Rootfinding('FcnPopup_Callback',handles.FcnPopup,[],guidata(handles.FcnPopup))
%disp('ChooseToleranceEditText')

% --------------------------------------------------------------------
function varargout = ChooseItMaxEditText_Callback(h, eventdata, handles, varargin)

const_itmax = eval(get(handles.ChooseItMaxEditText,'string'));
handles.const_itmax = const_itmax;
handles.itert_data = [handles.const_eps, handles.const_itmax];
guidata(h,handles);
Rootfinding('FcnPopup_Callback',handles.FcnPopup,[],guidata(handles.FcnPopup))
%disp('ChooseItMaxEditText')

% --------------------------------------------------------------------
function varargout = IterationOutputListbox_Callback(h, eventdata, handles, varargin)

% --------------------------------------------------------------------
function varargout = file_menu_Callback(h, eventdata, handles, varargin)
if isempty(get(handles.axes1,'Children'))
    set(handles.print_submenu,'Enable','off')
else
    set(handles.print_submenu,'Enable','on')
end

% --------------------------------------------------------------------
function varargout = print_submenu_Callback(h, eventdata, handles, varargin)

h_invisible = figure('visible','off'); 
hax = copyobj(handles.axes1,h_invisible);
set(hax,'units',get(0,'defaultaxesunits'),'position',get(0,'defaultaxesposition'))
print(h_invisible,'-depsc','rootfinding_graph') 
close(h_invisible);
disp('The graph is stored under the name "rootfinding_graph.eps"')

% --------------------------------------------------------------------
function varargout = table_submenu_Callback(h, eventdata, handles, varargin)

% Load data from handles structure
StringData = handles.StringData;

switch handles.method
case 'Bisection'
    fid = fopen('output_bisection','w');
    disp('The table is saved under the name "output_bisection"')
case 'Newton'
    fid = fopen('output_newton','w');
    disp('The table is saved under the name "output_newton"')
case 'Secant'
    fid = fopen('output_secant','w');
    disp('The table is saved under the name "output_secant"')
end

[num_rows,num_cols] = size(StringData);

for i=1:num_rows
    fprintf(fid,'%c',StringData(i,1:num_cols));
    fprintf(fid,'\n');
end

fclose(fid);

% --------------------------------------------------------------------
function varargout = close_submenu_Callback(h, eventdata, handles, varargin)
delete(handles.figure1)

% --------------------------------------------------------------------
function varargout = BisectionPushbutton_Callback(h, eventdata, handles, varargin)

getData = BisectionInit(handles);
handles.leftend = getData.dataIn_a;
handles.rightend = getData.dataIn_b;
handles.method = 'Bisection';
%disp('BisectionPushButton')
guidata(h,handles)
leftend = eval(handles.leftend);
rightend = eval(handles.rightend);
f_data = handles.fcn_data;
itert_data = handles.itert_data;
epsln = itert_data(1);
itmax = itert_data(2);
it_count = 1;
f_left = fcn(leftend,f_data);
f_right = fcn(rightend,f_data);
midpoint = (leftend + rightend)/2;
f_midpt = fcn(midpoint,f_data);
error_bound = rightend - midpoint;

celldata = cellstr(num2str(zeros(itmax+2,1)));
celldata(1) = cellstr('                  Bisection method output');
celldata(2) = cellstr('  n       a            b            c              f(c)     Error Bound');
celldata(3) = cellstr(sprintf('%3i%13.8f%13.8f%17.12f%12.2e%12.2e',...
                              it_count,leftend,rightend,midpoint,f_midpt,error_bound));

while abs(error_bound) > epsln & it_count < itmax
    it_count = it_count + 1;
    if sign(f_right)*sign(f_midpt) <= 0
        leftend = midpoint;
        f_left = f_midpt;
    else
        rightend = midpoint;
        f_right = f_midpt;
    end
    midpoint = (leftend + rightend)/2;
    f_midpt = fcn(midpoint,f_data);
    error_bound = rightend - midpoint;
    celldata(it_count+2) = cellstr(sprintf('%3i%13.8f%13.8f%17.12f%12.2e%12.2e',...
                              it_count,leftend,rightend,midpoint,f_midpt,error_bound));
end

celldata = celldata(1:it_count+2);
StringData = char(celldata);
handles.StringData = StringData;
guidata(h,handles);
set(handles.IterationOutputListbox,'string',StringData)

% --------------------------------------------------------------------
function varargout = NewtonPushbutton_Callback(h, eventdata, handles, varargin)

getData = NewtonInit(handles);
handles.x0 = getData.dataIn;
handles.method = 'Newton';
%disp('NewtonPushButton')
guidata(h,handles)
x0 = eval(handles.x0);
f_data = handles.fcn_data;
itert_data = handles.itert_data;
epsln = itert_data(1);
itmax = itert_data(2);

celldata = cellstr(num2str(zeros(itmax+3,1)));
celldata(1) = cellstr('                          Newton method output');
celldata(2) = cellstr('  n          x_n                 f(x_n)        x_n - x_{n-1}');
celldata(3) = cellstr(sprintf('%3i%20.12f%18.3e',0,x0,fcn(x0,f_data)));
it_count = 0;
diff = 10000;

while abs(diff) > epsln & it_count < itmax
    it_count = it_count + 1;
    fx = fcn(x0,f_data);
    dfx = dfcn(x0,f_data);
    x1 = x0 - fx/dfx;
    diff = x1 - x0;
    celldata(it_count+3) = cellstr(sprintf('%3i%20.12f%18.3e%18.3e',it_count,x1,fcn(x1,f_data),diff));
    x0 = x1;
end

celldata = celldata(1:it_count+3);
StringData = char(celldata);
handles.StringData = StringData;
guidata(h,handles);
set(handles.IterationOutputListbox,'string',StringData)

% --------------------------------------------------------------------
function varargout = SecantPushbutton_Callback(h, eventdata, handles, varargin)

getData = SecantInit(handles);
handles.x0 = getData.dataIn_x0;
handles.x1 = getData.dataIn_x1;
handles.method = 'Secant';
%disp('SecantPushButton')
guidata(h,handles)
x0 = eval(handles.x0);
x1 = eval(handles.x1);
f_data = handles.fcn_data;
itert_data = handles.itert_data;
epsln = itert_data(1);
itmax = itert_data(2);

celldata = cellstr(num2str(zeros(itmax+4,1)));
celldata(1) = cellstr('                          Secant method output');
celldata(2) = cellstr('  n          x_n                 f(x_n)        x_n - x_{n-1}');
f0 = fcn(x0,f_data);
f1 = fcn(x1,f_data);
celldata(3) = cellstr(sprintf('%3i%20.12f%18.3e',0,x0,f0));
celldata(4) = cellstr(sprintf('%3i%20.12f%18.3e',1,x1,f1));
it_count = 1;
diff = 10000;

while abs(diff) > epsln & it_count <= itmax
    it_count = it_count + 1;
    finite_diff = (f1 - f0)/(x1 - x0);
    x2 = x1 - f1/finite_diff;
    diff = x2 - x1;
    f2 = fcn(x2,f_data);
    celldata(it_count+3) = cellstr(sprintf('%3i%20.12f%18.3e%18.3e',it_count,x2,f2,diff));
    x0 = x1; x1 = x2; f0 = f1; f1 = f2;
end

celldata = celldata(1:it_count+3);
StringData = char(celldata);
handles.StringData = StringData;
guidata(h,handles);
set(handles.IterationOutputListbox,'string',StringData)

% ========================================================
% ========================================================
% ========================================================
%
% This is the place to add new functions to the GUI.  You must
% also make a change in the "FcnPopup" portion of the fig file, 
% adding the name of the new function to the list shown when 
% the table is activated.

function fcn_val = fcn(x,f_data)

indexfcn = f_data(1);
a = f_data(2);
b = f_data(3);
c1 = f_data(4);
c2 = f_data(5);

switch indexfcn
case 1  % f(x) = c1 + c2*cos(x) - x
    fcn_val = c1 + c2*cos(x) - x;
case 2  % f(x) = cos(x) - c2*sin(x) - c1
    fcn_val = cos(x) - c2*sin(x) - c1;
case 3  % f(x) = x - tan(x)
    fcn_val = x - tan(x);
case 4  % f(x) = x - exp(-c1*x)
    fcn_val = x - exp(-c1*x);
case 5  % f(x) = x + exp(-c1*x*x)*cos(x)
    fcn_val = x + exp(-c1*x.*x).*cos(x);
case 6  % f(x) = exp(c1*x) - c2*sin(x)
    fcn_val = exp(c1*x) - c2*sin(x);
case 7  % f(x) = x^3 - x^2 - x - 1
    fcn_val = x.^3 - x.^2 - x - 1;
case 8  % f(x) = x^3 - c1*x - c2
    fcn_val = x.^3 - c1*x - c2;
case 9  % f(x) = x^4 - c1*x - c2
    fcn_val = x.^4 - c1*x - c2;
case 10  % f(x) = x^6 - x - 1
    fcn_val = x.^6 - c1*x - c2;
case 11 % f(x) = (x-1)^3
    fcn_val = -1 + x.*(3+x.*(-3+x));
end


function deriv_val = dfcn(x,f_data)

indexfcn = f_data(1);
a = f_data(2);
b = f_data(3);
c1 = f_data(4);
c2 = f_data(5);

switch indexfcn
case 1  % f(x) = c1 + c2*cos(x) - x
    deriv_val = -c2*sin(x) - 1.0;
case 2  % f(x) = cos(x) - c2*sin(x) - c1
    deriv_val = -sin(x) - c2*cos(x);
case 3  % f(x) = x - tan(x)
    deriv_val = -tan(x).^2;
case 4  % f(x) = x - exp(-c1*x)
    deriv_val = 1.0 + c1*exp(-c1*x);
case 5  % f(x) = x + exp(-c1*x*x)*cos(x)
    deriv_val = 1.0 - exp(-c1*x.*x).*(2*c1*x.*cos(x) + sin(x));
case 6  % f(x) = exp(c1*x) - c2*sin(x)
    deriv_val = c1*exp(c1*x) - c2*cos(x);
case 7  % f(x) = x^3 - x^2 - x - 1
    deriv_val = 3*x.^2 - 2*x - 1;
case 8  % f(x) = x^3 - c1*x - c2
    deriv_val = 3*x.^2 - c1;
case 9  % f(x) = x^4 - c1*x - c2
    deriv_val = 4*x.^3 - c1;
case 10  % f(x) = x^6 - x - 1
    deriv_val = 6*x.^5 - c1;
case 11 % f(x) = (x-1)^3
    deriv_val = 3 + x.*(-6 + 3*x);
end

