00001 #ifndef PhysicsTools_Utilities_SimplifyRatio_h
00002 #define PhysicsTools_Utilities_SimplifyRatio_h
00003
00004 #include "PhysicsTools/Utilities/interface/Ratio.h"
00005 #include "PhysicsTools/Utilities/interface/Product.h"
00006 #include "PhysicsTools/Utilities/interface/Power.h"
00007 #include "PhysicsTools/Utilities/interface/Minus.h"
00008 #include "PhysicsTools/Utilities/interface/Fraction.h"
00009 #include "PhysicsTools/Utilities/interface/DecomposePower.h"
00010
00011 #include "PhysicsTools/Utilities/interface/Simplify_begin.h"
00012
00013 namespace funct {
00014
00015
00016 RATIO_RULE(TYPT1, NUM(0), A, NUM(0) , num<0>());
00017
00018
00019 RATIO_RULE(TYPT1, A, NUM(1), A, _1);
00020
00021
00022 RATIO_RULE(TYPT2, PROD_S(A, B), NUM(1), PROD(A, B), _1);
00023
00024
00025 template <int n, typename A, bool positive = (n>= 0)>
00026 struct SimplifyNegativeRatio {
00027 typedef RATIO_S(A, NUM(n)) type;
00028 COMBINE(A, NUM(n), type(_1, _2));
00029 };
00030
00031 TEMPL(N1T1)
00032 struct SimplifyNegativeRatio<n, A, false> {
00033 typedef MINUS(RATIO(A, NUM(-n))) type;
00034 COMBINE(A, NUM(n), - (_1 / num<-n>()));
00035 };
00036
00037 TEMPL(N1T1) struct Ratio<A, NUM(n)> :
00038 public SimplifyNegativeRatio<n, A> { };
00039
00040
00041 RATIO_RULE(TYPT2, MINUS_S(A), B, MINUS(RATIO(A, B)), -(_1._ / _2));
00042
00043
00044 RATIO_RULE(TYPN1T1, MINUS_S(A), NUM(n), MINUS(RATIO(A, NUM(n))), -(_1._ / _2));
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 RATIO_RULE(TYPT3, RATIO_S(A, B), C, \
00056 RATIO(A, PROD(B, C)), _1._1 / (_1._2 * _2));
00057
00058
00059 RATIO_RULE(TYPN1T2, RATIO_S(A, B), NUM(n), \
00060 RATIO(A, PROD(NUM(n), B)), _1._1 / (_2 * _1._2));
00061
00062
00063 RATIO_RULE(TYPT4, RATIO_S(A, B), PROD_S(C, D), \
00064 RATIO(A, PROD(PROD(B, C), D)), _1._1 / (_1._2 * _2));
00065
00066
00067 RATIO_RULE(TYPT4, PROD_S(A, B), RATIO_S(C, D), \
00068 RATIO(PROD(PROD(A, B), D), C), (_1 * _2._2) / _2._1);
00069
00070
00071 RATIO_RULE(TYPN2T2, PROD_S(NUM(n), A), PROD_S(NUM(m), B), \
00072 PROD_S(FRACT(n, m), RATIO(A, B)), \
00073 (PROD_S(FRACT(n, m), RATIO(A, B))((fract<n, m>()), (_1._2 / _2._2))));
00074
00075
00076 RATIO_RULE(TYPT3, A, RATIO_S(B, C), \
00077 RATIO(PROD(A, C), B), (_1 * _2._2) / _2._1);
00078
00079
00080 RATIO_RULE(TYPT4, SUM_S(A, B), RATIO_S(C, D), \
00081 RATIO(PROD(SUM(A, B), D), C), (_1 * _2._2) / _2._1);
00082
00083
00084 RATIO_RULE(TYPT4, RATIO_S(A, B), RATIO_S(C, D), \
00085 RATIO(PROD(A, D), PROD(B, C)), \
00086 (_1._1 * _2._2) / (_1._2 * _2._1));
00087
00088
00089 template<TYPT2,
00090 bool parametric = (Parametric<A>::value == 1) ||
00091 (Parametric<B>::value == 1)>
00092 struct SimplifyRatioSum {
00093 typedef RATIO_S(SUM(A, B), SUM(B, A)) type;
00094 COMBINE(SUM(A, B), SUM(B, A), type(_1, _2));
00095 };
00096
00097 TEMPL(T2) struct SimplifyRatioSum<A, B, false> {
00098 typedef NUM(1) type;
00099 COMBINE(SUM(A, B), SUM(B, A), num<1>());
00100 };
00101
00102 TEMPL(T2) struct Ratio<SUM_S(A, B), SUM_S(B, A)> :
00103 public SimplifyRatioSum<A, B> { };
00104
00105
00106 template<TYPT3, bool parametric = (Parametric<A>::value == 1)>
00107 struct SimplifyPowerRatio {
00108 typedef POWER(A, B) arg1;
00109 typedef POWER(A, C) arg2;
00110 typedef RATIO_S(arg1, arg2) type;
00111 COMBINE(arg1, arg2, type(_1, _2));
00112 };
00113
00114 TEMPL(T3)
00115 struct SimplifyPowerRatio<A, B, C, false> {
00116 typedef POWER(A, B) arg1;
00117 typedef POWER(A, C) arg2;
00118 typedef POWER(A, DIFF(B, C)) type;
00119 inline static type combine(const arg1& _1, const arg2& _2) {
00120 return pow(DecomposePower<A, B>::getBase(_1),
00121 (DecomposePower<A, B>::getExp(_1) -
00122 DecomposePower<A, C>::getExp(_2))); }
00123 };
00124
00125 TEMPL(T3) struct Ratio<POWER_S(A, B), POWER_S(A, C)> :
00126 public SimplifyPowerRatio<A, B, C> { };
00127
00128 TEMPL(T2) struct Ratio<POWER_S(A, B), POWER_S(A, B)> :
00129 public SimplifyPowerRatio<A, B, B> { };
00130
00131 TEMPL(T2) struct Ratio<A, POWER_S(A, B)> :
00132 public SimplifyPowerRatio<A, NUM(1), B> { };
00133
00134 TEMPL(N1T1) struct Ratio<A, POWER_S(A, NUM(n))> :
00135 public SimplifyPowerRatio<A, NUM(1), NUM(n)> { };
00136
00137 TEMPL(T2) struct Ratio<POWER_S(A, B), A> :
00138 public SimplifyPowerRatio<A, B, NUM(1)>{ };
00139
00140 TEMPL(N1T1) struct Ratio<POWER_S(A, NUM(n)), A> :
00141 public SimplifyPowerRatio<A, NUM(n), NUM(1)> { };
00142
00143 TEMPL(T1) struct Ratio<A, A> :
00144 public SimplifyPowerRatio<A, NUM(1), NUM(1)> { };
00145
00146 TEMPL(T2) struct Ratio<PROD_S(A, B), PROD_S(A, B)> :
00147 public SimplifyPowerRatio<PROD_S(A, B), NUM(1), NUM(1)> { };
00148
00149 TEMPL(N1T1) struct Ratio<PROD_S(NUM(n), A), PROD_S(NUM(n), A)> :
00150 public SimplifyPowerRatio<PROD_S(NUM(n), A), NUM(1), NUM(1)> { };
00151
00152 RATIO_RULE(TYPN1, NUM(n), NUM(n), NUM(1), num<1>());
00153
00154
00155
00156
00157 template <typename Prod, bool simplify = Prod::value> struct AuxProductRatio {
00158 typedef PROD(typename Prod::AB, typename Prod::C) type;
00159 inline static type combine(const typename Prod::A& a,
00160 const typename Prod::B& b,
00161 const typename Prod::C& c) { return (a / b) * c; }
00162 };
00163
00164 template<typename Prod> struct AuxProductRatio<Prod, false> {
00165 typedef RATIO_S(typename Prod::AB, typename Prod::C) type;
00166 inline static type combine(const typename Prod::A& a,
00167 const typename Prod::B& b,
00168 const typename Prod::C& c) { return type(a * b, c); }
00169 };
00170
00171 template<typename F, typename G, typename H>
00172 struct RatioP1 {
00173 struct prod0 {
00174 typedef F A; typedef G B; typedef H C;
00175 typedef PROD_S(A, B) AB;
00176 inline static const A& a(const F& f, const G& g, const H& h) { return f; }
00177 inline static const B& b(const F& f, const G& g, const H& h) { return g; }
00178 inline static const C& c(const F& f, const G& g, const H& h) { return h; }
00179 enum { value = false };
00180 };
00181 struct prod1 {
00182 typedef F A; typedef H B; typedef G C;
00183 typedef RATIO_S(A, B) base;
00184 typedef RATIO(A, B) AB;
00185 inline static const A& a(const F& f, const G& g, const H& h) { return f; }
00186 inline static const B& b(const F& f, const G& g, const H& h) { return h; }
00187 inline static const C& c(const F& f, const G& g, const H& h) { return g; }
00188 enum { value = ::boost::type_traits::ice_not<
00189 ::boost::is_same<AB, base>::value>::value };
00190 };
00191 struct prod2 {
00192 typedef G A; typedef H B; typedef F C;
00193 typedef RATIO_S(A, B) base;
00194 typedef RATIO(A, B) AB;
00195 inline static const A& a(const F& f, const G& g, const H& h) { return g; }
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 f; }
00198 enum { value = ::boost::type_traits::ice_not<
00199 ::boost::is_same<AB, base>::value>::value };
00200 };
00201
00202 typedef typename
00203 ::boost::mpl::if_<prod1,
00204 prod1,
00205 typename ::boost::mpl::if_<prod2,
00206 prod2,
00207 prod0
00208 >::type
00209 >::type prod;
00210 typedef typename AuxProductRatio<prod>::type type;
00211 inline static type combine(const PROD_S(F, G)& fg, const H& h) {
00212 const F& f = fg._1;
00213 const G& g = fg._2;
00214 const typename prod::A & a = prod::a(f, g, h);
00215 const typename prod::B & b = prod::b(f, g, h);
00216 const typename prod::C & c = prod::c(f, g, h);
00217 return AuxProductRatio<prod>::combine(a, b, c);
00218 }
00219 };
00220
00221
00222
00223
00224 template <typename Prod, bool simplify = Prod::value>
00225 struct AuxProductRatio2 {
00226 typedef RATIO(typename Prod::AB, typename Prod::C) type;
00227 inline static type combine(const typename Prod::A& a,
00228 const typename Prod::B& b,
00229 const typename Prod::C& c) { return (b / a) / c; }
00230 };
00231
00232 template<typename Prod>
00233 struct AuxProductRatio2<Prod, false> {
00234 typedef RATIO_S(typename Prod::C, typename Prod::AB) type;
00235 inline static type combine(const typename Prod::A& a,
00236 const typename Prod::B& b,
00237 const typename Prod::C& c) { return type(c, a * b); }
00238 };
00239
00240 template<typename F, typename G, typename H>
00241 struct RatioP2 {
00242 struct prod0 {
00243 typedef F A; typedef G B; typedef H C;
00244 typedef PROD_S(A, B) AB;
00245 inline static const A& a(const F& f, const G& g, const H& h) { return f; }
00246 inline static const B& b(const F& f, const G& g, const H& h) { return g; }
00247 inline static const C& c(const F& f, const G& g, const H& h) { return h; }
00248 enum { value = false };
00249 };
00250 struct prod1 {
00251 typedef F A; typedef H B; typedef G C;
00252 typedef RATIO_S(B, A) base;
00253 typedef RATIO(B, A) AB;
00254 inline static const A& a(const F& f, const G& g, const H& h) { return f; }
00255 inline static const B& b(const F& f, const G& g, const H& h) { return h; }
00256 inline static const C& c(const F& f, const G& g, const H& h) { return g; }
00257 enum { value = ::boost::type_traits::ice_not<
00258 ::boost::is_same<AB, base>::value>::value };
00259 };
00260 struct prod2 {
00261 typedef G A; typedef H B; typedef F C;
00262 typedef RATIO_S(B, A) base;
00263 typedef RATIO(B, A) AB;
00264 inline static const A& a(const F& f, const G& g, const H& h) { return g; }
00265 inline static const B& b(const F& f, const G& g, const H& h) { return h; }
00266 inline static const C& c(const F& f, const G& g, const H& h) { return f; }
00267 enum { value = ::boost::type_traits::ice_not<
00268 ::boost::is_same<AB, base>::value>::value };
00269 };
00270
00271 typedef typename
00272 ::boost::mpl::if_<prod1,
00273 prod1,
00274 typename ::boost::mpl::if_<prod2,
00275 prod2,
00276 prod0
00277 >::type
00278 >::type prod;
00279 typedef typename AuxProductRatio2<prod>::type type;
00280 inline static type combine(const H& h, const PROD_S(F, G)& fg) {
00281 const F& f = fg._1;
00282 const G& g = fg._2;
00283 const typename prod::A & a = prod::a(f, g, h);
00284 const typename prod::B & b = prod::b(f, g, h);
00285 const typename prod::C & c = prod::c(f, g, h);
00286 return AuxProductRatio2<prod>::combine(a, b, c);
00287 }
00288 };
00289
00290 TEMPL(T3) struct Ratio<PROD_S(A, B), C> :
00291 public RatioP1<A, B, C> { };
00292
00293 TEMPL(N1T2) struct Ratio<PROD_S(A, B), NUM(n)> :
00294 public RatioP1<A, B, NUM(n)> { };
00295
00296 TEMPL(T3) struct Ratio<C, PROD_S(A, B)> :
00297 public RatioP2<A, B, C> { };
00298
00299 TEMPL(T4) struct Ratio<PROD_S(C, D), PROD_S(A, B)> :
00300 public RatioP2<A, B, PROD_S(C, D)> { };
00301
00302
00303 template <TYPT3, bool simplify = false> struct AuxSumRatio {
00304 typedef RATIO_S(SUM_S(A, B), C) type;
00305 COMBINE(SUM_S(A, B), C, type(_1, _2));
00306 };
00307
00308 TEMPL(T3) struct AuxSumRatio<A, B, C, true> {
00309 typedef SUM(RATIO(A, C), RATIO(B, C)) type;
00310 COMBINE(SUM_S(A, B), C, (_1._1 / _2) + (_1._2 / _2));
00311 };
00312
00313 TEMPL(T3) struct RatioSimpl {
00314 struct ratio1 {
00315 typedef RATIO_S(A, C) base;
00316 typedef RATIO(A, C) type;
00317 enum { value = ::boost::type_traits::ice_not<
00318 ::boost::is_same<type, base>::value>::value };
00319 };
00320 struct ratio2 {
00321 typedef RATIO_S(B, C) base;
00322 typedef RATIO(B, C) type;
00323 enum { value = ::boost::type_traits::ice_not<
00324 ::boost::is_same<type, base>::value>::value };
00325 };
00326 typedef AuxSumRatio<A, B, C,
00327 ::boost::type_traits::ice_or<ratio1::value, ratio2::value>::value> aux;
00328 typedef typename aux::type type;
00329 COMBINE(SUM_S(A, B), C, aux::combine(_1, _2));
00330 };
00331
00332 TEMPL(T3) struct Ratio<SUM_S(A, B), C> :
00333 public RatioSimpl<A, B, C> { };
00334
00335 TEMPL(T4) struct Ratio<SUM_S(A, B), PROD_S(C, D)> :
00336 public RatioSimpl<A, B, PROD_S(C, D)> { };
00337
00338 TEMPL(N1T2) struct Ratio<SUM_S(A, B), NUM(n)> :
00339 public RatioSimpl<A, B, NUM(n)> { };
00340
00341 }
00342
00343 #include "PhysicsTools/Utilities/interface/Simplify_end.h"
00344
00345 #endif