CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/PhysicsTools/Utilities/interface/SimplifyProduct.h

Go to the documentation of this file.
00001 #ifndef PhysicsTools_Utilities_SimplifyProduct_h
00002 #define PhysicsTools_Utilities_SimplifyProduct_h
00003 
00004 #include "PhysicsTools/Utilities/interface/Product.h"
00005 #include "PhysicsTools/Utilities/interface/Fraction.h"
00006 #include "PhysicsTools/Utilities/interface/DecomposePower.h"
00007 #include "PhysicsTools/Utilities/interface/ParametricTrait.h"
00008 
00009 #include "PhysicsTools/Utilities/interface/Simplify_begin.h"
00010 
00011 namespace funct {
00012 
00013   // a * ( b * c ) = ( a * b ) * c
00014   PROD_RULE(TYPT3, A, PROD_S(B, C),
00015             PROD(PROD(A, B), C), (_1 * _2._1) * _2._2);
00016 
00017   // 0 * a = 0
00018   PROD_RULE(TYPT1, NUM(0), A, NUM(0), num<0>());
00019   
00020   // 0 * n = 0
00021   PROD_RULE(TYPN1, NUM(0), NUM(n), NUM(0), num<0>());
00022 
00023   // 0 * ( a * b ) => 0
00024   PROD_RULE(TYPT2, NUM(0), PROD_S(A, B), NUM(0), num<0>());
00025   
00026   // 1 * a = a
00027   PROD_RULE(TYPT1, NUM(1), A, A, _2);
00028 
00029   // avoid template ambiguities
00030   // 1 * n = n
00031   PROD_RULE(TYPN1, NUM(1), NUM(n), NUM(n), _2);
00032 
00033   // 1 * (n/m) = (n/m)
00034   PROD_RULE(TYPN2, NUM(1), FRACT_S(n, m), FRACT_S(n, m), _2);
00035     
00036   // 1 * 1 = 1
00037   PROD_RULE(TYP0, NUM(1), NUM(1), NUM(1), num<1>());
00038 
00039   // ( - 1 ) * a = - a
00040   PROD_RULE(TYPT1, NUM(-1), A, MINUS_S(A), -_2);
00041 
00042   // ( - 1 ) * n = -n
00043   PROD_RULE(TYPN1, NUM(-1), NUM(n), NUM(-n), num<-n>());
00044 
00045   // 1 * ( a * b ) => ( a * b )
00046   PROD_RULE(TYPT2, NUM(1), PROD_S(A, B), PROD_S(A, B), _2);
00047 
00048   // a * ( -b ) =  - ( a * b )
00049   PROD_RULE(TYPT2, A, MINUS_S(B), MINUS(PROD(A, B)), -(_1 * _2._));
00050 
00051   // n * ( -a ) =  - ( n * a )
00052   PROD_RULE(TYPN1T1, NUM(n), MINUS_S(A), MINUS(PROD(NUM(n), A)), -(_1 * _2._ )); 
00053 
00054   // ( a * b ) * ( -c )=  - ( ( a * b ) * c )
00055   PROD_RULE(TYPT3, PROD_S(A, B), MINUS_S(C), MINUS(PROD(PROD(A, B), C)), -(_1 * _2._));
00056 
00057   // 1 * ( -a ) = -a
00058   PROD_RULE(TYPT1, NUM(1), MINUS_S(A), MINUS(A), _2);
00059 
00060   // ( - a ) * ( - b ) = a * b
00061   PROD_RULE(TYPT2, MINUS_S(A), MINUS_S(B), PROD(A, B), _1._ * _2._);
00062 
00063   // ( -a ) * b = -( a * b )
00064   PROD_RULE(TYPT2, MINUS_S(A), B, MINUS(PROD(A, B)), -(_1._ * _2));
00065 
00066   // a * ( b / c ) = ( a * b ) / c
00067   PROD_RULE(TYPT3, A, RATIO_S(B, C), RATIO(PROD(A, B), C), (_1 * _2._1)/_2._2);
00068 
00069   // n * ( a / b ) = ( n * a ) / b
00070   PROD_RULE(TYPN1T2, NUM(n), RATIO_S(A, B),
00071             RATIO(PROD(NUM(n), A), B), (_1 * _2._1)/_2._2);
00072 
00073   // 1 * ( a / b ) = a / b
00074   PROD_RULE(TYPT2, NUM(1), RATIO_S(A, B), RATIO(A, B), _2);
00075     
00076   // 0 * ( a / b ) = 0
00077   PROD_RULE(TYPT2, NUM(0), RATIO_S(A, B), NUM(0), num<0>());
00078 
00079   // a * n = n * a
00080   PROD_RULE(TYPN1T1, A, NUM(n), PROD(NUM(n), A), _2 * _1);
00081 
00082   // ( a * b ) n = ( n * a ) * b
00083   PROD_RULE(TYPN1T2, PROD_S(A, B), NUM(n), PROD(PROD(NUM(n), A), B),
00084             (_2 * _1._1) * _1._2);
00085 
00086   // ( a * b ) * ( c * d ) => ( ( a * b ) * c ) * d 
00087   PROD_RULE(TYPT4, PROD_S(A, B), PROD_S(C, D),
00088              PROD(PROD(PROD(A, B), C), D),
00089              (_1 * _2._1) * _2._2);
00090   
00091   // n/m * ( a / k ) = n/(m+k) * a
00092   PROD_RULE(TYPN3T1, FRACT_S(n, m), RATIO_S(A, NUM(k)),
00093             PROD(FRACT(n, m + k), A), (fract<n, m + k>() * _2._1));
00094 
00095   // ( a / b ) * n = ( n a ) / b
00096   PROD_RULE(TYPN1T2, RATIO_S(A, B), NUM(n),
00097              RATIO(PROD(NUM(n), A), B), (_2 * _1._1) / _1._2);
00098 
00099   // ( a / b ) * c = ( a * c ) / b
00100   PROD_RULE(TYPT3, RATIO_S(A, B), C,
00101              RATIO(PROD(A, C), B), (_1._1 * _2) / _1._2);
00102 
00103   // 0 * 1 = 0  ( avoid template ambiguity )
00104   PROD_RULE(TYP0, NUM(0), NUM(1), NUM(0), num<0>());
00105     
00106   // ( a / b ) * ( c / d )= a * c / ( b * d )
00107   PROD_RULE(TYPT4, RATIO_S(A, B), RATIO_S(C, D),
00108              RATIO(PROD(A, C), PROD(B, D)),
00109              (_1._1 * _2._1)/(_1._2 * _2._2));
00110 
00111   // a^b * a^c => a^( b + c )
00112   template< TYPT3, bool parametric = Parametric<A>::value>
00113   struct SimplifyPowerProduct {
00114     typedef POWER( A, B ) arg1;
00115     typedef POWER( A, C ) arg2;
00116     typedef PROD_S( arg1, arg2 ) type;
00117     COMBINE( arg1, arg2, type( _1, _2 ) );
00118   };
00119   
00120   TEMPL( T3 )
00121   struct SimplifyPowerProduct< A, B, C, false > {
00122     typedef POWER( A, B ) arg1;
00123     typedef POWER( A, C ) arg2;
00124     typedef POWER( A, SUM( B, C ) ) type;
00125          inline static type combine( const arg1 & _1, const arg2 & _2 ) 
00126     { return pow( DecomposePower< A, B >::getBase( _1 ), 
00127                   ( DecomposePower< A, B >::getExp( _1 ) + 
00128                     DecomposePower< A, C >::getExp( _2 ) ) ); }
00129   };
00130   
00131   TEMPL( T3 ) struct Product< POWER_S( A, B ),POWER_S( A, C ) > :
00132     public SimplifyPowerProduct< A, B, C > { };
00133   
00134   TEMPL( T2 ) struct Product< POWER_S( A, B ),POWER_S( A, B ) > :
00135     public SimplifyPowerProduct< A, B, B > { };
00136   
00137   TEMPL( T2 ) struct Product< A, POWER_S( A, B ) > : 
00138     public SimplifyPowerProduct< A, NUM( 1 ), B > { };
00139 
00140   TEMPL( N1T1 ) struct Product< A, POWER_S( A, NUM( n ) ) > : 
00141     public SimplifyPowerProduct< A, NUM( 1 ), NUM( n ) > { };
00142   
00143   TEMPL( T2 ) struct Product< POWER_S( A, B ), A > : 
00144     public SimplifyPowerProduct< A, B, NUM( 1 ) > { };
00145 
00146   TEMPL( N1T1 ) struct Product< POWER_S( A, NUM( n ) ), A > : 
00147     public SimplifyPowerProduct< A, NUM( n ), NUM( 1 ) > { };
00148 
00149   TEMPL( T1 ) struct Product< A, A > : 
00150     public SimplifyPowerProduct< A, NUM( 1 ), NUM( 1 ) > { };
00151 
00152   TEMPL( T2 ) struct Product< PROD_S( A, B ), PROD_S( A, B ) > : 
00153     public SimplifyPowerProduct< PROD( A, B ), NUM( 1 ), NUM( 1 ) > { };
00154 
00155   TEMPL( T1 ) struct Product< MINUS_S( A ), MINUS_S( A ) > : 
00156     public SimplifyPowerProduct< MINUS_S( A ), NUM( 1 ), NUM( 1 ) > { };
00157 
00158 
00159   // n * n = n ^ 2
00160   PROD_RULE(TYPN1, NUM(n), NUM(n), NUM(n*n), num<n*n>());
00161 
00162   // a/ b * ( c * d ) = ( a * c * d ) / b
00163   PROD_RULE(TYPT4, RATIO_S(A, B), PROD_S(C, D),
00164              RATIO(PROD(PROD(A, C), D), B),
00165              ((_1._1 * _2._1) * _2._2) / _1._2);
00166 
00167   // simplify f * g * h regardless of the order 
00168   template <typename Prod, bool simplify = Prod::value> struct AuxProduct {
00169     typedef PROD(typename Prod::AB, typename Prod::C) type;
00170     COMBINE(typename Prod::AB, typename Prod::C, _1 * _2);
00171   };
00172   
00173   template<typename Prod>  struct AuxProduct<Prod, false> {
00174     typedef PROD_S(typename Prod::AB, typename Prod::C) type;
00175     COMBINE(typename Prod::AB, typename Prod::C, type(_1, _2));
00176   };
00177   
00178   template<typename F, typename G, typename H>
00179   struct Product<PROD_S(F, G), H> {
00180     struct prod0 { 
00181       typedef F A; typedef G B; typedef H C;
00182       typedef PROD_S(A, B) AB;
00183       inline static const A& a(const F& f, const G& g, const H& h) { return f; }
00184       inline static const B& b(const F& f, const G& g, const H& h) { return g; }
00185       inline static const C& c(const F& f, const G& g, const H& h) { return h; }
00186       enum { value = false };
00187     };
00188     struct prod1 { 
00189       typedef F A; typedef H B; typedef G C;
00190       typedef PROD_S(A, B) base;
00191       typedef PROD(A, B) AB;
00192       inline static const A& a(const F& f, const G& g, const H& h) { return f; }
00193       inline static const B& b(const F& f, const G& g, const H& h) { return h; }
00194       inline static const C& c(const F& f, const G& g, const H& h) { return g; }
00195       enum { value = ::boost::type_traits::ice_not<
00196 	     ::boost::is_same<AB, base>::value>::value };
00197     };
00198     struct prod2 { 
00199       typedef G A; typedef H B; typedef F C;
00200       typedef PROD_S(A, B) base;
00201       typedef PROD(A, B) AB;
00202       inline static const A& a(const F& f, const G& g, const H& h) { return g; }
00203       inline static const B& b(const F& f, const G& g, const H& h) { return h; }
00204       inline static const C& c(const F& f, const G& g, const H& h) { return f; }
00205       enum { value = ::boost::type_traits::ice_not<
00206 	     ::boost::is_same<AB, base>::value>::value };
00207     };
00208     
00209     typedef typename 
00210       ::boost::mpl::if_ <prod1, prod1,
00211         typename ::boost::mpl::if_ <prod2, prod2, prod0>::type
00212       >::type prod;
00213     typedef typename AuxProduct<prod>::type type;
00214     inline static type combine(const ProductStruct<F, G>& fg, const H& h) {
00215       const F& f = fg._1;
00216       const G& g = fg._2;
00217       const typename prod::A & a = prod::a(f, g, h);
00218       const typename prod::B & b = prod::b(f, g, h);
00219       const typename prod::C & c = prod::c(f, g, h);
00220       return AuxProduct<prod>::combine(a * b, c); 
00221     }
00222   };
00223 
00224 }
00225 
00226 #include "PhysicsTools/Utilities/interface/Simplify_end.h"
00227 
00228 #endif