Expression.h

Go to the documentation of this file.
00001 // @(#)root/smatrix:$Id: Expression.h 22419 2008-03-03 00:25:01Z rdm $
00002 // Authors: T. Glebe, L. Moneta    2005  
00003 
00004 #ifndef ROOT_Math_Expression
00005 #define ROOT_Math_Expression
00006 // ********************************************************************
00007 //
00008 // source:
00009 //
00010 // type:      source code
00011 //
00012 // created:   19. 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: Expression Template Elements for SVector
00023 //
00024 // changes:
00025 // 19 Mar 2001 (TG) creation
00026 // 20 Mar 2001 (TG) added rows(), cols() to Expr
00027 // 21 Mar 2001 (TG) added Expr::value_type
00028 // 11 Apr 2001 (TG) rows(), cols() replaced by rows, cols
00029 // 10 Okt 2001 (TG) added print() and operator<<() for Expr class
00030 //
00031 // ********************************************************************
00032 
00033 /**
00034    @defgroup Expression Expression Template Classes
00035    @ingroup SMatrixGroup
00036  */
00037 
00038 //==============================================================================
00039 // Expr: class representing SVector expressions
00040 //=============================================================================
00041 
00042 // modified BinaryOp with two extension BinaryOpCopyL and BinaryOpCopyR to store the 
00043 // object in BinaryOp by value and not reference. When used with constant BinaryOp reference give problems
00044 // on some compilers (like Windows) where a temporary Constant object is ccreated and then destructed
00045 
00046 
00047 #include <iomanip>
00048 #include <iostream>
00049 
00050 namespace ROOT { 
00051 
00052   namespace Math { 
00053 
00054 
00055 
00056 //    template <class T, unsigned int D, unsigned int D2> class MatRepStd;
00057 
00058 /** 
00059     Expression wrapper class for Vector objects
00060 
00061     @ingroup Expression
00062 */
00063 template <class ExprType, class T, unsigned int D >
00064 class VecExpr {
00065 
00066 public:
00067   typedef T  value_type;
00068 
00069   ///
00070   VecExpr(const ExprType& rhs) :
00071     rhs_(rhs) {}
00072 
00073   ///
00074   ~VecExpr() {}
00075 
00076    /// 
00077   inline T apply(unsigned int i) const {
00078     return rhs_.apply(i);
00079   }
00080 
00081   inline T operator() (unsigned int i) const {
00082     return rhs_.apply(i);
00083   }
00084 
00085 
00086 #ifdef OLD_IMPL
00087   ///
00088   static const unsigned int rows = D;
00089   ///
00090   ///static const unsigned int cols = D2;
00091 #else
00092   // use enumerations
00093   enum { 
00094 
00095     kRows = D 
00096 
00097   };
00098 #endif
00099 
00100   /// used by operator<<()
00101   std::ostream& print(std::ostream& os) const {
00102     os.setf(std::ios::right,std::ios::adjustfield);
00103     unsigned int i=0;
00104     os << "[ ";
00105     for(; i<D-1; ++i) {
00106       os << apply(i) << ", ";
00107     }
00108     os << apply(i);
00109     os << " ]";
00110     
00111     return os;
00112   }
00113 
00114 private:
00115   ExprType rhs_; // cannot be a reference!
00116 };
00117 
00118 
00119 /** 
00120     Expression wrapper class for Matrix objects
00121 
00122     @ingroup Expression
00123 */
00124 
00125 template <class T, unsigned int D, unsigned int D2> class MatRepStd;
00126 
00127 template <class ExprType, class T, unsigned int D, unsigned int D2 = 1,
00128           class R1=MatRepStd<T,D,D2> >
00129 class Expr {
00130 public:
00131   typedef T  value_type;
00132 
00133   ///
00134   Expr(const ExprType& rhs) :
00135     rhs_(rhs) {}
00136 
00137   ///
00138   ~Expr() {}
00139 
00140   ///
00141   inline T apply(unsigned int i) const {
00142     return rhs_.apply(i);
00143   }
00144   inline T operator() (unsigned int i, unsigned j) const {
00145     return rhs_(i,j);
00146   }
00147    
00148   /** 
00149       function to  determine if any use operand 
00150       is being used (has same memory adress)
00151    */ 
00152   inline bool IsInUse (const T * p) const { 
00153     return rhs_.IsInUse(p); 
00154   }
00155   
00156 
00157 
00158 #ifdef OLD_IMPL
00159   ///
00160   static const unsigned int rows = D;
00161   ///
00162   static const unsigned int cols = D2;
00163 #else
00164   // use enumerations
00165   enum { 
00166     ///
00167     kRows = D, 
00168   ///
00169     kCols = D2
00170   };
00171 #endif
00172 
00173   /// used by operator<<()
00174   /// simplify to use apply(i,j) 
00175   std::ostream& print(std::ostream& os) const {
00176     os.setf(std::ios::right,std::ios::adjustfield);
00177       os << "[ ";
00178       for (unsigned int i=0; i < D; ++i) {
00179         unsigned int d2 = D2; // to avoid some annoying warnings in case of vectors (D2 = 0)
00180         for (unsigned int j=0; j < D2; ++j) {
00181           os << std::setw(12) << this->operator() (i,j);
00182           if ((!((j+1)%12)) && (j < d2-1))
00183             os << std::endl << "         ...";
00184         }
00185         if (i != D - 1)
00186           os << std::endl  << "  ";
00187       }
00188       os << " ]";
00189 
00190     return os;
00191   }
00192 
00193 private:
00194   ExprType rhs_; // cannot be a reference!
00195 };
00196 
00197 //==============================================================================
00198 // operator<<
00199 //==============================================================================
00200 template <class A, class T, unsigned int D>
00201 inline std::ostream& operator<<(std::ostream& os, const VecExpr<A,T,D>& rhs) {
00202   return rhs.print(os);
00203 }
00204 
00205 template <class A, class T, unsigned int D1, unsigned int D2, class R1>
00206 inline std::ostream& operator<<(std::ostream& os, const Expr<A,T,D1,D2,R1>& rhs) {
00207   return rhs.print(os);
00208 }
00209 
00210 /** 
00211     BinaryOperation class
00212     A class representing binary operators in the parse tree. 
00213     This is the default case where objects are kept by reference
00214 
00215     @ingroup  Expression
00216     @author T. Glebe
00217 */
00218 
00219 
00220 
00221 //==============================================================================
00222 // BinaryOp
00223 //==============================================================================
00224 template <class Operator, class LHS, class RHS, class T>
00225 class BinaryOp {
00226 public:
00227   ///
00228   BinaryOp( Operator /* op */, const LHS& lhs, const RHS& rhs) :
00229     lhs_(lhs), rhs_(rhs) {}
00230 
00231   ///
00232   ~BinaryOp() {}
00233 
00234   ///
00235   inline T apply(unsigned int i) const {
00236     return Operator::apply(lhs_.apply(i), rhs_.apply(i));
00237   }
00238   inline T operator() (unsigned int i, unsigned int j) const {
00239     return Operator::apply(lhs_(i,j), rhs_(i,j) );
00240   }
00241 
00242   inline bool IsInUse (const T * p) const { 
00243     return lhs_.IsInUse(p) || rhs_.IsInUse(p); 
00244   }
00245 
00246 protected:
00247 
00248   const LHS& lhs_;
00249   const RHS& rhs_;
00250 
00251 };
00252 
00253 //LM :: add specialization of BinaryOP when first or second argument needs to be copied
00254 // (maybe it can be doen with a template specialization, but it is not worth, easier to have a separate class    
00255 
00256 //==============================================================================
00257 /**
00258    Binary Operation class with value storage for the left argument. 
00259    Special case of BinaryOp where for the left argument the passed object 
00260    is copied and stored by value instead of a reference.  
00261    This is used in the case of operations involving a constant, where we cannot store a 
00262    reference to the constant (we get a temporary object) and we need to copy it. 
00263 
00264    @ingroup  Expression
00265 */
00266 //==============================================================================
00267 template <class Operator, class LHS, class RHS, class T>
00268 class BinaryOpCopyL {
00269 public:
00270   ///
00271   BinaryOpCopyL( Operator /* op */, const LHS& lhs, const RHS& rhs) :
00272     lhs_(lhs), rhs_(rhs) {}
00273 
00274   ///
00275   ~BinaryOpCopyL() {}
00276 
00277   ///
00278   inline T apply(unsigned int i) const {
00279     return Operator::apply(lhs_.apply(i), rhs_.apply(i));
00280   }
00281   inline T operator() (unsigned int i, unsigned int j) const {
00282     return Operator::apply(lhs_(i,j), rhs_(i,j) );
00283   }
00284 
00285   inline bool IsInUse (const T * p) const { 
00286     // no need to check left since we copy it
00287     return rhs_.IsInUse(p); 
00288   }
00289 
00290 protected:
00291 
00292   const LHS  lhs_;
00293   const RHS& rhs_;
00294 
00295 };
00296 
00297 
00298 //==============================================================================
00299 /**
00300    Binary Operation class with value storage for the right argument. 
00301    Special case of BinaryOp where for the wight argument a copy is stored instead of a reference 
00302    This is use in the case for example of constant where we cannot store by reference 
00303    but need to copy since Constant is a temporary object
00304 
00305    @ingroup  Expression
00306 */
00307 //==============================================================================
00308 template <class Operator, class LHS, class RHS, class T>
00309 class BinaryOpCopyR {
00310 public:
00311   ///
00312   BinaryOpCopyR( Operator /* op */, const LHS& lhs, const RHS& rhs) :
00313     lhs_(lhs), rhs_(rhs) {}
00314 
00315   ///
00316   ~BinaryOpCopyR() {}
00317 
00318   ///
00319   inline T apply(unsigned int i) const {
00320     return Operator::apply(lhs_.apply(i), rhs_.apply(i));
00321   }
00322   inline T operator() (unsigned int i, unsigned int j) const {
00323     return Operator::apply(lhs_(i,j), rhs_(i,j) );
00324   }
00325 
00326   inline bool IsInUse (const T * p) const { 
00327     // no need for right since we copied 
00328     return lhs_.IsInUse(p); 
00329   }
00330 
00331 protected:
00332 
00333   const LHS&  lhs_;
00334   const RHS rhs_;
00335 
00336 };
00337 
00338 
00339 
00340 /** 
00341     UnaryOperation class
00342     A class representing unary operators in the parse tree.
00343     The objects are stored by reference
00344 
00345     @ingroup  Expression
00346     @author T. Glebe
00347 */
00348 //==============================================================================
00349 // UnaryOp
00350 //==============================================================================
00351 template <class Operator, class RHS, class T>
00352 class UnaryOp {
00353 public:
00354   ///
00355   UnaryOp( Operator /* op */ , const RHS& rhs) :
00356     rhs_(rhs) {}
00357 
00358   ///
00359   ~UnaryOp() {}
00360   
00361   ///
00362   inline T apply(unsigned int i) const {
00363     return Operator::apply(rhs_.apply(i));
00364   }
00365   inline T operator() (unsigned int i, unsigned int j) const {
00366     return Operator::apply(rhs_(i,j));
00367   }
00368 
00369   inline bool IsInUse (const T * p) const { 
00370     return rhs_.IsInUse(p); 
00371   }
00372 
00373 protected:
00374 
00375   const RHS& rhs_;
00376 
00377 };
00378 
00379 
00380 /** 
00381     Constant expression class
00382     A class representing constant expressions (literals) in the parse tree.
00383 
00384     @ingroup Expression
00385     @author T. Glebe
00386 */
00387 //==============================================================================
00388 // Constant
00389 //==============================================================================
00390 template <class T>
00391 class Constant {
00392 public:
00393   ///
00394   Constant( const T& rhs ) :
00395     rhs_(rhs) {}
00396 
00397   ///
00398   ~Constant() {}
00399 
00400   ///
00401   inline T apply(unsigned int /*i */ ) const { return rhs_; }
00402 
00403   inline T operator() (unsigned int /*i */, unsigned int /*j */ ) const { return rhs_; }
00404 
00405   //inline bool IsInUse (const T * ) const { return false; }
00406 
00407 protected:
00408 
00409   const T rhs_;  // no need for reference. It is  a fundamental type normally 
00410 
00411 
00412 };
00413 
00414 
00415 
00416   }  // namespace Math
00417 
00418 }  // namespace ROOT
00419           
00420 
00421 
00422 #endif  /* ROOT_Math_Expression */

Generated on Tue Jul 5 14:25:13 2011 for ROOT_528-00b_version by  doxygen 1.5.1