Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:33:32

0001 #ifndef PhysicsTools_Utilities_SimplifySum_h
0002 #define PhysicsTools_Utilities_SimplifySum_h
0003 
0004 #include "PhysicsTools/Utilities/interface/Sum.h"
0005 #include "PhysicsTools/Utilities/interface/Difference.h"
0006 #include "PhysicsTools/Utilities/interface/Product.h"
0007 #include "PhysicsTools/Utilities/interface/Numerical.h"
0008 #include "PhysicsTools/Utilities/interface/DecomposeProduct.h"
0009 #include "PhysicsTools/Utilities/interface/ParametricTrait.h"
0010 #include <type_traits>
0011 
0012 #include "PhysicsTools/Utilities/interface/Simplify_begin.h"
0013 
0014 namespace funct {
0015 
0016   // A + ( B + C ) => ( A + B ) + C
0017   SUM_RULE(TYPT3, A, SUM_S(B, C), SUM(SUM(A, B), C), (_1 + _2._1) + _2._2);
0018 
0019   // ( A + B ) + ( C + D ) => ( ( A + B ) + C ) + D
0020   SUM_RULE(TYPT4, SUM_S(A, B), SUM_S(C, D), SUM(SUM(SUM(A, B), C), D), (_1 + _2._1) + _2._2);
0021 
0022   // n + A = A + n
0023   SUM_RULE(TYPN1T1, NUM(n), A, SUM(A, NUM(n)), _2 + _1);
0024 
0025   // n + ( A + B )= ( A + B ) + n
0026   SUM_RULE(TYPN1T2, NUM(n), SUM_S(A, B), SUM(SUM_S(A, B), NUM(n)), _2 + _1);
0027 
0028   // A + 0 = A
0029   SUM_RULE(TYPT1, A, NUM(0), A, _1);
0030 
0031   // 0 + 0 = 0
0032   SUM_RULE(TYP0, NUM(0), NUM(0), NUM(0), num<0>());
0033 
0034   // ( A * B ) + 0 = ( A * B )
0035   SUM_RULE(TYPT2, PROD_S(A, B), NUM(0), PROD_S(A, B), _1);
0036 
0037   // 0 + ( A * B ) = ( A * B )
0038   SUM_RULE(TYPT2, NUM(0), PROD_S(A, B), PROD_S(A, B), _2);
0039 
0040   // 0 - ( A * B ) = - ( A * B )
0041   SUM_RULE(TYPT2, NUM(0), MINUS_S(PROD_S(A, B)), MINUS_S(PROD_S(A, B)), _2);
0042 
0043   // ( A + B ) + 0 = ( A + B )
0044   SUM_RULE(TYPT2, SUM_S(A, B), NUM(0), SUM_S(A, B), _1);
0045 
0046   // 0 + ( A + B ) = ( A + B )
0047   SUM_RULE(TYPT2, NUM(0), SUM_S(A, B), SUM_S(A, B), _2);
0048 
0049   // A - ( -B ) =  A + B
0050   DIFF_RULE(TYPT2, A, MINUS_S(B), SUM(A, B), _1 + _2._);
0051 
0052   // n * A + m * A => ( n + m ) * A
0053   template <TYPN2T1, bool parametric = Parametric<A>::value == 1>
0054   struct ParametricSimplifiedSum {
0055     typedef PROD(NUM(n), A) arg1;
0056     typedef PROD(NUM(m), A) arg2;
0057     typedef SUM_S(arg1, arg2) type;
0058     COMBINE(arg1, arg2, type(_1, _2));
0059   };
0060 
0061   TEMPL(N2T1)
0062   struct ParametricSimplifiedSum<n, m, A, false> {
0063     typedef PROD(NUM(n + m), A) type;
0064     typedef DecomposeProduct<PROD(NUM(n), A), A> Dec;
0065     COMBINE(PROD(NUM(n), A), PROD(NUM(m), A), num<n + m>() * Dec::get(_1));
0066   };
0067 
0068   TEMPL(T1)
0069   struct ParametricSimplifiedSum<1, 1, A, true> {
0070     typedef SumStruct<A, A> type;
0071     COMBINE(A, A, type(_1, _2));
0072   };
0073 
0074   TEMPL(T1)
0075   struct ParametricSimplifiedSum<1, 1, A, false> {
0076     typedef PROD(NUM(2), A) type;
0077     COMBINE(A, A, num<2>() * _1);
0078   };
0079 
0080   TEMPL(N2T1)
0081   struct Sum<PROD_S(NUM(n), A), PROD_S(NUM(m), A)> : public ParametricSimplifiedSum<n, m, A> {};
0082 
0083   TEMPL(N1T1)
0084   struct Sum<A, PROD_S(NUM(n), A)> : public ParametricSimplifiedSum<1, n, A> {};
0085 
0086   TEMPL(N1T1)
0087   struct Sum<PROD_S(NUM(n), A), A> : public ParametricSimplifiedSum<n, 1, A> {};
0088 
0089   TEMPL(T1)
0090   struct Sum<A, A> : public ParametricSimplifiedSum<1, 1, A> {};
0091 
0092   TEMPL(T1)
0093   struct Sum<MINUS_S(A), MINUS_S(A)> : public ParametricSimplifiedSum<1, 1, MINUS_S(A)> {};
0094 
0095   TEMPL(T2)
0096   struct Sum<MINUS_S(PROD_S(A, B)), MINUS_S(PROD_S(A, B))>
0097       : public ParametricSimplifiedSum<1, 1, MINUS_S(PROD_S(A, B))> {};
0098 
0099   TEMPL(N1)
0100   struct Sum<NUM(n), NUM(n)> : public ParametricSimplifiedSum<1, 1, NUM(n)> {};
0101 
0102   TEMPL(T2)
0103   struct Sum<PROD_S(A, B), PROD_S(A, B)> : public ParametricSimplifiedSum<1, 1, PROD_S(A, B)> {};
0104 
0105   TEMPL(N1T1)
0106   struct Sum<PROD_S(NUM(n), A), PROD_S(NUM(n), A)> : public ParametricSimplifiedSum<1, 1, PROD_S(NUM(n), A)> {};
0107 
0108   // simplify f + g + h regardless of the order
0109   template <typename Prod, bool simplify = Prod::value>
0110   struct AuxSum {
0111     typedef SUM(typename Prod::AB, typename Prod::C) type;
0112     COMBINE(typename Prod::AB, typename Prod::C, _1 + _2);
0113   };
0114 
0115   template <typename Prod>
0116   struct AuxSum<Prod, false> {
0117     typedef SUM_S(typename Prod::AB, typename Prod::C) type;
0118     COMBINE(typename Prod::AB, typename Prod::C, type(_1, _2));
0119   };
0120 
0121   template <typename F, typename G, typename H>
0122   struct SimplSumOrd {
0123     struct prod0 {
0124       typedef F A;
0125       typedef G B;
0126       typedef H C;
0127       typedef SUM_S(A, B) AB;
0128       inline static const A& a(const F& f, const G& g, const H& h) { return f; }
0129       inline static const B& b(const F& f, const G& g, const H& h) { return g; }
0130       inline static const C& c(const F& f, const G& g, const H& h) { return h; }
0131       enum { value = false };
0132     };
0133     struct prod1 {
0134       typedef F A;
0135       typedef H B;
0136       typedef G C;
0137       typedef SUM_S(A, B) base;
0138       typedef SUM(A, B) AB;
0139       inline static const A& a(const F& f, const G& g, const H& h) { return f; }
0140       inline static const B& b(const F& f, const G& g, const H& h) { return h; }
0141       inline static const C& c(const F& f, const G& g, const H& h) { return g; }
0142       enum { value = not ::std::is_same<AB, base>::value };
0143     };
0144     struct prod2 {
0145       typedef G A;
0146       typedef H B;
0147       typedef F C;
0148       typedef SUM_S(A, B) base;
0149       typedef SUM(A, B) AB;
0150       inline static const A& a(const F& f, const G& g, const H& h) { return g; }
0151       inline static const B& b(const F& f, const G& g, const H& h) { return h; }
0152       inline static const C& c(const F& f, const G& g, const H& h) { return f; }
0153       enum { value = not ::std::is_same<AB, base>::value };
0154     };
0155 
0156     typedef
0157         typename std::conditional<prod1::value, prod1, typename std::conditional<prod2::value, prod2, prod0>::type>::type
0158             prod;
0159     typedef typename AuxSum<prod>::type type;
0160     inline static type combine(const SUM_S(F, G) & fg, const H& h) {
0161       const F& f = fg._1;
0162       const G& g = fg._2;
0163       const typename prod::A& a = prod::a(f, g, h);
0164       const typename prod::B& b = prod::b(f, g, h);
0165       const typename prod::C& c = prod::c(f, g, h);
0166       return AuxSum<prod>::combine(a + b, c);
0167     }
0168   };
0169 
0170   TEMPL(T3)
0171   struct Sum<SUM_S(A, B), C> : public SimplSumOrd<A, B, C> {};
0172 
0173   TEMPL(T4)
0174   struct Sum<SUM_S(A, B), PROD_S(C, D)> : public SimplSumOrd<A, B, PROD_S(C, D)> {};
0175 
0176 }  // namespace funct
0177 
0178 #include "PhysicsTools/Utilities/interface/Simplify_end.h"
0179 
0180 #endif