Path: blob/devel/ElmerGUI/netgen/libsrc/general/autodiff.hpp
3206 views
#ifndef FILE_AUTODIFF1#define FILE_AUTODIFF23/**************************************************************************/4/* File: autodiff.hpp */5/* Author: Joachim Schoeberl */6/* Date: 24. Oct. 02 */7/**************************************************************************/89// Automatic differentiation datatype101112/**13Datatype for automatic differentiation.14Contains function value and D derivatives. Algebraic15operations are overloaded by using product-rule etc. etc.16**/17template <int D, typename SCAL = double>18class AutoDiff19{20SCAL val;21SCAL dval[D];22public:2324typedef AutoDiff<D,SCAL> TELEM;25typedef SCAL TSCAL;262728/// elements are undefined29AutoDiff () throw() { };30// { val = 0; for (int i = 0; i < D; i++) dval[i] = 0; } // !3132/// copy constructor33AutoDiff (const AutoDiff & ad2) throw()34{35val = ad2.val;36for (int i = 0; i < D; i++)37dval[i] = ad2.dval[i];38}3940/// initial object with constant value41AutoDiff (SCAL aval) throw()42{43val = aval;44for (int i = 0; i < D; i++)45dval[i] = 0;46}4748/// init object with (val, e_diffindex)49AutoDiff (SCAL aval, int diffindex) throw()50{51val = aval;52for (int i = 0; i < D; i++)53dval[i] = 0;54dval[diffindex] = 1;55}5657/// assign constant value58AutoDiff & operator= (SCAL aval) throw()59{60val = aval;61for (int i = 0; i < D; i++)62dval[i] = 0;63return *this;64}6566/// returns value67SCAL Value() const throw() { return val; }6869/// returns partial derivative70SCAL DValue (int i) const throw() { return dval[i]; }7172/// access value73SCAL & Value() throw() { return val; }7475/// accesses partial derivative76SCAL & DValue (int i) throw() { return dval[i]; }7778///79AutoDiff<D,SCAL> & operator+= (const AutoDiff<D,SCAL> & y) throw()80{81val += y.val;82for (int i = 0; i < D; i++)83dval[i] += y.dval[i];84return *this;85}8687///88AutoDiff<D,SCAL> & operator-= (const AutoDiff<D,SCAL> & y) throw()89{90val -= y.val;91for (int i = 0; i < D; i++)92dval[i] -= y.dval[i];93return *this;9495}9697///98AutoDiff<D,SCAL> & operator*= (const AutoDiff<D,SCAL> & y) throw()99{100for (int i = 0; i < D; i++)101{102// dval[i] *= y.val;103// dval[i] += val * y.dval[i];104dval[i] = dval[i] * y.val + val * y.dval[i];105}106val *= y.val;107return *this;108}109110///111AutoDiff<D,SCAL> & operator*= (const SCAL & y) throw()112{113val *= y;114for (int i = 0; i < D; i++)115dval[i] *= y;116return *this;117}118119///120AutoDiff<D,SCAL> & operator/= (const SCAL & y) throw()121{122SCAL iy = 1.0 / y;123val *= iy;124for (int i = 0; i < D; i++)125dval[i] *= iy;126return *this;127}128129///130bool operator== (SCAL val2) throw()131{132return val == val2;133}134135///136bool operator!= (SCAL val2) throw()137{138return val != val2;139}140141///142bool operator< (SCAL val2) throw()143{144return val < val2;145}146147///148bool operator> (SCAL val2) throw()149{150return val > val2;151}152};153154155//@{ AutoDiff helper functions.156157/// prints AutoDiff158template<int D, typename SCAL>159inline ostream & operator<< (ostream & ost, const AutoDiff<D,SCAL> & x)160{161ost << x.Value() << ", D = ";162for (int i = 0; i < D; i++)163ost << x.DValue(i) << " ";164return ost;165}166167/// AutoDiff plus AutoDiff168template<int D, typename SCAL>169inline AutoDiff<D,SCAL> operator+ (const AutoDiff<D,SCAL> & x, const AutoDiff<D,SCAL> & y) throw()170{171AutoDiff<D,SCAL> res;172res.Value () = x.Value()+y.Value();173// AutoDiff<D,SCAL> res(x.Value()+y.Value());174for (int i = 0; i < D; i++)175res.DValue(i) = x.DValue(i) + y.DValue(i);176return res;177}178179180/// AutoDiff minus AutoDiff181template<int D, typename SCAL>182inline AutoDiff<D,SCAL> operator- (const AutoDiff<D,SCAL> & x, const AutoDiff<D,SCAL> & y) throw()183{184AutoDiff<D,SCAL> res;185res.Value() = x.Value()-y.Value();186// AutoDiff<D,SCAL> res (x.Value()-y.Value());187for (int i = 0; i < D; i++)188res.DValue(i) = x.DValue(i) - y.DValue(i);189return res;190}191192/// double plus AutoDiff193template<int D, typename SCAL>194inline AutoDiff<D,SCAL> operator+ (double x, const AutoDiff<D,SCAL> & y) throw()195{196AutoDiff<D,SCAL> res;197res.Value() = x+y.Value();198for (int i = 0; i < D; i++)199res.DValue(i) = y.DValue(i);200return res;201}202203/// AutoDiff plus double204template<int D, typename SCAL>205inline AutoDiff<D,SCAL> operator+ (const AutoDiff<D,SCAL> & y, double x) throw()206{207AutoDiff<D,SCAL> res;208res.Value() = x+y.Value();209for (int i = 0; i < D; i++)210res.DValue(i) = y.DValue(i);211return res;212}213214215/// minus AutoDiff216template<int D, typename SCAL>217inline AutoDiff<D,SCAL> operator- (const AutoDiff<D,SCAL> & x) throw()218{219AutoDiff<D,SCAL> res;220res.Value() = -x.Value();221for (int i = 0; i < D; i++)222res.DValue(i) = -x.DValue(i);223return res;224}225226/// AutoDiff minus double227template<int D, typename SCAL>228inline AutoDiff<D,SCAL> operator- (const AutoDiff<D,SCAL> & x, double y) throw()229{230AutoDiff<D,SCAL> res;231res.Value() = x.Value()-y;232for (int i = 0; i < D; i++)233res.DValue(i) = x.DValue(i);234return res;235}236237///238template<int D, typename SCAL>239inline AutoDiff<D,SCAL> operator- (double x, const AutoDiff<D,SCAL> & y) throw()240{241AutoDiff<D,SCAL> res;242res.Value() = x-y.Value();243for (int i = 0; i < D; i++)244res.DValue(i) = -y.DValue(i);245return res;246}247248249/// double times AutoDiff250template<int D, typename SCAL>251inline AutoDiff<D,SCAL> operator* (double x, const AutoDiff<D,SCAL> & y) throw()252{253AutoDiff<D,SCAL> res;254res.Value() = x*y.Value();255for (int i = 0; i < D; i++)256res.DValue(i) = x*y.DValue(i);257return res;258}259260/// AutoDiff times double261template<int D, typename SCAL>262inline AutoDiff<D,SCAL> operator* (const AutoDiff<D,SCAL> & y, double x) throw()263{264AutoDiff<D,SCAL> res;265res.Value() = x*y.Value();266for (int i = 0; i < D; i++)267res.DValue(i) = x*y.DValue(i);268return res;269}270271/// AutoDiff times AutoDiff272template<int D, typename SCAL>273inline AutoDiff<D,SCAL> operator* (const AutoDiff<D,SCAL> & x, const AutoDiff<D,SCAL> & y) throw()274{275AutoDiff<D,SCAL> res;276SCAL hx = x.Value();277SCAL hy = y.Value();278279res.Value() = hx*hy;280for (int i = 0; i < D; i++)281res.DValue(i) = hx*y.DValue(i) + hy*x.DValue(i);282283return res;284}285286/// AutoDiff times AutoDiff287template<int D, typename SCAL>288inline AutoDiff<D,SCAL> sqr (const AutoDiff<D,SCAL> & x) throw()289{290AutoDiff<D,SCAL> res;291SCAL hx = x.Value();292res.Value() = hx*hx;293hx *= 2;294for (int i = 0; i < D; i++)295res.DValue(i) = hx*x.DValue(i);296return res;297}298299/// Inverse of AutoDiff300template<int D, typename SCAL>301inline AutoDiff<D,SCAL> Inv (const AutoDiff<D,SCAL> & x)302{303AutoDiff<D,SCAL> res(1.0 / x.Value());304for (int i = 0; i < D; i++)305res.DValue(i) = -x.DValue(i) / (x.Value() * x.Value());306return res;307}308309310/// AutoDiff div AutoDiff311template<int D, typename SCAL>312inline AutoDiff<D,SCAL> operator/ (const AutoDiff<D,SCAL> & x, const AutoDiff<D,SCAL> & y)313{314return x * Inv (y);315}316317/// AutoDiff div double318template<int D, typename SCAL>319inline AutoDiff<D,SCAL> operator/ (const AutoDiff<D,SCAL> & x, double y)320{321return (1/y) * x;322}323324/// double div AutoDiff325template<int D, typename SCAL>326inline AutoDiff<D,SCAL> operator/ (double x, const AutoDiff<D,SCAL> & y)327{328return x * Inv(y);329}330331332333334template<int D, typename SCAL>335inline AutoDiff<D,SCAL> fabs (const AutoDiff<D,SCAL> & x)336{337double abs = fabs (x.Value());338AutoDiff<D,SCAL> res( abs );339if (abs != 0.0)340for (int i = 0; i < D; i++)341res.DValue(i) = x.DValue(i) / abs;342else343for (int i = 0; i < D; i++)344res.DValue(i) = 0.0;345return res;346}347348//@}349350#endif351352353