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
00014 PROD_RULE(TYPT3, A, PROD_S(B, C),
00015 PROD(PROD(A, B), C), (_1 * _2._1) * _2._2);
00016
00017
00018 PROD_RULE(TYPT1, NUM(0), A, NUM(0), num<0>());
00019
00020
00021 PROD_RULE(TYPN1, NUM(0), NUM(n), NUM(0), num<0>());
00022
00023
00024 PROD_RULE(TYPT2, NUM(0), PROD_S(A, B), NUM(0), num<0>());
00025
00026
00027 PROD_RULE(TYPT1, NUM(1), A, A, _2);
00028
00029
00030
00031 PROD_RULE(TYPN1, NUM(1), NUM(n), NUM(n), _2);
00032
00033
00034 PROD_RULE(TYPN2, NUM(1), FRACT_S(n, m), FRACT_S(n, m), _2);
00035
00036
00037 PROD_RULE(TYP0, NUM(1), NUM(1), NUM(1), num<1>());
00038
00039
00040 PROD_RULE(TYPT1, NUM(-1), A, MINUS_S(A), -_2);
00041
00042
00043 PROD_RULE(TYPN1, NUM(-1), NUM(n), NUM(-n), num<-n>());
00044
00045
00046 PROD_RULE(TYPT2, NUM(1), PROD_S(A, B), PROD_S(A, B), _2);
00047
00048
00049 PROD_RULE(TYPT2, A, MINUS_S(B), MINUS(PROD(A, B)), -(_1 * _2._));
00050
00051
00052 PROD_RULE(TYPN1T1, NUM(n), MINUS_S(A), MINUS(PROD(NUM(n), A)), -(_1 * _2._ ));
00053
00054
00055 PROD_RULE(TYPT3, PROD_S(A, B), MINUS_S(C), MINUS(PROD(PROD(A, B), C)), -(_1 * _2._));
00056
00057
00058 PROD_RULE(TYPT1, NUM(1), MINUS_S(A), MINUS(A), _2);
00059
00060
00061 PROD_RULE(TYPT2, MINUS_S(A), MINUS_S(B), PROD(A, B), _1._ * _2._);
00062
00063
00064 PROD_RULE(TYPT2, MINUS_S(A), B, MINUS(PROD(A, B)), -(_1._ * _2));
00065
00066
00067 PROD_RULE(TYPT3, A, RATIO_S(B, C), RATIO(PROD(A, B), C), (_1 * _2._1)/_2._2);
00068
00069
00070 PROD_RULE(TYPN1T2, NUM(n), RATIO_S(A, B),
00071 RATIO(PROD(NUM(n), A), B), (_1 * _2._1)/_2._2);
00072
00073
00074 PROD_RULE(TYPT2, NUM(1), RATIO_S(A, B), RATIO(A, B), _2);
00075
00076
00077 PROD_RULE(TYPT2, NUM(0), RATIO_S(A, B), NUM(0), num<0>());
00078
00079
00080 PROD_RULE(TYPN1T1, A, NUM(n), PROD(NUM(n), A), _2 * _1);
00081
00082
00083 PROD_RULE(TYPN1T2, PROD_S(A, B), NUM(n), PROD(PROD(NUM(n), A), B),
00084 (_2 * _1._1) * _1._2);
00085
00086
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
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
00096 PROD_RULE(TYPN1T2, RATIO_S(A, B), NUM(n),
00097 RATIO(PROD(NUM(n), A), B), (_2 * _1._1) / _1._2);
00098
00099
00100 PROD_RULE(TYPT3, RATIO_S(A, B), C,
00101 RATIO(PROD(A, C), B), (_1._1 * _2) / _1._2);
00102
00103
00104 PROD_RULE(TYPN2, NUM(1), FRACT(n, m), FRACT(n, m), _2);
00105
00106
00107 PROD_RULE(TYP0, NUM(0), NUM(1), NUM(0), num<0>());
00108
00109
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
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
00163 PROD_RULE(TYPN1, NUM(n), NUM(n), NUM(n*n), num<n*n>());
00164
00165
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
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