#ifndef FILE_AUTODIFF #define FILE_AUTODIFF /**************************************************************************/ /* File: autodiff.hpp */ /* Author: Joachim Schoeberl */ /* Date: 24. Oct. 02 */ /**************************************************************************/ // Automatic differentiation datatype /** Object for automatic differentiation. Contains function value and D derivatives. Algebraic operations are overloaded by using product-rule etc. etc. **/ template class AutoDiff { double val; double dval[D]; public: /// initial object as zero AutoDiff () throw() { ; } AutoDiff (const AutoDiff & ad2) throw() { val = ad2.val; for (int i = 0; i < D; i++) dval[i] = ad2.dval[i]; } /// initial object with constant value AutoDiff (double aval) throw() { val = aval; for (int i = 0; i < D; i++) dval[i] = 0; } /// init object with (val, e_diffindex) AutoDiff (double aval, int diffindex) throw() { val = aval; for (int i = 0; i < D; i++) dval[i] = 0; dval[diffindex] = 1; } /// assign constant value AutoDiff & operator= (double aval) throw() { val = aval; for (int i = 0; i < D; i++) dval[i] = 0; return *this; } /// returns value double Value() const throw() { return val; } /// returns partial derivative double DValue (int i) const throw() { return dval[i]; } /// access value double & Value() throw() { return val; } /// accesses partial derivative double & DValue (int i) throw() { return dval[i]; } /// AutoDiff & operator+= (const AutoDiff & y) throw() { val += y.val; for (int i = 0; i < D; i++) dval[i] += y.dval[i]; return *this; } /// AutoDiff & operator-= (const AutoDiff & y) throw() { val -= y.val; for (int i = 0; i < D; i++) dval[i] -= y.dval[i]; return *this; } /// AutoDiff & operator*= (const AutoDiff & y) throw() { for (int i = 0; i < D; i++) { dval[i] *= y.val; dval[i] += val * y.dval[i]; } val *= y.val; return *this; } /// bool operator== (double val2) throw() { return val == val2; } /// bool operator!= (double val2) throw() { return val != val2; } /// bool operator< (double val2) throw() { return val < val2; } /// bool operator> (double val2) throw() { return val > val2; } }; //@{ AutoDiff helper functions. /// template inline ostream & operator<< (ostream & ost, const AutoDiff & x) { ost << x.Value() << ", D = "; for (int i = 0; i < D; i++) ost << x.DValue(i) << " "; return ost; } /// template inline AutoDiff operator+ (const AutoDiff & x, const AutoDiff & y) throw() { AutoDiff res; res.Value () = x.Value()+y.Value(); for (int i = 0; i < D; i++) res.DValue(i) = x.DValue(i) + y.DValue(i); return res; } /// template inline AutoDiff operator- (const AutoDiff & x, const AutoDiff & y) throw() { AutoDiff res; res.Value() = x.Value()-y.Value(); for (int i = 0; i < D; i++) res.DValue(i) = x.DValue(i) - y.DValue(i); return res; } /* template inline AutoDiff Minus (const AutoDiff & x, const AutoDiff & y) { AutoDiff res; res.Value() = x.Value()-y.Value(); for (int i = 0; i < D; i++) res.DValue(i) = x.DValue(i) - y.DValue(i); return res; } */ /// template inline AutoDiff operator+ (double x, const AutoDiff & y) throw() { AutoDiff res; res.Value() = x+y.Value(); for (int i = 0; i < D; i++) res.DValue(i) = y.DValue(i); return res; } /// template inline AutoDiff operator+ (const AutoDiff & y, double x) throw() { AutoDiff res; res.Value() = x+y.Value(); for (int i = 0; i < D; i++) res.DValue(i) = y.DValue(i); return res; } /// template inline AutoDiff operator- (const AutoDiff & x) throw() { AutoDiff res; res.Value() = -x.Value(); for (int i = 0; i < D; i++) res.DValue(i) = -x.DValue(i); return res; } /// template inline AutoDiff operator- (const AutoDiff & x, double y) throw() { AutoDiff res; res.Value() = x.Value()-y; for (int i = 0; i < D; i++) res.DValue(i) = x.DValue(i); return res; } /// template inline AutoDiff operator- (double x, const AutoDiff & y) throw() { AutoDiff res; res.Value() = x-y.Value(); for (int i = 0; i < D; i++) res.DValue(i) = -y.DValue(i); return res; } /// template inline AutoDiff operator* (double x, const AutoDiff & y) throw() { AutoDiff res; res.Value() = x*y.Value(); for (int i = 0; i < D; i++) res.DValue(i) = x*y.DValue(i); return res; } /// template inline AutoDiff operator* (const AutoDiff & y, double x) throw() { AutoDiff res; res.Value() = x*y.Value(); for (int i = 0; i < D; i++) res.DValue(i) = x*y.DValue(i); return res; } /// template inline AutoDiff operator* (const AutoDiff & x, const AutoDiff & y) throw() { AutoDiff res; double hx = x.Value(); double hy = y.Value(); res.Value() = hx*hy; for (int i = 0; i < D; i++) res.DValue(i) = hx*y.DValue(i) + hy*x.DValue(i); /* res.Value() = x.Value()*y.Value(); for (int i = 0; i < D; i++) res.DValue(i) = x.Value()*y.DValue(i) + x.DValue(i) * y.Value(); */ return res; } /* template inline AutoDiff Mult (const AutoDiff & x, const AutoDiff & y) { AutoDiff res; double hx = x.Value(); double hy = y.Value(); res.Value() = hx*hy; for (int i = 0; i < D; i++) res.DValue(i) = hx*y.DValue(i) + hy*x.DValue(i); return res; } */ template inline AutoDiff Inv (const AutoDiff & x) { AutoDiff res(1.0 / x.Value()); for (int i = 0; i < D; i++) res.DValue(i) = -x.DValue(i) / (x.Value() * x.Value()); return res; } template inline AutoDiff operator/ (const AutoDiff & x, const AutoDiff & y) { return x * Inv (y); } template inline AutoDiff operator/ (const AutoDiff & x, double y) { return (1/y) * x; } template inline AutoDiff operator/ (double x, const AutoDiff & y) { return x * Inv(y); } //@} #endif