CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_1/src/PhysicsTools/Utilities/interface/SimplifyRatio.h

Go to the documentation of this file.
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   // 0 / a = 0
00016   RATIO_RULE(TYPT1, NUM(0), A, NUM(0) , num<0>());
00017 
00018   // a / 1 = a
00019   RATIO_RULE(TYPT1, A, NUM(1), A, _1);
00020 
00021   // ( a * b )/ 1 = a * b
00022   RATIO_RULE(TYPT2, PROD_S(A, B), NUM(1), PROD(A, B), _1);
00023   
00024   // a / ( -n ) = - ( a / n )
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   // ( -a ) / b = - ( a / b )
00041   RATIO_RULE(TYPT2, MINUS_S(A), B, MINUS(RATIO(A, B)), -(_1._ / _2));
00042 
00043   // ( -a ) / n = - ( a / n )
00044   RATIO_RULE(TYPN1T1, MINUS_S(A), NUM(n), MINUS(RATIO(A, NUM(n))), -(_1._ / _2));
00045 
00046   //TEMPL( N1T2 struct Ratio<PROD_S( A, B ), NUM( n )> : 
00047   //  public SimplifyNegativeRatio<n, PROD_S( A, B )> { };
00048   
00049   // n / ( m * a ) = (n/m) * a
00050   /* WRONG!!
00051   RATIO_RULE(TYPN2T1, NUM(n), PROD_S(NUM(m), A), \
00052              PROD(FRACT(n, m), A), (fract<n, m>() * _2._2));
00053   */
00054   // ( a / b ) / c = a / ( b * c )
00055   RATIO_RULE(TYPT3, RATIO_S(A, B), C, \
00056              RATIO(A, PROD(B, C)), _1._1 / (_1._2 * _2));
00057     
00058   // ( a / b ) / n = a / ( n * b )
00059   RATIO_RULE(TYPN1T2, RATIO_S(A, B), NUM(n), \
00060              RATIO(A, PROD(NUM(n), B)), _1._1 / (_2 * _1._2));
00061 
00062   // ( a / b ) / ( c * d ) = a / ( b * c * d )
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   // ( a * b ) / ( c / d ) = ( a * b * d ) / c
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   // ( n * a ) / ( m * b ) = ( n/m ) ( a / b )
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   //  a / ( b / c ) = a * c / b
00076   RATIO_RULE(TYPT3, A, RATIO_S(B, C), \
00077              RATIO(PROD(A, C), B), (_1 * _2._2) / _2._1);
00078 
00079   //  ( a + b ) / ( c / d ) = ( a + b ) * d / c
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   // ( a / b ) / ( c / d )= a * d / ( b * c )
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   // ( a + b ) / ( b + a ) = 1
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   // a^b / a^c => a^( b - c)
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   // simplify ( f * g ) / h
00155   // try ( f / h ) * g and ( g / h ) * f, otherwise leave ( f * g ) / h
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   // simplify c / ( a * b )
00222   // try ( c / a ) / b and ( c / b ) / a, otherwise leave c / ( a * b )
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   // simplify ( a + b ) / c trying to simplify ( a / c ) and ( b / c ) 
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