File indexing completed on 2024-04-06 12:24:22
0001 #ifndef PhysicsTools_Utilities_SimplifyRatio_h
0002 #define PhysicsTools_Utilities_SimplifyRatio_h
0003
0004 #include "PhysicsTools/Utilities/interface/Ratio.h"
0005 #include "PhysicsTools/Utilities/interface/Product.h"
0006 #include "PhysicsTools/Utilities/interface/Power.h"
0007 #include "PhysicsTools/Utilities/interface/Minus.h"
0008 #include "PhysicsTools/Utilities/interface/Fraction.h"
0009 #include "PhysicsTools/Utilities/interface/DecomposePower.h"
0010 #include "PhysicsTools/Utilities/interface/ParametricTrait.h"
0011
0012 #include "PhysicsTools/Utilities/interface/Simplify_begin.h"
0013
0014 #include <type_traits>
0015
0016 namespace funct {
0017
0018
0019 RATIO_RULE(TYPT1, NUM(0), A, NUM(0), num<0>());
0020
0021
0022 RATIO_RULE(TYPT1, A, NUM(1), A, _1);
0023
0024
0025 RATIO_RULE(TYPT2, PROD_S(A, B), NUM(1), PROD(A, B), _1);
0026
0027
0028 template <int n, typename A, bool positive = (n >= 0)>
0029 struct SimplifyNegativeRatio {
0030 typedef RATIO_S(A, NUM(n)) type;
0031 COMBINE(A, NUM(n), type(_1, _2));
0032 };
0033
0034 TEMPL(N1T1)
0035 struct SimplifyNegativeRatio<n, A, false> {
0036 typedef MINUS(RATIO(A, NUM(-n))) type;
0037 COMBINE(A, NUM(n), -(_1 / num<-n>()));
0038 };
0039
0040 TEMPL(N1T1) struct Ratio<A, NUM(n)> : public SimplifyNegativeRatio<n, A> {};
0041
0042
0043 RATIO_RULE(TYPT2, MINUS_S(A), B, MINUS(RATIO(A, B)), -(_1._ / _2));
0044
0045
0046 RATIO_RULE(TYPN1T1, MINUS_S(A), NUM(n), MINUS(RATIO(A, NUM(n))), -(_1._ / _2));
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057 RATIO_RULE(TYPT3, RATIO_S(A, B), C, RATIO(A, PROD(B, C)), _1._1 / (_1._2 * _2));
0058
0059
0060 RATIO_RULE(TYPN1T2, RATIO_S(A, B), NUM(n), RATIO(A, PROD(NUM(n), B)), _1._1 / (_2 * _1._2));
0061
0062
0063 RATIO_RULE(TYPT4, RATIO_S(A, B), PROD_S(C, D), RATIO(A, PROD(PROD(B, C), D)), _1._1 / (_1._2 * _2));
0064
0065
0066 RATIO_RULE(TYPT4, PROD_S(A, B), RATIO_S(C, D), RATIO(PROD(PROD(A, B), D), C), (_1 * _2._2) / _2._1);
0067
0068
0069 RATIO_RULE(TYPN2T2,
0070 PROD_S(NUM(n), A),
0071 PROD_S(NUM(m), B),
0072 PROD_S(FRACT(n, m), RATIO(A, B)),
0073 (PROD_S(FRACT(n, m), RATIO(A, B))((fract<n, m>()), (_1._2 / _2._2))));
0074
0075
0076 RATIO_RULE(TYPT3, A, RATIO_S(B, C), RATIO(PROD(A, C), B), (_1 * _2._2) / _2._1);
0077
0078
0079 RATIO_RULE(TYPT4, SUM_S(A, B), RATIO_S(C, D), RATIO(PROD(SUM(A, B), D), C), (_1 * _2._2) / _2._1);
0080
0081
0082 RATIO_RULE(TYPT4, RATIO_S(A, B), RATIO_S(C, D), RATIO(PROD(A, D), PROD(B, C)), (_1._1 * _2._2) / (_1._2 * _2._1));
0083
0084
0085 template <TYPT2, bool parametric = (Parametric<A>::value == 1) || (Parametric<B>::value == 1)>
0086 struct SimplifyRatioSum {
0087 typedef RATIO_S(SUM(A, B), SUM(B, A)) type;
0088 COMBINE(SUM(A, B), SUM(B, A), type(_1, _2));
0089 };
0090
0091 TEMPL(T2) struct SimplifyRatioSum<A, B, false> {
0092 typedef NUM(1) type;
0093 COMBINE(SUM(A, B), SUM(B, A), num<1>());
0094 };
0095
0096 TEMPL(T2) struct Ratio<SUM_S(A, B), SUM_S(B, A)> : public SimplifyRatioSum<A, B> {};
0097
0098
0099 template <TYPT3, bool parametric = (Parametric<A>::value == 1)>
0100 struct SimplifyPowerRatio {
0101 typedef POWER(A, B) arg1;
0102 typedef POWER(A, C) arg2;
0103 typedef RATIO_S(arg1, arg2) type;
0104 COMBINE(arg1, arg2, type(_1, _2));
0105 };
0106
0107 TEMPL(T3)
0108 struct SimplifyPowerRatio<A, B, C, false> {
0109 typedef POWER(A, B) arg1;
0110 typedef POWER(A, C) arg2;
0111 typedef POWER(A, DIFF(B, C)) type;
0112 inline static type combine(const arg1& _1, const arg2& _2) {
0113 return pow(DecomposePower<A, B>::getBase(_1),
0114 (DecomposePower<A, B>::getExp(_1) - DecomposePower<A, C>::getExp(_2)));
0115 }
0116 };
0117
0118 TEMPL(T3) struct Ratio<POWER_S(A, B), POWER_S(A, C)> : public SimplifyPowerRatio<A, B, C> {};
0119
0120 TEMPL(T2) struct Ratio<POWER_S(A, B), POWER_S(A, B)> : public SimplifyPowerRatio<A, B, B> {};
0121
0122 TEMPL(T2) struct Ratio<A, POWER_S(A, B)> : public SimplifyPowerRatio<A, NUM(1), B> {};
0123
0124 TEMPL(N1T1) struct Ratio<A, POWER_S(A, NUM(n))> : public SimplifyPowerRatio<A, NUM(1), NUM(n)> {};
0125
0126 TEMPL(T2) struct Ratio<POWER_S(A, B), A> : public SimplifyPowerRatio<A, B, NUM(1)> {};
0127
0128 TEMPL(N1T1) struct Ratio<POWER_S(A, NUM(n)), A> : public SimplifyPowerRatio<A, NUM(n), NUM(1)> {};
0129
0130 TEMPL(T1) struct Ratio<A, A> : public SimplifyPowerRatio<A, NUM(1), NUM(1)> {};
0131
0132 TEMPL(T2) struct Ratio<PROD_S(A, B), PROD_S(A, B)> : public SimplifyPowerRatio<PROD_S(A, B), NUM(1), NUM(1)> {};
0133
0134 TEMPL(N1T1)
0135 struct Ratio<PROD_S(NUM(n), A), PROD_S(NUM(n), A)> : public SimplifyPowerRatio<PROD_S(NUM(n), A), NUM(1), NUM(1)> {};
0136
0137 RATIO_RULE(TYPN1, NUM(n), NUM(n), NUM(1), num<1>());
0138
0139
0140
0141
0142 template <typename Prod, bool simplify = Prod::value>
0143 struct AuxProductRatio {
0144 typedef PROD(typename Prod::AB, typename Prod::C) type;
0145 inline static type combine(const typename Prod::A& a, const typename Prod::B& b, const typename Prod::C& c) {
0146 return (a / b) * c;
0147 }
0148 };
0149
0150 template <typename Prod>
0151 struct AuxProductRatio<Prod, false> {
0152 typedef RATIO_S(typename Prod::AB, typename Prod::C) type;
0153 inline static type combine(const typename Prod::A& a, const typename Prod::B& b, const typename Prod::C& c) {
0154 return type(a * b, c);
0155 }
0156 };
0157
0158 template <typename F, typename G, typename H>
0159 struct RatioP1 {
0160 struct prod0 {
0161 typedef F A;
0162 typedef G B;
0163 typedef H C;
0164 typedef PROD_S(A, B) AB;
0165 inline static const A& a(const F& f, const G& g, const H& h) { return f; }
0166 inline static const B& b(const F& f, const G& g, const H& h) { return g; }
0167 inline static const C& c(const F& f, const G& g, const H& h) { return h; }
0168 enum { value = false };
0169 };
0170 struct prod1 {
0171 typedef F A;
0172 typedef H B;
0173 typedef G C;
0174 typedef RATIO_S(A, B) base;
0175 typedef RATIO(A, B) AB;
0176 inline static const A& a(const F& f, const G& g, const H& h) { return f; }
0177 inline static const B& b(const F& f, const G& g, const H& h) { return h; }
0178 inline static const C& c(const F& f, const G& g, const H& h) { return g; }
0179 enum { value = not ::std::is_same<AB, base>::value };
0180 };
0181 struct prod2 {
0182 typedef G A;
0183 typedef H B;
0184 typedef F C;
0185 typedef RATIO_S(A, B) base;
0186 typedef RATIO(A, B) AB;
0187 inline static const A& a(const F& f, const G& g, const H& h) { return g; }
0188 inline static const B& b(const F& f, const G& g, const H& h) { return h; }
0189 inline static const C& c(const F& f, const G& g, const H& h) { return f; }
0190 enum { value = not ::std::is_same<AB, base>::value };
0191 };
0192
0193 typedef
0194 typename std::conditional<prod1::value, prod1, typename std::conditional<prod2::value, prod2, prod0>::type>::type
0195 prod;
0196 typedef typename AuxProductRatio<prod>::type type;
0197 inline static type combine(const PROD_S(F, G) & fg, const H& h) {
0198 const F& f = fg._1;
0199 const G& g = fg._2;
0200 const typename prod::A& a = prod::a(f, g, h);
0201 const typename prod::B& b = prod::b(f, g, h);
0202 const typename prod::C& c = prod::c(f, g, h);
0203 return AuxProductRatio<prod>::combine(a, b, c);
0204 }
0205 };
0206
0207
0208
0209
0210 template <typename Prod, bool simplify = Prod::value>
0211 struct AuxProductRatio2 {
0212 typedef RATIO(typename Prod::AB, typename Prod::C) type;
0213 inline static type combine(const typename Prod::A& a, const typename Prod::B& b, const typename Prod::C& c) {
0214 return (b / a) / c;
0215 }
0216 };
0217
0218 template <typename Prod>
0219 struct AuxProductRatio2<Prod, false> {
0220 typedef RATIO_S(typename Prod::C, typename Prod::AB) type;
0221 inline static type combine(const typename Prod::A& a, const typename Prod::B& b, const typename Prod::C& c) {
0222 return type(c, a * b);
0223 }
0224 };
0225
0226 template <typename F, typename G, typename H>
0227 struct RatioP2 {
0228 struct prod0 {
0229 typedef F A;
0230 typedef G B;
0231 typedef H C;
0232 typedef PROD_S(A, B) AB;
0233 inline static const A& a(const F& f, const G& g, const H& h) { return f; }
0234 inline static const B& b(const F& f, const G& g, const H& h) { return g; }
0235 inline static const C& c(const F& f, const G& g, const H& h) { return h; }
0236 enum { value = false };
0237 };
0238 struct prod1 {
0239 typedef F A;
0240 typedef H B;
0241 typedef G C;
0242 typedef RATIO_S(B, A) base;
0243 typedef RATIO(B, A) AB;
0244 inline static const A& a(const F& f, const G& g, const H& h) { return f; }
0245 inline static const B& b(const F& f, const G& g, const H& h) { return h; }
0246 inline static const C& c(const F& f, const G& g, const H& h) { return g; }
0247 enum { value = not ::std::is_same<AB, base>::value };
0248 };
0249 struct prod2 {
0250 typedef G A;
0251 typedef H B;
0252 typedef F C;
0253 typedef RATIO_S(B, A) base;
0254 typedef RATIO(B, A) AB;
0255 inline static const A& a(const F& f, const G& g, const H& h) { return g; }
0256 inline static const B& b(const F& f, const G& g, const H& h) { return h; }
0257 inline static const C& c(const F& f, const G& g, const H& h) { return f; }
0258 enum { value = not ::std::is_same<AB, base>::value };
0259 };
0260
0261 typedef
0262 typename std::conditional<prod1::value, prod1, typename std::conditional<prod2::value, prod2, prod0>::type>::type
0263 prod;
0264 typedef typename AuxProductRatio2<prod>::type type;
0265 inline static type combine(const H& h, const PROD_S(F, G) & fg) {
0266 const F& f = fg._1;
0267 const G& g = fg._2;
0268 const typename prod::A& a = prod::a(f, g, h);
0269 const typename prod::B& b = prod::b(f, g, h);
0270 const typename prod::C& c = prod::c(f, g, h);
0271 return AuxProductRatio2<prod>::combine(a, b, c);
0272 }
0273 };
0274
0275 TEMPL(T3) struct Ratio<PROD_S(A, B), C> : public RatioP1<A, B, C> {};
0276
0277 TEMPL(N1T2) struct Ratio<PROD_S(A, B), NUM(n)> : public RatioP1<A, B, NUM(n)> {};
0278
0279 TEMPL(T3) struct Ratio<C, PROD_S(A, B)> : public RatioP2<A, B, C> {};
0280
0281 TEMPL(T4) struct Ratio<PROD_S(C, D), PROD_S(A, B)> : public RatioP2<A, B, PROD_S(C, D)> {};
0282
0283
0284 template <TYPT3, bool simplify = false>
0285 struct AuxSumRatio {
0286 typedef RATIO_S(SUM_S(A, B), C) type;
0287 COMBINE(SUM_S(A, B), C, type(_1, _2));
0288 };
0289
0290 TEMPL(T3) struct AuxSumRatio<A, B, C, true> {
0291 typedef SUM(RATIO(A, C), RATIO(B, C)) type;
0292 COMBINE(SUM_S(A, B), C, (_1._1 / _2) + (_1._2 / _2));
0293 };
0294
0295 TEMPL(T3) struct RatioSimpl {
0296 struct ratio1 {
0297 typedef RATIO_S(A, C) base;
0298 typedef RATIO(A, C) type;
0299 enum { value = not ::std::is_same<type, base>::value };
0300 };
0301 struct ratio2 {
0302 typedef RATIO_S(B, C) base;
0303 typedef RATIO(B, C) type;
0304 enum { value = not ::std::is_same<type, base>::value };
0305 };
0306 typedef AuxSumRatio<A, B, C, ratio1::value or ratio2::value> aux;
0307 typedef typename aux::type type;
0308 COMBINE(SUM_S(A, B), C, aux::combine(_1, _2));
0309 };
0310
0311 TEMPL(T3) struct Ratio<SUM_S(A, B), C> : public RatioSimpl<A, B, C> {};
0312
0313 TEMPL(T4) struct Ratio<SUM_S(A, B), PROD_S(C, D)> : public RatioSimpl<A, B, PROD_S(C, D)> {};
0314
0315 TEMPL(N1T2) struct Ratio<SUM_S(A, B), NUM(n)> : public RatioSimpl<A, B, NUM(n)> {};
0316
0317 }
0318
0319 #include "PhysicsTools/Utilities/interface/Simplify_end.h"
0320
0321 #endif