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

% Last Modified by GUIDE v2.5 21-Sep-2004 15:16:33

if nargin == 0  % LAUNCH GUI

	fig = openfig(mfilename,'reuse');

	% Generate a structure of handles to pass to callbacks, and store it. 
	handles = guihandles(fig);
    handles.popup_fcn_menu=1;
    handles.indexfcn=handles.popup_fcn_menu;
    handles.degree=1;
    handles.const_a=0;
    handles.const_b=1;
	handles.problem_data = [handles.indexfcn, handles.degree, handles.const_a, handles.const_b];
    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 = Menu_File_Callback(h, eventdata, handles, varargin)

if isempty(get(handles.axes1,'Children'))
    set(handles.Submenu_save_axes1,'Enable','off')
    set(handles.Submenu_save_axes2,'Enable','off')
else
    set(handles.Submenu_save_axes1,'Enable','on')
    set(handles.Submenu_save_axes2,'Enable','on')
end

% --------------------------------------------------------------------
function varargout = Submenu_save_axes1_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','Uniform') 
close(h_invisible);
disp('The graph is stored under the name "Uniform.eps"')



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

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

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

delete(handles.figure1)

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

indexfcn = get(h,'Value');
handles.indexfcn = indexfcn;
handles.problem_data = [handles.indexfcn, handles.degree, handles.const_a, handles.const_b];
guidata(h,handles);     % Save the handles structure after adding data

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

const_a = eval(get(handles.LeftHand,'string'));
handles.const_a = const_a;
handles.problem_data = [handles.indexfcn, handles.degree, handles.const_a, handles.const_b];
guidata(h,handles);     % Save the handles structure after adding data

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

const_b = eval(get(handles.RightHand,'string'));
handles.const_b = const_b;
handles.problem_data = [handles.indexfcn, handles.degree, handles.const_a, handles.const_b];
guidata(h,handles);     % Save the handles structure after adding data

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

degree = eval(get(handles.SelectDegree,'string'));
handles.degree = degree;
handles.problem_data = [handles.indexfcn, handles.degree, handles.const_a, handles.const_b];
guidata(h,handles);     % Save the handles structure after adding data

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

% --------------------------------------------------------------------

function varargout = pushbutton1_Callback(h, eventdata, handles, varargin)

prob_data = handles.problem_data;
indexfcn = prob_data(1);
degree=prob_data(2);
a = prob_data(3);
b = prob_data(4);

x_eval = a:(b-a)/500:b;
[y_unif,y_cheb,true] = fcn(x_eval,prob_data);
delta_x = (b-a)/10;

error_unif = true-y_unif;
max_y = max(error_unif); min_y = min(error_unif);
delta_y = (max_y - min_y)/10;

% Graph error in Uniform P(x)
axes(handles.axes1)
cla
axis([a-delta_x,b+delta_x,min_y-delta_y,max_y+delta_y])
hold on
plot(x_eval,error_unif)
plot([a-delta_x b+delta_x/2],[0 0],'k')
text(b+.6*delta_x,0,'\itx')
%title(['Error using Uniform nodes: degree = ',num2str(degree)])
hold off
max_error_unif = max(abs(error_unif));

error_cheb = true-y_cheb;
max_y = max(error_cheb); min_y = min(error_cheb);
delta_y = (max_y - min_y)/10;

% Graph error in Chebyshev P(x)
axes(handles.axes2)
cla
axis([a-delta_x,b+delta_x,min_y-delta_y,max_y+delta_y])
hold on
plot(x_eval,error_cheb)
plot([a-delta_x b+delta_x/2],[0 0],'k')
text(b+.6*delta_x,0,'\itx')
%title(['Error using Chebyshev nodes: degree = ',num2str(degree)])
hold off
max_error_cheb = max(abs(error_cheb));

celldata = cellstr(num2str(zeros(2,1)));
celldata(1) = cellstr(sprintf('Maximum Absolute  Uniform  Error = %12.3e',max_error_unif));
celldata(2) = cellstr(sprintf('Maximum Absolute Chebyshev Error = %12.3e',max_error_cheb));
StringData = char(celldata);
set(handles.output_listbox,'string',StringData)
guidata(h,handles);

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



% --------------------------------------------------------------------
function [y_unif,y_cheb,true] = fcn(x_eval,prob_data)

indexfcn = prob_data(1);
degree=prob_data(2);
n=degree;
a = prob_data(3);
b = prob_data(4);
true=f(x_eval,indexfcn);

h=(b-a)/n;
x_unif=a:h:b;
y=f(x_unif,indexfcn);
divdif_y=divdif(x_unif,y);
y_unif=interp(x_unif,divdif_y,x_eval);

t_cheb=cos((pi/(2*n+2))*[1:2:2*n+1]);
x_cheb=(b+a)/2 + t_cheb*(b-a)/2;
y=f(x_cheb,indexfcn);
divdif_y=divdif(x_cheb,y);
y_cheb=interp(x_cheb,divdif_y,x_eval);


% --------------------------------------------------------------------
function f_value=f(x,indexfcn)

switch indexfcn
case 1  % f(x) = exp(x)
    f_value = exp(x);
case 2  % f(x) = cos x
    f_value = cos(x);
case 3  % f(x) = arctan x
    f_value = atan(x);
case 4  % f(x) = 1/(1+x^2)
    f_value = 1./(1+x.^2);
case 5  % f(x) = log x
    f_value = log(x);
case 6  % f(x) = tan x
    f_value = tan(x);
case 7  % f(x) = exp(-x^2)
    f_value = exp(-x.^2);
case 8
    f_value = 1 ./(2+cos(x));
case 9  % f(x) = sqrt(abs(x))
    f_value = sqrt(abs(x));
case 10  % f(x) = sqrt(abs(x^3))
    f_value = x.*sqrt(abs(x));
end

% --------------------------------------------------------------------
function divdif_y = divdif(x_nodes,y_values)
%
% This is a function
%         divdif_y = divdif(x_nodes,y_values)
% It calculates the divided differences of the function 
% values given in the vector y_values, which are the values of
% some function f(x) at the nodes given in x_nodes.  On exit, 
%         divdif_y(i) = f[x_1,...,x_i],  i=1,...,m
% with m the length of x_nodes.  The input values x_nodes and
% y_values are not changed by this program.
%
divdif_y = y_values;
m = length(x_nodes);
for i=2:m
    for j=m:-1:i
        divdif_y(j) = (divdif_y(j)-divdif_y(j-1)) ...
                           /(x_nodes(j)-x_nodes(j-i+1));
    end
end

% --------------------------------------------------------------------
function p_eval = interp(x_nodes,divdif_y,x_eval)
%
% This is a function
%         p_eval = interp(x_nodes,divdif_y,x_eval)
% It calculates the Newton divided difference form of 
% the interpolation polynomial of degree m-1, where the 
% nodes are given in x_nodes, m is the length of x_nodes, 
% and the divided differences are given in divdif_y.  The 
% points at which the interpolation is to be carried out 
% are given in x_eval; and on exit, p_eval contains the 
% corresponding values of the interpolation polynomial.
%
m = length(x_nodes);
p_eval = divdif_y(m)*ones(size(x_eval));
for i=m-1:-1:1
    p_eval = divdif_y(i) + (x_eval - x_nodes(i)).*p_eval;
end
