00001 // @(#)root/smatrix:$Id: Functions.h 20882 2007-11-19 11:31:26Z rdm $ 00002 // Authors: T. Glebe, L. Moneta 2005 00003 00004 #ifndef ROOT_Math_Functions 00005 #define ROOT_Math_Functions 00006 // ******************************************************************** 00007 // 00008 // source: 00009 // 00010 // type: source code 00011 // 00012 // created: 16. Mar 2001 00013 // 00014 // author: Thorsten Glebe 00015 // HERA-B Collaboration 00016 // Max-Planck-Institut fuer Kernphysik 00017 // Saupfercheckweg 1 00018 // 69117 Heidelberg 00019 // Germany 00020 // E-mail: T.Glebe@mpi-hd.mpg.de 00021 // 00022 // Description: Functions which are not applied like a unary operator 00023 // 00024 // changes: 00025 // 16 Mar 2001 (TG) creation 00026 // 03 Apr 2001 (TG) minimum added, doc++ comments added 00027 // 07 Apr 2001 (TG) Lmag2, Lmag added 00028 // 19 Apr 2001 (TG) added #include <cmath> 00029 // 24 Apr 2001 (TG) added sign() 00030 // 26 Jul 2001 (TG) round() added 00031 // 27 Sep 2001 (TG) added Expr declaration 00032 // 00033 // ******************************************************************** 00034 #include <cmath> 00035 00036 #ifndef ROOT_Math_Expression 00037 #include "Math/Expression.h" 00038 #endif 00039 00040 /** 00041 @defgroup TempFunction Generic Template Functions 00042 @ingroup SMatrixGroup 00043 00044 These functions apply for any type T, such as a scalar, a vector or a matrix. 00045 */ 00046 /** 00047 @defgroup VectFunction Vector Template Functions 00048 @ingroup SMatrixGroup 00049 00050 These functions apply to SVector types (and also to Vector expressions) and can 00051 return a vector expression or 00052 a scalar, like in the Dot product, or a matrix, like in the Tensor product 00053 */ 00054 00055 00056 namespace ROOT { 00057 00058 namespace Math { 00059 00060 00061 00062 template <class T, unsigned int D> class SVector; 00063 00064 00065 /** square 00066 Template function to compute \f$x\cdot x \f$, for any type T returning a type T 00067 00068 @ingroup TempFunction 00069 @author T. Glebe 00070 */ 00071 //============================================================================== 00072 // square: x*x 00073 //============================================================================== 00074 template <class T> 00075 inline const T Square(const T& x) { return x*x; } 00076 00077 /** maximum. 00078 Template to find max(a,b) where a,b are of type T 00079 00080 @ingroup TempFunction 00081 @author T. Glebe 00082 */ 00083 //============================================================================== 00084 // maximum 00085 //============================================================================== 00086 template <class T> 00087 inline const T Maximum(const T& lhs, const T& rhs) { 00088 return (lhs > rhs) ? lhs : rhs; 00089 } 00090 00091 /** minimum. 00092 Template to find min(a,b) where a,b are of type T 00093 00094 @ingroup TempFunction 00095 @author T. Glebe 00096 */ 00097 //============================================================================== 00098 // minimum 00099 //============================================================================== 00100 template <class T> 00101 inline const T Minimum(const T& lhs, const T& rhs) { 00102 return (lhs < rhs) ? lhs : rhs; 00103 } 00104 00105 /** round. 00106 Template to compute nearest integer value for any type T 00107 @ingroup TempFunction 00108 @author T. Glebe 00109 */ 00110 //============================================================================== 00111 // round 00112 //============================================================================== 00113 template <class T> 00114 inline int Round(const T& x) { 00115 return (x-static_cast<int>(x) < 0.5) ? static_cast<int>(x) : static_cast<int>(x+1); 00116 } 00117 00118 00119 /** sign. 00120 Template to compute the sign of a number 00121 00122 @ingroup TempFunction 00123 @author T. Glebe 00124 */ 00125 //============================================================================== 00126 // sign 00127 //============================================================================== 00128 template <class T> 00129 inline int Sign(const T& x) { return (x==0)? 0 : (x<0)? -1 : 1; } 00130 00131 //============================================================================== 00132 // meta_dot 00133 //============================================================================== 00134 template <unsigned int I> 00135 struct meta_dot { 00136 template <class A, class B, class T> 00137 static inline T f(const A& lhs, const B& rhs, const T& x) { 00138 return lhs.apply(I) * rhs.apply(I) + meta_dot<I-1>::f(lhs,rhs,x); 00139 } 00140 }; 00141 00142 00143 //============================================================================== 00144 // meta_dot<0> 00145 //============================================================================== 00146 template <> 00147 struct meta_dot<0> { 00148 template <class A, class B, class T> 00149 static inline T f(const A& lhs, const B& rhs, const T& /*x */) { 00150 return lhs.apply(0) * rhs.apply(0); 00151 } 00152 }; 00153 00154 00155 /** 00156 Vector dot product. 00157 Template to compute \f$\vec{a}\cdot\vec{b} = \sum_i a_i\cdot b_i \f$. 00158 00159 @ingroup VectFunction 00160 @author T. Glebe 00161 */ 00162 //============================================================================== 00163 // dot 00164 //============================================================================== 00165 template <class T, unsigned int D> 00166 inline T Dot(const SVector<T,D>& lhs, const SVector<T,D>& rhs) { 00167 return meta_dot<D-1>::f(lhs,rhs, T()); 00168 } 00169 00170 //============================================================================== 00171 // dot 00172 //============================================================================== 00173 template <class A, class T, unsigned int D> 00174 inline T Dot(const SVector<T,D>& lhs, const VecExpr<A,T,D>& rhs) { 00175 return meta_dot<D-1>::f(lhs,rhs, T()); 00176 } 00177 00178 //============================================================================== 00179 // dot 00180 //============================================================================== 00181 template <class A, class T, unsigned int D> 00182 inline T Dot(const VecExpr<A,T,D>& lhs, const SVector<T,D>& rhs) { 00183 return meta_dot<D-1>::f(lhs,rhs, T()); 00184 } 00185 00186 00187 //============================================================================== 00188 // dot 00189 //============================================================================== 00190 template <class A, class B, class T, unsigned int D> 00191 inline T Dot(const VecExpr<A,T,D>& lhs, const VecExpr<B,T,D>& rhs) { 00192 return meta_dot<D-1>::f(rhs,lhs, T()); 00193 } 00194 00195 00196 //============================================================================== 00197 // meta_mag 00198 //============================================================================== 00199 template <unsigned int I> 00200 struct meta_mag { 00201 template <class A, class T> 00202 static inline T f(const A& rhs, const T& x) { 00203 return Square(rhs.apply(I)) + meta_mag<I-1>::f(rhs, x); 00204 } 00205 }; 00206 00207 00208 //============================================================================== 00209 // meta_mag<0> 00210 //============================================================================== 00211 template <> 00212 struct meta_mag<0> { 00213 template <class A, class T> 00214 static inline T f(const A& rhs, const T& ) { 00215 return Square(rhs.apply(0)); 00216 } 00217 }; 00218 00219 00220 /** 00221 Vector magnitude square 00222 Template to compute \f$|\vec{v}|^2 = \sum_iv_i^2 \f$. 00223 00224 @ingroup VectFunction 00225 @author T. Glebe 00226 */ 00227 //============================================================================== 00228 // mag2 00229 //============================================================================== 00230 template <class T, unsigned int D> 00231 inline T Mag2(const SVector<T,D>& rhs) { 00232 return meta_mag<D-1>::f(rhs, T()); 00233 } 00234 00235 //============================================================================== 00236 // mag2 00237 //============================================================================== 00238 template <class A, class T, unsigned int D> 00239 inline T Mag2(const VecExpr<A,T,D>& rhs) { 00240 return meta_mag<D-1>::f(rhs, T()); 00241 } 00242 00243 /** 00244 Vector magnitude (Euclidian norm) 00245 Compute : \f$ |\vec{v}| = \sqrt{\sum_iv_i^2} \f$. 00246 00247 @ingroup VectFunction 00248 @author T. Glebe 00249 */ 00250 //============================================================================== 00251 // mag 00252 //============================================================================== 00253 template <class T, unsigned int D> 00254 inline T Mag(const SVector<T,D>& rhs) { 00255 return std::sqrt(Mag2(rhs)); 00256 } 00257 00258 //============================================================================== 00259 // mag 00260 //============================================================================== 00261 template <class A, class T, unsigned int D> 00262 inline T Mag(const VecExpr<A,T,D>& rhs) { 00263 return std::sqrt(Mag2(rhs)); 00264 } 00265 00266 00267 /** Lmag2: Square of Minkowski Lorentz-Vector norm (only for 4D Vectors) 00268 Template to compute \f$ |\vec{v}|^2 = v_0^2 - v_1^2 - v_2^2 -v_3^2 \f$. 00269 00270 @ingroup VectFunction 00271 @author T. Glebe 00272 */ 00273 //============================================================================== 00274 // Lmag2 00275 //============================================================================== 00276 template <class T> 00277 inline T Lmag2(const SVector<T,4>& rhs) { 00278 return Square(rhs[0]) - Square(rhs[1]) - Square(rhs[2]) - Square(rhs[3]); 00279 } 00280 00281 //============================================================================== 00282 // Lmag2 00283 //============================================================================== 00284 template <class A, class T> 00285 inline T Lmag2(const VecExpr<A,T,4>& rhs) { 00286 return Square(rhs.apply(0)) 00287 - Square(rhs.apply(1)) - Square(rhs.apply(2)) - Square(rhs.apply(3)); 00288 } 00289 00290 /** Lmag: Minkowski Lorentz-Vector norm (only for 4-dim vectors) 00291 Length of a vector Lorentz-Vector: 00292 \f$ |\vec{v}| = \sqrt{v_0^2 - v_1^2 - v_2^2 -v_3^2} \f$. 00293 00294 @ingroup VectFunction 00295 @author T. Glebe 00296 */ 00297 //============================================================================== 00298 // Lmag 00299 //============================================================================== 00300 template <class T> 00301 inline T Lmag(const SVector<T,4>& rhs) { 00302 return std::sqrt(Lmag2(rhs)); 00303 } 00304 00305 //============================================================================== 00306 // Lmag 00307 //============================================================================== 00308 template <class A, class T> 00309 inline T Lmag(const VecExpr<A,T,4>& rhs) { 00310 return std::sqrt(Lmag2(rhs)); 00311 } 00312 00313 00314 /** Vector Cross Product (only for 3-dim vectors) 00315 \f$ \vec{c} = \vec{a}\times\vec{b} \f$. 00316 00317 @ingroup VectFunction 00318 @author T. Glebe 00319 */ 00320 //============================================================================== 00321 // cross product 00322 //============================================================================== 00323 template <class T> 00324 inline SVector<T,3> Cross(const SVector<T,3>& lhs, const SVector<T,3>& rhs) { 00325 return SVector<T,3>(lhs.apply(1)*rhs.apply(2) - 00326 lhs.apply(2)*rhs.apply(1), 00327 lhs.apply(2)*rhs.apply(0) - 00328 lhs.apply(0)*rhs.apply(2), 00329 lhs.apply(0)*rhs.apply(1) - 00330 lhs.apply(1)*rhs.apply(0)); 00331 } 00332 00333 //============================================================================== 00334 // cross product 00335 //============================================================================== 00336 template <class A, class T> 00337 inline SVector<T,3> Cross(const VecExpr<A,T,3>& lhs, const SVector<T,3>& rhs) { 00338 return SVector<T,3>(lhs.apply(1)*rhs.apply(2) - 00339 lhs.apply(2)*rhs.apply(1), 00340 lhs.apply(2)*rhs.apply(0) - 00341 lhs.apply(0)*rhs.apply(2), 00342 lhs.apply(0)*rhs.apply(1) - 00343 lhs.apply(1)*rhs.apply(0)); 00344 } 00345 00346 //============================================================================== 00347 // cross product 00348 //============================================================================== 00349 template <class T, class A> 00350 inline SVector<T,3> Cross(const SVector<T,3>& lhs, const VecExpr<A,T,3>& rhs) { 00351 return SVector<T,3>(lhs.apply(1)*rhs.apply(2) - 00352 lhs.apply(2)*rhs.apply(1), 00353 lhs.apply(2)*rhs.apply(0) - 00354 lhs.apply(0)*rhs.apply(2), 00355 lhs.apply(0)*rhs.apply(1) - 00356 lhs.apply(1)*rhs.apply(0)); 00357 } 00358 00359 //============================================================================== 00360 // cross product 00361 //============================================================================== 00362 template <class A, class B, class T> 00363 inline SVector<T,3> Cross(const VecExpr<A,T,3>& lhs, const VecExpr<B,T,3>& rhs) { 00364 return SVector<T,3>(lhs.apply(1)*rhs.apply(2) - 00365 lhs.apply(2)*rhs.apply(1), 00366 lhs.apply(2)*rhs.apply(0) - 00367 lhs.apply(0)*rhs.apply(2), 00368 lhs.apply(0)*rhs.apply(1) - 00369 lhs.apply(1)*rhs.apply(0)); 00370 } 00371 00372 00373 /** Unit. 00374 Return a vector of unit lenght: \f$ \vec{e}_v = \vec{v}/|\vec{v}| \f$. 00375 00376 @ingroup VectFunction 00377 @author T. Glebe 00378 */ 00379 //============================================================================== 00380 // unit: returns a unit vector 00381 //============================================================================== 00382 template <class T, unsigned int D> 00383 inline SVector<T,D> Unit(const SVector<T,D>& rhs) { 00384 return SVector<T,D>(rhs).Unit(); 00385 } 00386 00387 //============================================================================== 00388 // unit: returns a unit vector 00389 //============================================================================== 00390 template <class A, class T, unsigned int D> 00391 inline SVector<T,D> Unit(const VecExpr<A,T,D>& rhs) { 00392 return SVector<T,D>(rhs).Unit(); 00393 } 00394 00395 #ifdef XXX 00396 //============================================================================== 00397 // unit: returns a unit vector (worse performance) 00398 //============================================================================== 00399 template <class T, unsigned int D> 00400 inline VecExpr<BinaryOp<DivOp<T>, SVector<T,D>, Constant<T>, T>, T, D> 00401 unit(const SVector<T,D>& lhs) { 00402 typedef BinaryOp<DivOp<T>, SVector<T,D>, Constant<T>, T> DivOpBinOp; 00403 return VecExpr<DivOpBinOp,T,D>(DivOpBinOp(DivOp<T>(),lhs,Constant<T>(mag(lhs)))); 00404 } 00405 00406 //============================================================================== 00407 // unit: returns a unit vector (worse performance) 00408 //============================================================================== 00409 template <class A, class T, unsigned int D> 00410 inline VecExpr<BinaryOp<DivOp<T>, VecExpr<A,T,D>, Constant<T>, T>, T, D> 00411 unit(const VecExpr<A,T,D>& lhs) { 00412 typedef BinaryOp<DivOp<T>, VecExpr<A,T,D>, Constant<T>, T> DivOpBinOp; 00413 return VecExpr<DivOpBinOp,T,D>(DivOpBinOp(DivOp<T>(),lhs,Constant<T>(mag(lhs)))); 00414 } 00415 #endif 00416 00417 00418 } // namespace Math 00419 00420 } // namespace ROOT 00421 00422 00423 00424 #endif /* ROOT_Math_Functions */