CMS 3D CMS Logo

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   // 1 * n/m = n/m ( avoid template ambiguity)
00104   PROD_RULE(TYPN2, NUM(1), FRACT(n, m), FRACT(n, m), _2);
00105 
00106   // 0 * 1 = 0  ( avoid template ambiguity )
00107   PROD_RULE(TYP0, NUM(0), NUM(1), NUM(0), num<0>());
00108     
00109   // ( a / b ) * ( c / d )= a * c / ( b * d )
00110   PROD_RULE(TYPT4, RATIO_S(A, B), RATIO_S(C, D),
00111              RATIO(PROD(A, C), PROD(B, D)),
00112              (_1._1 * _2._1)/(_1._2 * _2._2));
00113 
00114   // a^b * a^c => a^( b + c )
00115   template< TYPT3, bool parametric = Parametric<A>::value>
00116   struct SimplifyPowerProduct {
00117     typedef POWER( A, B ) arg1;
00118     typedef POWER( A, C ) arg2;
00119     typedef PROD_S( arg1, arg2 ) type;
00120     COMBINE( arg1, arg2, type( _1, _2 ) );
00121   };
00122   
00123   TEMPL( T3 )
00124   struct SimplifyPowerProduct< A, B, C, false > {
00125     typedef POWER( A, B ) arg1;
00126     typedef POWER( A, C ) arg2;
00127     typedef POWER( A, SUM( B, C ) ) type;
00128          inline static type combine( const arg1 & _1, const arg2 & _2 ) 
00129     { return pow( DecomposePower< A, B >::getBase( _1 ), 
00130                   ( DecomposePower< A, B >::getExp( _1 ) + 
00131                     DecomposePower< A, C >::getExp( _2 ) ) ); }
00132   };
00133   
00134   TEMPL( T3 ) struct Product< POWER_S( A, B ),POWER_S( A, C ) > :
00135     public SimplifyPowerProduct< A, B, C > { };
00136   
00137   TEMPL( T2 ) struct Product< POWER_S( A, B ),POWER_S( A, B ) > :
00138     public SimplifyPowerProduct< A, B, B > { };
00139   
00140   TEMPL( T2 ) struct Product< A, POWER_S( A, B ) > : 
00141     public SimplifyPowerProduct< A, NUM( 1 ), B > { };
00142 
00143   TEMPL( N1T1 ) struct Product< A, POWER_S( A, NUM( n ) ) > : 
00144     public SimplifyPowerProduct< A, NUM( 1 ), NUM( n ) > { };
00145   
00146   TEMPL( T2 ) struct Product< POWER_S( A, B ), A > : 
00147     public SimplifyPowerProduct< A, B, NUM( 1 ) > { };
00148 
00149   TEMPL( N1T1 ) struct Product< POWER_S( A, NUM( n ) ), A > : 
00150     public SimplifyPowerProduct< A, NUM( n ), NUM( 1 ) > { };
00151 
00152   TEMPL( T1 ) struct Product< A, A > : 
00153     public SimplifyPowerProduct< A, NUM( 1 ), NUM( 1 ) > { };
00154 
00155   TEMPL( T2 ) struct Product< PROD_S( A, B ), PROD_S( A, B ) > : 
00156     public SimplifyPowerProduct< PROD( A, B ), NUM( 1 ), NUM( 1 ) > { };
00157 
00158   TEMPL( T1 ) struct Product< MINUS_S( A ), MINUS_S( A ) > : 
00159     public SimplifyPowerProduct< MINUS_S( A ), NUM( 1 ), NUM( 1 ) > { };
00160 
00161 
00162   // n * n = n ^ 2
00163   PROD_RULE(TYPN1, NUM(n), NUM(n), NUM(n*n), num<n*n>());
00164 
00165   // a/ b * ( c * d ) = ( a * c * d ) / b
00166   PROD_RULE(TYPT4, RATIO_S(A, B), PROD_S(C, D),
00167              RATIO(PROD(PROD(A, C), D), B),
00168              ((_1._1 * _2._1) * _2._2) / _1._2);
00169 
00170   // simplify f * g * h regardless of the order 
00171   template <typename Prod, bool simplify = Prod::value> struct AuxProduct {
00172     typedef PROD(typename Prod::AB, typename Prod::C) type;
00173     COMBINE(typename Prod::AB, typename Prod::C, _1 * _2);
00174   };
00175   
00176   template<typename Prod>  struct AuxProduct<Prod, false> {
00177     typedef PROD_S(typename Prod::AB, typename Prod::C) type;
00178     COMBINE(typename Prod::AB, typename Prod::C, type(_1, _2));
00179   };
00180   
00181   template<typename F, typename G, typename H>
00182   struct Product<PROD_S(F, G), H> {
00183     struct prod0 { 
00184       typedef F A; typedef G B; typedef H C;
00185       typedef PROD_S(A, B) AB;
00186       inline static const A& a(const F& f, const G& g, const H& h) { return f; }
00187       inline static const B& b(const F& f, const G& g, const H& h) { return g; }
00188       inline static const C& c(const F& f, const G& g, const H& h) { return h; }
00189       enum { value = false };
00190     };
00191     struct prod1 { 
00192       typedef F A; typedef H B; typedef G C;
00193       typedef PROD_S(A, B) base;
00194       typedef PROD(A, B) AB;
00195       inline static const A& a(const F& f, const G& g, const H& h) { return f; }
00196       inline static const B& b(const F& f, const G& g, const H& h) { return h; }
00197       inline static const C& c(const F& f, const G& g, const H& h) { return g; }
00198       enum { value = ::boost::type_traits::ice_not<
00199 	     ::boost::is_same<AB, base>::value>::value };
00200     };
00201     struct prod2 { 
00202       typedef G A; typedef H B; typedef F C;
00203       typedef PROD_S(A, B) base;
00204       typedef PROD(A, B) AB;
00205       inline static const A& a(const F& f, const G& g, const H& h) { return g; }
00206       inline static const B& b(const F& f, const G& g, const H& h) { return h; }
00207       inline static const C& c(const F& f, const G& g, const H& h) { return f; }
00208       enum { value = ::boost::type_traits::ice_not<
00209 	     ::boost::is_same<AB, base>::value>::value };
00210     };
00211     
00212     typedef typename 
00213       ::boost::mpl::if_ <prod1, prod1,
00214         typename ::boost::mpl::if_ <prod2, prod2, prod0>::type
00215       >::type prod;
00216     typedef typename AuxProduct<prod>::type type;
00217     inline static type combine(const ProductStruct<F, G>& fg, const H& h) {
00218       const F& f = fg._1;
00219       const G& g = fg._2;
00220       const typename prod::A & a = prod::a(f, g, h);
00221       const typename prod::B & b = prod::b(f, g, h);
00222       const typename prod::C & c = prod::c(f, g, h);
00223       return AuxProduct<prod>::combine(a * b, c); 
00224     }
00225   };
00226 
00227 }
00228 
00229 #include "PhysicsTools/Utilities/interface/Simplify_end.h"
00230 
00231 #endif

Generated on Tue Jun 9 17:42:50 2009 for CMSSW by  doxygen 1.5.4