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
00018 SUM_RULE(TYPT3, A, SUM_S(B, C),
00019 SUM(SUM(A, B), C), (_1 + _2._1) + _2._2);
00020
00021
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
00026 SUM_RULE(TYPN1T1, NUM(n), A, SUM(A, NUM(n)), _2 + _1);
00027
00028
00029 SUM_RULE(TYPN1T2, NUM(n), SUM_S(A, B), SUM(SUM_S(A, B), NUM(n)), _2 + _1);
00030
00031
00032 SUM_RULE(TYPT1, A, NUM(0), A, _1);
00033
00034
00035 SUM_RULE(TYP0, NUM(0), NUM(0), NUM(0), num<0>());
00036
00037
00038 SUM_RULE(TYPT2, PROD_S(A, B), NUM(0), PROD_S(A, B), _1);
00039
00040
00041 SUM_RULE(TYPT2, NUM(0), PROD_S(A, B), PROD_S(A, B), _2);
00042
00043
00044 SUM_RULE(TYPT2, NUM(0), MINUS_S(PROD_S(A, B)), MINUS_S(PROD_S(A, B)), _2);
00045
00046
00047 SUM_RULE(TYPT2, SUM_S(A, B), NUM(0), SUM_S(A, B), _1);
00048
00049
00050 SUM_RULE(TYPT2, NUM(0), SUM_S(A, B), SUM_S(A, B), _2);
00051
00052
00053 DIFF_RULE(TYPT2, A, MINUS_S(B), SUM(A, B), _1 + _2._);
00054
00055
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
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