CMS 3D CMS Logo

/data/git/CMSSW_5_3_11_patch5/src/PhysicsTools/Utilities/interface/SimplifySum.h

Go to the documentation of this file.
00001 #ifndef PhysicsTools_Utilities_SimplifySum_h
00002 #define PhysicsTools_Utilities_SimplifySum_h
00003 
00004 #include "PhysicsTools/Utilities/interface/Sum.h"
00005 #include "PhysicsTools/Utilities/interface/Difference.h"
00006 #include "PhysicsTools/Utilities/interface/Product.h"
00007 #include "PhysicsTools/Utilities/interface/Numerical.h"
00008 #include "PhysicsTools/Utilities/interface/DecomposeProduct.h"
00009 #include "PhysicsTools/Utilities/interface/ParametricTrait.h"
00010 #include <boost/type_traits.hpp>
00011 #include <boost/mpl/if.hpp>
00012 
00013 #include "PhysicsTools/Utilities/interface/Simplify_begin.h"
00014 
00015 namespace funct {
00016 
00017   // A + ( B + C ) => ( A + B ) + C
00018   SUM_RULE(TYPT3, A, SUM_S(B, C),
00019            SUM(SUM(A, B), C), (_1 + _2._1) + _2._2);
00020 
00021   // ( A + B ) + ( C + D ) => ( ( A + B ) + C ) + D
00022   SUM_RULE(TYPT4, SUM_S(A, B), SUM_S(C, D),
00023            SUM(SUM(SUM(A, B), C), D), (_1 + _2._1) + _2._2);
00024 
00025   // n + A = A + n
00026   SUM_RULE(TYPN1T1, NUM(n), A, SUM(A, NUM(n)), _2 + _1);
00027 
00028   // n + ( A + B )= ( A + B ) + n
00029   SUM_RULE(TYPN1T2, NUM(n), SUM_S(A, B), SUM(SUM_S(A, B), NUM(n)), _2 + _1);
00030 
00031   // A + 0 = A
00032   SUM_RULE(TYPT1, A, NUM(0), A, _1);
00033 
00034   // 0 + 0 = 0
00035   SUM_RULE(TYP0, NUM(0), NUM(0), NUM(0), num<0>());
00036 
00037   // ( A * B ) + 0 = ( A * B )
00038   SUM_RULE(TYPT2, PROD_S(A, B), NUM(0), PROD_S(A, B), _1);
00039 
00040   // 0 + ( A * B ) = ( A * B )
00041   SUM_RULE(TYPT2, NUM(0), PROD_S(A, B), PROD_S(A, B), _2);
00042 
00043   // 0 - ( A * B ) = - ( A * B )
00044   SUM_RULE(TYPT2, NUM(0), MINUS_S(PROD_S(A, B)), MINUS_S(PROD_S(A, B)), _2);
00045 
00046   // ( A + B ) + 0 = ( A + B )
00047   SUM_RULE(TYPT2, SUM_S(A, B), NUM(0), SUM_S(A, B), _1);
00048 
00049   // 0 + ( A + B ) = ( A + B )
00050   SUM_RULE(TYPT2, NUM(0), SUM_S(A, B), SUM_S(A, B), _2);
00051 
00052   // A - ( -B ) =  A + B
00053   DIFF_RULE(TYPT2, A, MINUS_S(B), SUM(A, B), _1 + _2._);
00054 
00055   // n * A + m * A => ( n + m ) * A
00056   template<TYPN2T1, bool parametric = Parametric<A>::value == 1>
00057     struct ParametricSimplifiedSum {
00058       typedef PROD(NUM(n), A) arg1;
00059       typedef PROD(NUM(m), A) arg2;
00060       typedef SUM_S(arg1, arg2) type;
00061       COMBINE(arg1, arg2, type(_1, _2));
00062     };
00063 
00064   TEMPL(N2T1) 
00065   struct ParametricSimplifiedSum<n, m, A, false> {
00066     typedef PROD(NUM(n + m), A) type;
00067     typedef DecomposeProduct<PROD(NUM(n), A), A> Dec;
00068     COMBINE(PROD(NUM(n), A), PROD(NUM(m), A),
00069             num<n + m>() * Dec::get(_1));
00070   };
00071 
00072   TEMPL(T1) 
00073   struct ParametricSimplifiedSum<1, 1, A, true> {
00074     typedef SumStruct<A, A> type;
00075     COMBINE(A, A, type(_1, _2));
00076   };
00077 
00078   TEMPL(T1) 
00079   struct ParametricSimplifiedSum<1, 1, A, false> {
00080     typedef PROD(NUM(2), A) type;
00081     COMBINE( A, A, num<2>() * _1 );
00082   };
00083 
00084   TEMPL(N2T1) 
00085   struct Sum<PROD_S(NUM(n), A), PROD_S(NUM(m), A) > : 
00086     public ParametricSimplifiedSum<n, m, A> { };
00087 
00088   TEMPL(N1T1) 
00089   struct Sum<A, PROD_S(NUM(n), A) > : 
00090     public ParametricSimplifiedSum<1, n, A> { };
00091 
00092   TEMPL(N1T1) 
00093   struct Sum<PROD_S(NUM(n), A) , A> : 
00094     public ParametricSimplifiedSum<n, 1, A> { };
00095 
00096   TEMPL(T1) 
00097   struct Sum<A, A> : 
00098     public ParametricSimplifiedSum<1, 1, A> { };
00099 
00100   TEMPL(T1) 
00101   struct Sum<MINUS_S(A), MINUS_S(A) > : 
00102     public ParametricSimplifiedSum<1, 1, MINUS_S(A) > { };
00103 
00104   TEMPL(T2) 
00105   struct Sum< MINUS_S(PROD_S(A, B)), 
00106     MINUS_S(PROD_S(A, B)) > : 
00107     public ParametricSimplifiedSum< 1, 1, MINUS_S(PROD_S(A, B)) > { };
00108 
00109   TEMPL(N1) 
00110   struct Sum< NUM(n), NUM(n) > : 
00111     public ParametricSimplifiedSum< 1, 1, NUM(n) > { };
00112 
00113   TEMPL(T2) 
00114   struct Sum< PROD_S(A, B), PROD_S(A, B) > : 
00115     public ParametricSimplifiedSum< 1, 1, PROD_S(A, B) > { };
00116 
00117   TEMPL(N1T1) 
00118   struct Sum< PROD_S(NUM(n), A), 
00119     PROD_S(NUM(n), A) > : 
00120     public ParametricSimplifiedSum< 1, 1, PROD_S(NUM(n), A) > { };
00121 
00122   // simplify f + g + h regardless of the order 
00123   template <typename Prod, bool simplify = Prod::value> 
00124   struct AuxSum {
00125     typedef SUM(typename Prod::AB, typename Prod::C) type;
00126     COMBINE(typename Prod::AB, typename Prod::C, _1 + _2);
00127   };
00128   
00129   template<typename Prod>  
00130   struct AuxSum<Prod, false> {
00131     typedef SUM_S(typename Prod::AB, typename Prod::C) type;
00132     COMBINE(typename Prod::AB, typename Prod::C, type(_1, _2));
00133   };
00134 
00135   template<typename F, typename G, typename H>
00136   struct SimplSumOrd {
00137     struct prod0 { 
00138       typedef F A; typedef G B; typedef H C;
00139       typedef SUM_S(A, B) AB;
00140       inline static const A& a(const F& f, const G& g, const H& h) { return f; }
00141       inline static const B& b(const F& f, const G& g, const H& h) { return g; }
00142       inline static const C& c(const F& f, const G& g, const H& h) { return h; }
00143       enum { value = false };
00144     };
00145     struct prod1 { 
00146       typedef F A; typedef H B; typedef G C;
00147       typedef SUM_S(A, B) base;
00148       typedef SUM(A, B) AB;
00149       inline static const A& a(const F& f, const G& g, const H& h) { return f; }
00150       inline static const B& b(const F& f, const G& g, const H& h) { return h; }
00151       inline static const C& c(const F& f, const G& g, const H& h) { return g; }
00152       enum { value = ::boost::type_traits::ice_not< 
00153 	     ::boost::is_same< AB, base >::value >::value };
00154     };
00155     struct prod2 { 
00156       typedef G A; typedef H B; typedef F C;
00157       typedef SUM_S(A, B) base;
00158       typedef SUM(A, B) AB;
00159       inline static const A& a(const F& f, const G& g, const H& h) { return g; }
00160       inline static const B& b(const F& f, const G& g, const H& h) { return h; }
00161       inline static const C& c(const F& f, const G& g, const H& h) { return f; }
00162       enum { value = ::boost::type_traits::ice_not< 
00163 	     ::boost::is_same< AB, base >::value >::value };
00164     };
00165     
00166     typedef typename 
00167     ::boost::mpl::if_ <prod1, 
00168                        prod1,
00169                        typename ::boost::mpl::if_ <prod2,
00170                                                    prod2,
00171                                                    prod0 
00172                                                    >::type
00173                        >::type prod;
00174     typedef typename AuxSum< prod >::type type;
00175     inline static type combine(const SUM_S(F, G)& fg, const H& h) {
00176       const F& f = fg._1;
00177       const G& g = fg._2;
00178       const typename prod::A & a = prod::a(f, g, h);
00179       const typename prod::B & b = prod::b(f, g, h);
00180       const typename prod::C & c = prod::c(f, g, h);
00181       return AuxSum< prod >::combine(a + b, c); 
00182     }
00183   };
00184   
00185   TEMPL(T3) 
00186   struct Sum<SUM_S(A, B), C> : 
00187     public SimplSumOrd<A, B, C> { };
00188   
00189   TEMPL(T4) 
00190   struct Sum< SUM_S(A, B), PROD_S(C, D) > : 
00191     public SimplSumOrd< A, B, PROD_S(C, D) > { };
00192 
00193 }
00194 
00195 #include "PhysicsTools/Utilities/interface/Simplify_end.h"
00196 
00197 #endif