% @valder directory
% by Richard Neidinger, Davidson College
% copyright August 2006; may only be used for educational purposes.
% 
%   acos     - overloads arccosine of a valder object argument
%   asin     - overloads arcsine of a valder object argument
%   atan     - overloads arctangent of a valder object argument
%   cos      - overloads cosine of a valder object argument
%   cot      - overloads cotangent of a valder object argument
%   csc      - overloads cosecant of a valder object argument
%   display  - Command window display of a valder object.
%   double   - Convert valder object to vector of doubles.
%   exp      - overloads exp of a valder object argument
%   log      - overloads natural logarithm of a valder object argument
%   minus    - overloads subtraction with at least one valder object argument
%   mpower   - overloads power with at least one valder object argument
%   mrdivide - overloads division with at least one valder object argument
%   mtimes   - overloads multiplication with at least one valder object argument
%   plus     - overloads addition with at least one valder object argument
%   sec      - overloads cosecant of a valder object argument
%   sin      - overloads sine with a valder object argument
%   sqrt     - overloads square root of a valder object argument
%   tan      - overloads tangent of a valder object argument
%   uminus   - overloads negation with a valder object argument
%   valder   - ValDer class constructor


function x = valder(a,b)
%VALDER ValDer class constructor
%   x = valder(a,b) creates a Value & Derivative object 
%   with function value a and derivative value b.
%   x = valder(a) creates a constant with derivative 0.
if nargin == 0
    x.val = [];
    x.der = [];
    x = class(x,'valder');
elseif isa(a,'valder')
    x = a;
elseif nargin == 1
    x.val = a;
    x.der = 0;
    x = class(x,'valder');
else
    x.val = a;
    x.der = b;
    x = class(x,'valder');
end


function fdf = double(f)
%VALDER/DOUBLE Convert valder object to vector of doubles.
%   fdf = double(f) converts a valder object 
%   to a vector of the function value and derivative value.
fdf = [ f.val, f.der ];


function display(f)
%VALDER/DISPLAY Command window display of a valder object.
disp(['func value = ',num2str(f.val),',  derivative = ',num2str(f.der)])


function h = plus(u,v)
%VALDER/PLUS overloads addition with at least one valder object argument
u = valder(u);  % converts scalar to valder, if necessary
v = valder(v);
h = valder(u.val+v.val, u.der+v.der);


function h = uminus(u)
%VALDER/UMINUS overloads negation with a valder object argument
h = valder(-u.val, -u.der);


function h = minus(u,v)
%VALDER/MINUS overloads subtraction with at least one valder object argument
u = valder(u);  % converts scalar to valder, if necessary
v = valder(v);
h = valder(u.val-v.val, u.der-v.der);


function h = mtimes(u,v)
%VALDER/MTIMES overloads multiplication with at least one valder object argument
u = valder(u);  % converts scalar to valder, if necessary
v = valder(v);  % alternatively, could create if ~isa(v,'valder')
h = valder(u.val*v.val, u.der*v.val+u.val*v.der);


function h = mrdivide(u,v)
%VALDER/MRDIVIDE overloads division with at least one valder object argument
u = valder(u);  % converts scalar to valder, if necessary
if isa(v,'valder')
    h = valder(u.val/v.val, (u.der*v.val-u.val*v.der)/(v.val)^2);
else
    h = valder(u.val/v, u.der/v);
end


function h = mpower(u,r)
%VALDER/MPOWER overloads power with at least one valder object argument
u = valder(u);  % converts scalar to valder, if necessary
if isa(r,'valder')
    h = exp(r*log(u));
else
    h = valder(u.val^r, r*u.val^(r-1)*u.der);
end


function h = exp(u)
%VALDER/EXP overloads exp of a valder object argument
h = valder(exp(u.val), exp(u.val)*u.der);


function h = log(u)
%VALDER/LOG overloads natural logarithm of a valder object argument
h = valder(log(u.val), (1/u.val)*u.der);


function h = sqrt(u)
%VALDER/SQRT overloads square root of a valder object argument
h = valder(sqrt(u.val), u.der/(2*sqrt(u.val)));


function h = sin(u)
%VALDER/SIN overloads sine with a valder object argument
h = valder(sin(u.val), cos(u.val)*u.der);


function h = cos(u)
%VALDER/COS overloads cosine of a valder object argument
h = valder(cos(u.val), -sin(u.val)*u.der);


function h = tan(u)
%VALDER/TAN overloads tangent of a valder object argument
h = valder(tan(u.val), (sec(u.val))^2*u.der);


function h = csc(u)
%VALDER/CSC overloads cosecant of a valder object argument
h = valder(csc(u.val), -csc(u.val)*cot(u.val)*u.der);


function h = sec(u)
%VALDER/SEC overloads cosecant of a valder object argument
h = valder(sec(u.val), sec(u.val)*tan(u.val)*(u.der));


function h = cot(u)
%VALDER/COT overloads cotangent of a valder object argument
h = valder(cot(u.val), -(csc(u.val))^2*u.der);


function h = asin(u)
%VALDER/ASIN overloads arcsine of a valder object argument
h = valder(asin(u.val), u.der/sqrt(1-u.val^2));


function h = atan(u)
%VALDER/ATAN overloads arctangent of a valder object argument
h = valder(atan(u.val), u.der/(1+u.val^2));


function h = acos(u)
%VALDER/ACOS overloads arccosine of a valder object argument
h = valder(acos(u.val), -u.der/sqrt(1-u.val^2));

