/***************************************************************************** * \file * class for automatic differentiation on scalar values and 1st * derivatives . * * \author * Erwin Aertbelien, Div. PMA, Dep. of Mech. Eng., K.U.Leuven * * \version * ORO_Geometry V0.2 * * \par Note * VC6++ contains a bug, concerning the use of inlined friend functions * in combination with namespaces. So, try to avoid inlined friend * functions ! * * \par History * - $log$ * * \par Release * $Id: rall1d.h 23467 2009-09-25 01:13:07Z gsrb3d $ * $Name: $ ****************************************************************************/ #ifndef Rall1D_H #define Rall1D_H #include #include "utility.h" namespace KDL { /** * Rall1d contains a value, and its gradient, and defines an algebraic structure on this pair. * This template class has 3 template parameters : * - T contains the type of the value. * - V contains the type of the gradient (can be a vector-like type). * - S defines a scalar type that can operate on Rall1d. This is the type that * is used to give back values of Norm() etc. * * S is usefull when you recurse a Rall1d object into itself to create a 2nd, 3th, 4th,.. * derivatives. (e.g. Rall1d< Rall1d, Rall1d, double> ). * * S is always passed by value. * * \par Class Type * Concrete implementation */ template class Rall1d { public: typedef T valuetype; typedef V gradienttype; typedef S scalartype; public : T t; //!< value V grad; //!< gradient public : INLINE Rall1d() {} T value() const { return t; } V deriv() const { return grad; } explicit INLINE Rall1d(typename TI::Arg c) {t=T(c);SetToZero(grad);} INLINE Rall1d(typename TI::Arg tn, typename TI::Arg afg):t(tn),grad(afg) {} INLINE Rall1d(const Rall1d& r):t(r.t),grad(r.grad) {} //if one defines this constructor, it's better optimized then the //automatically generated one ( this one set's up a loop to copy // word by word. INLINE T& Value() { return t; } INLINE V& Gradient() { return grad; } INLINE static Rall1d Zero() { Rall1d tmp; SetToZero(tmp); return tmp; } INLINE static Rall1d Identity() { Rall1d tmp; SetToIdentity(tmp); return tmp; } INLINE Rall1d& operator =(S c) {t=c;SetToZero(grad);return *this;} INLINE Rall1d& operator =(const Rall1d& r) {t=r.t;grad=r.grad;return *this;} INLINE Rall1d& operator /=(const Rall1d& rhs) { grad = LinComb(rhs.t,grad,-t,rhs.grad) / (rhs.t*rhs.t); t /= rhs.t; return *this; } INLINE Rall1d& operator *=(const Rall1d& rhs) { LinCombR(rhs.t,grad,t,rhs.grad,grad); t *= rhs.t; return *this; } INLINE Rall1d& operator +=(const Rall1d& rhs) { grad +=rhs.grad; t +=rhs.t; return *this; } INLINE Rall1d& operator -=(const Rall1d& rhs) { grad -= rhs.grad; t -= rhs.t; return *this; } INLINE Rall1d& operator /=(S rhs) { grad /= rhs; t /= rhs; return *this; } INLINE Rall1d& operator *=(S rhs) { grad *= rhs; t *= rhs; return *this; } INLINE Rall1d& operator +=(S rhs) { t += rhs; return *this; } INLINE Rall1d& operator -=(S rhs) { t -= rhs; return *this; } // = operators /* gives warnings on cygwin template friend INLINE Rall1d operator /(const Rall1d& lhs,const Rall1d& rhs); friend INLINE Rall1d operator *(const Rall1d& lhs,const Rall1d& rhs); friend INLINE Rall1d operator +(const Rall1d& lhs,const Rall1d& rhs); friend INLINE Rall1d operator -(const Rall1d& lhs,const Rall1d& rhs); friend INLINE Rall1d operator -(const Rall1d& arg); friend INLINE Rall1d operator *(S s,const Rall1d& v); friend INLINE Rall1d operator *(const Rall1d& v,S s); friend INLINE Rall1d operator +(S s,const Rall1d& v); friend INLINE Rall1d operator +(const Rall1d& v,S s); friend INLINE Rall1d operator -(S s,const Rall1d& v); friend INLINE Rall1d operator -(const Rall1d& v,S s); friend INLINE Rall1d operator /(S s,const Rall1d& v); friend INLINE Rall1d operator /(const Rall1d& v,S s); // = Mathematical functions that operate on Rall1d objects friend INLINE Rall1d exp(const Rall1d& arg); friend INLINE Rall1d log(const Rall1d& arg); friend INLINE Rall1d sin(const Rall1d& arg); friend INLINE Rall1d cos(const Rall1d& arg); friend INLINE Rall1d tan(const Rall1d& arg); friend INLINE Rall1d sinh(const Rall1d& arg); friend INLINE Rall1d cosh(const Rall1d& arg); friend INLINE Rall1d sqr(const Rall1d& arg); friend INLINE Rall1d pow(const Rall1d& arg,double m) ; friend INLINE Rall1d sqrt(const Rall1d& arg); friend INLINE Rall1d atan(const Rall1d& x); friend INLINE Rall1d hypot(const Rall1d& y,const Rall1d& x); friend INLINE Rall1d asin(const Rall1d& x); friend INLINE Rall1d acos(const Rall1d& x); friend INLINE Rall1d abs(const Rall1d& x); friend INLINE S Norm(const Rall1d& value) ; friend INLINE Rall1d tanh(const Rall1d& arg); friend INLINE Rall1d atan2(const Rall1d& y,const Rall1d& x); // = Utility functions to improve performance friend INLINE Rall1d LinComb(S alfa,const Rall1d& a, const T& beta,const Rall1d& b ); friend INLINE void LinCombR(S alfa,const Rall1d& a, const T& beta,const Rall1d& b,Rall1d& result ); // = Setting value of a Rall1d object to 0 or 1 friend INLINE void SetToZero(Rall1d& value); friend INLINE void SetToOne(Rall1d& value); // = Equality in an eps-interval friend INLINE bool Equal(const Rall1d& y,const Rall1d& x,double eps); */ }; template INLINE Rall1d operator /(const Rall1d& lhs,const Rall1d& rhs) { return Rall1d(lhs.t/rhs.t,(lhs.grad*rhs.t-lhs.t*rhs.grad)/(rhs.t*rhs.t)); } template INLINE Rall1d operator *(const Rall1d& lhs,const Rall1d& rhs) { return Rall1d(lhs.t*rhs.t,rhs.t*lhs.grad+lhs.t*rhs.grad); } template INLINE Rall1d operator +(const Rall1d& lhs,const Rall1d& rhs) { return Rall1d(lhs.t+rhs.t,lhs.grad+rhs.grad); } template INLINE Rall1d operator -(const Rall1d& lhs,const Rall1d& rhs) { return Rall1d(lhs.t-rhs.t,lhs.grad-rhs.grad); } template INLINE Rall1d operator -(const Rall1d& arg) { return Rall1d(-arg.t,-arg.grad); } template INLINE Rall1d operator *(S s,const Rall1d& v) { return Rall1d(s*v.t,s*v.grad); } template INLINE Rall1d operator *(const Rall1d& v,S s) { return Rall1d(v.t*s,v.grad*s); } template INLINE Rall1d operator +(S s,const Rall1d& v) { return Rall1d(s+v.t,v.grad); } template INLINE Rall1d operator +(const Rall1d& v,S s) { return Rall1d(v.t+s,v.grad); } template INLINE Rall1d operator -(S s,const Rall1d& v) { return Rall1d(s-v.t,-v.grad); } template INLINE Rall1d operator -(const Rall1d& v,S s) { return Rall1d(v.t-s,v.grad); } template INLINE Rall1d operator /(S s,const Rall1d& v) { return Rall1d(s/v.t,(-s*v.grad)/(v.t*v.t)); } template INLINE Rall1d operator /(const Rall1d& v,S s) { return Rall1d(v.t/s,v.grad/s); } template INLINE Rall1d exp(const Rall1d& arg) { T v; v= (exp(arg.t)); return Rall1d(v,v*arg.grad); } template INLINE Rall1d log(const Rall1d& arg) { T v; v=(log(arg.t)); return Rall1d(v,arg.grad/arg.t); } template INLINE Rall1d sin(const Rall1d& arg) { T v; v=(sin(arg.t)); return Rall1d(v,cos(arg.t)*arg.grad); } template INLINE Rall1d cos(const Rall1d& arg) { T v; v=(cos(arg.t)); return Rall1d(v,-sin(arg.t)*arg.grad); } template INLINE Rall1d tan(const Rall1d& arg) { T v; v=(tan(arg.t)); return Rall1d(v,arg.grad/sqr(cos(arg.t))); } template INLINE Rall1d sinh(const Rall1d& arg) { T v; v=(sinh(arg.t)); return Rall1d(v,cosh(arg.t)*arg.grad); } template INLINE Rall1d cosh(const Rall1d& arg) { T v; v=(cosh(arg.t)); return Rall1d(v,sinh(arg.t)*arg.grad); } template INLINE Rall1d sqr(const Rall1d& arg) { T v; v=(arg.t*arg.t); return Rall1d(v,(2.0*arg.t)*arg.grad); } template INLINE Rall1d pow(const Rall1d& arg,double m) { T v; v=(pow(arg.t,m)); return Rall1d(v,(m*v/arg.t)*arg.grad); } template INLINE Rall1d sqrt(const Rall1d& arg) { T v; v=sqrt(arg.t); return Rall1d(v, (0.5/v)*arg.grad); } template INLINE Rall1d atan(const Rall1d& x) { T v; v=(atan(x.t)); return Rall1d(v,x.grad/(1.0+sqr(x.t))); } template INLINE Rall1d hypot(const Rall1d& y,const Rall1d& x) { T v; v=(hypot(y.t,x.t)); return Rall1d(v,(x.t/v)*x.grad+(y.t/v)*y.grad); } template INLINE Rall1d asin(const Rall1d& x) { T v; v=(asin(x.t)); return Rall1d(v,x.grad/sqrt(1.0-sqr(x.t))); } template INLINE Rall1d acos(const Rall1d& x) { T v; v=(acos(x.t)); return Rall1d(v,-x.grad/sqrt(1.0-sqr(x.t))); } template INLINE Rall1d abs(const Rall1d& x) { T v; v=(Sign(x)); return Rall1d(v*x,v*x.grad); } template INLINE S Norm(const Rall1d& value) { return Norm(value.t); } template INLINE Rall1d tanh(const Rall1d& arg) { T v(tanh(arg.t)); return Rall1d(v,arg.grad/sqr(cosh(arg.t))); } template INLINE Rall1d atan2(const Rall1d& y,const Rall1d& x) { T v(x.t*x.t+y.t*y.t); return Rall1d(atan2(y.t,x.t),(x.t*y.grad-y.t*x.grad)/v); } template INLINE Rall1d LinComb(S alfa,const Rall1d& a, const T& beta,const Rall1d& b ) { return Rall1d( LinComb(alfa,a.t,beta,b.t), LinComb(alfa,a.grad,beta,b.grad) ); } template INLINE void LinCombR(S alfa,const Rall1d& a, const T& beta,const Rall1d& b,Rall1d& result ) { LinCombR(alfa, a.t, beta, b.t, result.t); LinCombR(alfa, a.grad, beta, b.grad, result.grad); } template INLINE void SetToZero(Rall1d& value) { SetToZero(value.grad); SetToZero(value.t); } template INLINE void SetToIdentity(Rall1d& value) { SetToIdentity(value.t); SetToZero(value.grad); } template INLINE bool Equal(const Rall1d& y,const Rall1d& x,double eps=epsilon) { return (Equal(x.t,y.t,eps)&&Equal(x.grad,y.grad,eps)); } } #endif