/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
PhysicsTools/Utilities/interface/SimplifyRatio.h
321 строка
12 KB
camolezi
removed boost dependencies
07 июн 2020, 22:44
07 июн 2020, 22:44
65eda09
Код
Авторство
О чём код?
#ifndef PhysicsTools_Utilities_SimplifyRatio_h #define PhysicsTools_Utilities_SimplifyRatio_h #include "PhysicsTools/Utilities/interface/Ratio.h" #include "PhysicsTools/Utilities/interface/Product.h" #include "PhysicsTools/Utilities/interface/Power.h" #include "PhysicsTools/Utilities/interface/Minus.h" #include "PhysicsTools/Utilities/interface/Fraction.h" #include "PhysicsTools/Utilities/interface/DecomposePower.h" #include "PhysicsTools/Utilities/interface/ParametricTrait.h" #include "PhysicsTools/Utilities/interface/Simplify_begin.h" #include <type_traits> namespace funct { // 0 / a = 0 RATIO_RULE(TYPT1, NUM(0), A, NUM(0), num<0>()); // a / 1 = a RATIO_RULE(TYPT1, A, NUM(1), A, _1); // ( a * b )/ 1 = a * b RATIO_RULE(TYPT2, PROD_S(A, B), NUM(1), PROD(A, B), _1); // a / ( -n ) = - ( a / n ) template <int n, typename A, bool positive = (n >= 0)> struct SimplifyNegativeRatio { typedef RATIO_S(A, NUM(n)) type; COMBINE(A, NUM(n), type(_1, _2)); }; TEMPL(N1T1) struct SimplifyNegativeRatio<n, A, false> { typedef MINUS(RATIO(A, NUM(-n))) type; COMBINE(A, NUM(n), -(_1 / num<-n>())); }; TEMPL(N1T1) struct Ratio<A, NUM(n)> : public SimplifyNegativeRatio<n, A> {}; // ( -a ) / b = - ( a / b ) RATIO_RULE(TYPT2, MINUS_S(A), B, MINUS(RATIO(A, B)), -(_1._ / _2)); // ( -a ) / n = - ( a / n ) RATIO_RULE(TYPN1T1, MINUS_S(A), NUM(n), MINUS(RATIO(A, NUM(n))), -(_1._ / _2)); //TEMPL( N1T2 struct Ratio<PROD_S( A, B ), NUM( n )> : // public SimplifyNegativeRatio<n, PROD_S( A, B )> { }; // n / ( m * a ) = (n/m) * a /* WRONG!! RATIO_RULE(TYPN2T1, NUM(n), PROD_S(NUM(m), A), \ PROD(FRACT(n, m), A), (fract<n, m>() * _2._2)); */ // ( a / b ) / c = a / ( b * c ) RATIO_RULE(TYPT3, RATIO_S(A, B), C, RATIO(A, PROD(B, C)), _1._1 / (_1._2 * _2)); // ( a / b ) / n = a / ( n * b ) RATIO_RULE(TYPN1T2, RATIO_S(A, B), NUM(n), RATIO(A, PROD(NUM(n), B)), _1._1 / (_2 * _1._2)); // ( a / b ) / ( c * d ) = a / ( b * c * d ) RATIO_RULE(TYPT4, RATIO_S(A, B), PROD_S(C, D), RATIO(A, PROD(PROD(B, C), D)), _1._1 / (_1._2 * _2)); // ( a * b ) / ( c / d ) = ( a * b * d ) / c RATIO_RULE(TYPT4, PROD_S(A, B), RATIO_S(C, D), RATIO(PROD(PROD(A, B), D), C), (_1 * _2._2) / _2._1); // ( n * a ) / ( m * b ) = ( n/m ) ( a / b ) RATIO_RULE(TYPN2T2, PROD_S(NUM(n), A), PROD_S(NUM(m), B), PROD_S(FRACT(n, m), RATIO(A, B)), (PROD_S(FRACT(n, m), RATIO(A, B))((fract<n, m>()), (_1._2 / _2._2)))); // a / ( b / c ) = a * c / b RATIO_RULE(TYPT3, A, RATIO_S(B, C), RATIO(PROD(A, C), B), (_1 * _2._2) / _2._1); // ( a + b ) / ( c / d ) = ( a + b ) * d / c RATIO_RULE(TYPT4, SUM_S(A, B), RATIO_S(C, D), RATIO(PROD(SUM(A, B), D), C), (_1 * _2._2) / _2._1); // ( a / b ) / ( c / d )= a * d / ( b * c ) 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)); // ( a + b ) / ( b + a ) = 1 template <TYPT2, bool parametric = (Parametric<A>::value == 1) || (Parametric<B>::value == 1)> struct SimplifyRatioSum { typedef RATIO_S(SUM(A, B), SUM(B, A)) type; COMBINE(SUM(A, B), SUM(B, A), type(_1, _2)); }; TEMPL(T2) struct SimplifyRatioSum<A, B, false> { typedef NUM(1) type; COMBINE(SUM(A, B), SUM(B, A), num<1>()); }; TEMPL(T2) struct Ratio<SUM_S(A, B), SUM_S(B, A)> : public SimplifyRatioSum<A, B> {}; // a^b / a^c => a^( b - c) template <TYPT3, bool parametric = (Parametric<A>::value == 1)> struct SimplifyPowerRatio { typedef POWER(A, B) arg1; typedef POWER(A, C) arg2; typedef RATIO_S(arg1, arg2) type; COMBINE(arg1, arg2, type(_1, _2)); }; TEMPL(T3) struct SimplifyPowerRatio<A, B, C, false> { typedef POWER(A, B) arg1; typedef POWER(A, C) arg2; typedef POWER(A, DIFF(B, C)) type; inline static type combine(const arg1& _1, const arg2& _2) { return pow(DecomposePower<A, B>::getBase(_1), (DecomposePower<A, B>::getExp(_1) - DecomposePower<A, C>::getExp(_2))); } }; TEMPL(T3) struct Ratio<POWER_S(A, B), POWER_S(A, C)> : public SimplifyPowerRatio<A, B, C> {}; TEMPL(T2) struct Ratio<POWER_S(A, B), POWER_S(A, B)> : public SimplifyPowerRatio<A, B, B> {}; TEMPL(T2) struct Ratio<A, POWER_S(A, B)> : public SimplifyPowerRatio<A, NUM(1), B> {}; TEMPL(N1T1) struct Ratio<A, POWER_S(A, NUM(n))> : public SimplifyPowerRatio<A, NUM(1), NUM(n)> {}; TEMPL(T2) struct Ratio<POWER_S(A, B), A> : public SimplifyPowerRatio<A, B, NUM(1)> {}; TEMPL(N1T1) struct Ratio<POWER_S(A, NUM(n)), A> : public SimplifyPowerRatio<A, NUM(n), NUM(1)> {}; TEMPL(T1) struct Ratio<A, A> : public SimplifyPowerRatio<A, NUM(1), NUM(1)> {}; TEMPL(T2) struct Ratio<PROD_S(A, B), PROD_S(A, B)> : public SimplifyPowerRatio<PROD_S(A, B), NUM(1), NUM(1)> {}; TEMPL(N1T1) struct Ratio<PROD_S(NUM(n), A), PROD_S(NUM(n), A)> : public SimplifyPowerRatio<PROD_S(NUM(n), A), NUM(1), NUM(1)> {}; RATIO_RULE(TYPN1, NUM(n), NUM(n), NUM(1), num<1>()); // simplify ( f * g ) / h // try ( f / h ) * g and ( g / h ) * f, otherwise leave ( f * g ) / h template <typename Prod, bool simplify = Prod::value> struct AuxProductRatio { typedef PROD(typename Prod::AB, typename Prod::C) type; inline static type combine(const typename Prod::A& a, const typename Prod::B& b, const typename Prod::C& c) { return (a / b) * c; } }; template <typename Prod> struct AuxProductRatio<Prod, false> { typedef RATIO_S(typename Prod::AB, typename Prod::C) type; inline static type combine(const typename Prod::A& a, const typename Prod::B& b, const typename Prod::C& c) { return type(a * b, c); } }; template <typename F, typename G, typename H> struct RatioP1 { struct prod0 { typedef F A; typedef G B; typedef H C; typedef PROD_S(A, B) AB; inline static const A& a(const F& f, const G& g, const H& h) { return f; } inline static const B& b(const F& f, const G& g, const H& h) { return g; } inline static const C& c(const F& f, const G& g, const H& h) { return h; } enum { value = false }; }; struct prod1 { typedef F A; typedef H B; typedef G C; typedef RATIO_S(A, B) base; typedef RATIO(A, B) AB; inline static const A& a(const F& f, const G& g, const H& h) { return f; } inline static const B& b(const F& f, const G& g, const H& h) { return h; } inline static const C& c(const F& f, const G& g, const H& h) { return g; } enum { value = not ::std::is_same<AB, base>::value }; }; struct prod2 { typedef G A; typedef H B; typedef F C; typedef RATIO_S(A, B) base; typedef RATIO(A, B) AB; inline static const A& a(const F& f, const G& g, const H& h) { return g; } inline static const B& b(const F& f, const G& g, const H& h) { return h; } inline static const C& c(const F& f, const G& g, const H& h) { return f; } enum { value = not ::std::is_same<AB, base>::value }; }; typedef typename std::conditional<prod1::value, prod1, typename std::conditional<prod2::value, prod2, prod0>::type>::type prod; typedef typename AuxProductRatio<prod>::type type; inline static type combine(const PROD_S(F, G) & fg, const H& h) { const F& f = fg._1; const G& g = fg._2; const typename prod::A& a = prod::a(f, g, h); const typename prod::B& b = prod::b(f, g, h); const typename prod::C& c = prod::c(f, g, h); return AuxProductRatio<prod>::combine(a, b, c); } }; // simplify c / ( a * b ) // try ( c / a ) / b and ( c / b ) / a, otherwise leave c / ( a * b ) template <typename Prod, bool simplify = Prod::value> struct AuxProductRatio2 { typedef RATIO(typename Prod::AB, typename Prod::C) type; inline static type combine(const typename Prod::A& a, const typename Prod::B& b, const typename Prod::C& c) { return (b / a) / c; } }; template <typename Prod> struct AuxProductRatio2<Prod, false> { typedef RATIO_S(typename Prod::C, typename Prod::AB) type; inline static type combine(const typename Prod::A& a, const typename Prod::B& b, const typename Prod::C& c) { return type(c, a * b); } }; template <typename F, typename G, typename H> struct RatioP2 { struct prod0 { typedef F A; typedef G B; typedef H C; typedef PROD_S(A, B) AB; inline static const A& a(const F& f, const G& g, const H& h) { return f; } inline static const B& b(const F& f, const G& g, const H& h) { return g; } inline static const C& c(const F& f, const G& g, const H& h) { return h; } enum { value = false }; }; struct prod1 { typedef F A; typedef H B; typedef G C; typedef RATIO_S(B, A) base; typedef RATIO(B, A) AB; inline static const A& a(const F& f, const G& g, const H& h) { return f; } inline static const B& b(const F& f, const G& g, const H& h) { return h; } inline static const C& c(const F& f, const G& g, const H& h) { return g; } enum { value = not ::std::is_same<AB, base>::value }; }; struct prod2 { typedef G A; typedef H B; typedef F C; typedef RATIO_S(B, A) base; typedef RATIO(B, A) AB; inline static const A& a(const F& f, const G& g, const H& h) { return g; } inline static const B& b(const F& f, const G& g, const H& h) { return h; } inline static const C& c(const F& f, const G& g, const H& h) { return f; } enum { value = not ::std::is_same<AB, base>::value }; }; typedef typename std::conditional<prod1::value, prod1, typename std::conditional<prod2::value, prod2, prod0>::type>::type prod; typedef typename AuxProductRatio2<prod>::type type; inline static type combine(const H& h, const PROD_S(F, G) & fg) { const F& f = fg._1; const G& g = fg._2; const typename prod::A& a = prod::a(f, g, h); const typename prod::B& b = prod::b(f, g, h); const typename prod::C& c = prod::c(f, g, h); return AuxProductRatio2<prod>::combine(a, b, c); } }; TEMPL(T3) struct Ratio<PROD_S(A, B), C> : public RatioP1<A, B, C> {}; TEMPL(N1T2) struct Ratio<PROD_S(A, B), NUM(n)> : public RatioP1<A, B, NUM(n)> {}; TEMPL(T3) struct Ratio<C, PROD_S(A, B)> : public RatioP2<A, B, C> {}; TEMPL(T4) struct Ratio<PROD_S(C, D), PROD_S(A, B)> : public RatioP2<A, B, PROD_S(C, D)> {}; // simplify ( a + b ) / c trying to simplify ( a / c ) and ( b / c ) template <TYPT3, bool simplify = false> struct AuxSumRatio { typedef RATIO_S(SUM_S(A, B), C) type; COMBINE(SUM_S(A, B), C, type(_1, _2)); }; TEMPL(T3) struct AuxSumRatio<A, B, C, true> { typedef SUM(RATIO(A, C), RATIO(B, C)) type; COMBINE(SUM_S(A, B), C, (_1._1 / _2) + (_1._2 / _2)); }; TEMPL(T3) struct RatioSimpl { struct ratio1 { typedef RATIO_S(A, C) base; typedef RATIO(A, C) type; enum { value = not ::std::is_same<type, base>::value }; }; struct ratio2 { typedef RATIO_S(B, C) base; typedef RATIO(B, C) type; enum { value = not ::std::is_same<type, base>::value }; }; typedef AuxSumRatio<A, B, C, ratio1::value or ratio2::value> aux; typedef typename aux::type type; COMBINE(SUM_S(A, B), C, aux::combine(_1, _2)); }; TEMPL(T3) struct Ratio<SUM_S(A, B), C> : public RatioSimpl<A, B, C> {}; TEMPL(T4) struct Ratio<SUM_S(A, B), PROD_S(C, D)> : public RatioSimpl<A, B, PROD_S(C, D)> {}; TEMPL(N1T2) struct Ratio<SUM_S(A, B), NUM(n)> : public RatioSimpl<A, B, NUM(n)> {}; } // namespace funct #include "PhysicsTools/Utilities/interface/Simplify_end.h" #endif