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