function SigDig
clc
clear all

% Revised: 
% February 11, 2008
 
% Authors:
% Ana Catalina Torres, Dr. Autar Kaw      
 
% Purpose

%   To illustrate the concept of he effect of significant digits on the
%   numerical calculation of the Forward Difference Approximation of the 
%   first derivative of continuous functions. 
 
% Inputs
%    Clearing all data, variable names, and files from any other source and
%    clearing the command window after each succesive run of the program.

%    This is the only place in the program where the user makes changes to
%    the data

%        Function f(x)
 
         function g=f(x)
            g=exp(2*x);
         end

%   Declaring 'x' as a variable
  
x = sym('x','real');

%       Value of x at which f '(x) is desired, xv
 
        xv=4;
         
%       Starting step size, h
 
        h=0.2;
         
%       Number of times starting step size is halved
 
        n=12;

%       Lowest number of Significant Digits 

        nlow=2;

%       Highest Number of Significant Digits
        
        nhigh=10;
         
         
%--------------------------------------------------------------------------
disp(sprintf('          Effect of Significant Digits on Derivative of a Function'))
disp(sprintf('                       Ana Catalina Torres, Autar Kaw'))
disp(sprintf('                         University of South Florida'))
disp(sprintf('                           United States of America'))
disp(sprintf('                               kaw@eng.usf.edu'))
%--------------------------------------------------------------------------
disp(sprintf('\n\n**************************** Introduction ******************************'))

disp(sprintf('\nThis worksheet demonstrates the use of Matlab to illustrate the effect '))
disp(sprintf('of significant digits on the numerical calculation of the Forward '))
disp(sprintf('Difference Approximation of the first derivative of continuous functions.'))
disp(sprintf('Forward Difference Approximation of the first derivative uses a point h'))
disp(sprintf('ahead of the given value of x at which the derivative of f(x) is to be\nfound.'))

disp(sprintf('\n\n************************** Section 1: Input ****************************'))
format short g
disp(sprintf('\nThe following simulation approximates the first derivative of a')) 
disp(sprintf('function using Forward Difference Approximation with fixed number of '))
disp(sprintf('significant digits used in the calculation. \n\nThe user inputs are'))

disp(sprintf('      a) function,\nf(x)=%g'))
disp(f(x))
disp(sprintf('      b) point at which the derivative is to be found, xv = %g',xv)) 
disp(sprintf('      c) starting step size, h = %g',h))
disp(sprintf('      d) The lowest and highest number of significant digits user wants to')) 
disp(sprintf('         use in the calcluation.  The user should choose the lowest number \nto be at least 2.'))
disp(sprintf('      Lowest number of Significant Digits, nlow = %g',nlow))
disp(sprintf('      Highest Number of Significant Digits, nhigh = %g',nhigh))
disp(sprintf('\nThe outputs include'))
disp(sprintf('      a) exact value'))
disp(sprintf('      b) true error and absolute relative true error as a function of'))
disp(sprintf('         step size.'))

disp(sprintf('\nAll the information must be entered at the beginning of the M-File.'))


disp(sprintf('\n\n************************* Section 2: Simulation **************************'))

disp(sprintf('\nThe exact value EV of the first derivative of the equation:'))
disp(sprintf('\nFirst, using the derivative command the solution is found. '))
Soln=diff(f(x))
disp(sprintf('In a second step, the exact value of the derivative is shown'))
disp(sprintf('The exact solution of the first derivative is:'))
Ev=subs(Soln,x,xv)

%   The following functions modify standard arithmetic operators allowing 
%   computation with the appropriate number of significant digits. These 
%   redefined operators are then used in the Forward Difference 
%   Approximation method to generate a solution that was computed with the 
%   number of significant digits specified.

    function q=sdscale(sd,k)
        if k==0;
           m=sd;
        else m=sd-floor(log10(abs(k))+1);
           q=k*10^m;
           q=floor(q)*10^(-m);
        end
    end
%--------------------------------------------------------------------------
    function c=add(a,b)
        c=a+b;
    end

    function c=sub(a,b)
        c=a-b;
    end

    function c=mul(a,b)
        c=a*b;
    end

    function c=div(a,b)
        c=a/b;
    end
%--------------------------------------------------------------------------
    function d=sdadd(sd,a,b)
        d=sdscale(sd,(add(sdscale(sd,a),sdscale(sd,b))));
    end

    function d=sdsub(sd,a,b)
        d=sdscale(sd,(sub(sdscale(sd,a),sdscale(sd,b))));
    end

    function d=sdmul(sd,a,b)
        d=sdscale(sd,(mul(sdscale(sd,a),sdscale(sd,b))));
    end

    function d=sddiv(sd,a,b)
        d=sdscale(sd,(div(sdscale(sd,a),sdscale(sd,b))));
    end

%--------------------------------------------------------------------------
  
disp(sprintf('\nAn internal loop calculates the following:'))
disp(sprintf('Av: Approximate value of the first derivative using Forward Difference \nApproximation'))
disp(sprintf('Et: True Error'))
disp(sprintf('et: Absolute relative true percentage error'))
dig=zeros(1,nhigh);
Av=zeros(1,nhigh);
Et=zeros(1,nhigh);
et=zeros(1,nhigh);

x = sym('x','real');

for i=nlow:nhigh
    Digits(i)=i;
    Av(i)=sddiv(i,sdsub(i,f(sdadd(i,xv,h)),f(xv)),h);
    Et(i)=Ev-Av(i);
    et(i)=abs(Et(i)/Ev*100);
end
%   The loop calculates the approximate value of the first derivative the 
%   corresponding true error and relative true error as  a function of the 
%   number of significant digits used in the calculations.

disp(sprintf('\n\n********************* Section 3: Table of Values ************************'))

disp(sprintf('\nThe next table shows the approximate value, true error, and the absolute')) 
disp(sprintf('relative true percentage error, as a function of the number of significant\ndigits used in the calculations.\n\n'))
disp('         Digits        AV          Et           et')
Results=[Digits' Av' Et' et'];
disp(sprintf('\n'))
disp(Results)

disp(sprintf('\n\n*************************** Section 4: Graphs ***************************'))

disp(sprintf('\nThe attached graphs show the approximate solution, true error and absolute')) 
disp(sprintf('relative true error as a function of the number of significant digits used.\n'))

set(0,'Units','pixels')
  scnsize=get(0,'ScreenSize');
  wid=round(scnsize(3));
  hei=round(0.9*scnsize(4));
  wind=[1, 1, wid, hei];
  figure('Position',wind)
  
%   Approximate Solutions vs. Sig. Digits:
  
subplot(2,2,1); plot(Digits,Av,'LineWidth',2,'Color','g')
xlabel('Significant Digits')
ylabel('Approximate Value')
title({'Approximate Solution of the First Derivative using'; 'Forward Difference Approximation as a Function of';'Number of Significant Digits'})

%   True error vs. Sig. Digits:

subplot(2,2,2); plot(Digits,Et,'LineWidth',2,'Color','y')
xlabel('Significant Digits')
ylabel('True Error')
title({'True Error in the First Derivative using';'Forward Difference Approximation as a Function of';'Number of Significant Digits'})

%   Absolute relative approximate error vs. Sig. Digits:

subplot(2,2,3); plot(Digits,et,'LineWidth',2,'Color','m')
xlabel('Significant Digits')
ylabel('Absolute Relative True Error')
title({'Absolute Relative True Error in the First Derivative using';'Forward Difference Approximation as a Function of';'Number of Significant Digits'})

disp(sprintf('\n****************************** References *******************************'))

disp(sprintf('\nNumerical Differentiation of Continuous Functions. See')) 
disp(sprintf('http://numericalmethods.eng.usf.edu/mws/gen/02dif'))

disp(sprintf('\n\n****************************** Questions ********************************'))

disp(sprintf('\n1. The velocity of a rocket is given by\n\n               v(t)=2000*ln(140000/(140000-2100t))-9.8*t'))

disp(sprintf('\nUse Forward Divided Difference method with a step size of 0.25 to find the')) 
disp(sprintf('acceleration at t=5s using different number of significant digits'))


disp(sprintf('\n\n***************************** Conclusions *******************************'))

disp(sprintf('\nThe effect of significant digits on the calculation of the first')) 
disp(sprintf('derivative using Forward Difference approximation is studied. '))

disp(sprintf('\n\n-------------------------------------------------------------------------'))
disp(sprintf('\nLegal Notice: The copyright for this application is owned by the ')) 
disp(sprintf('author(s). Neither Mathcad nor the author are responsible for any errors '))
disp(sprintf('contained within and are not liable for any damages resulting from the '))
disp(sprintf('use of this material. This application is intended for non-commercial, '))
disp(sprintf('non-profit use only. Contact the author for permission if you wish to use\nthis application for-profit activities.'))

end
