CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/PhysicsTools/Utilities/interface/Primitive.h

Go to the documentation of this file.
00001 #ifndef PhysicsTools_Utilities_Primitive_h
00002 #define PhysicsTools_Utilities_Primitive_h
00003 #include "PhysicsTools/Utilities/interface/Functions.h"
00004 #include "PhysicsTools/Utilities/interface/Operations.h"
00005 #include "PhysicsTools/Utilities/interface/Fraction.h"
00006 #include "PhysicsTools/Utilities/interface/Derivative.h"
00007 #include "PhysicsTools/Utilities/interface/Parameter.h"
00008 #include "PhysicsTools/Utilities/interface/Identity.h"
00009 #include <boost/type_traits.hpp>
00010 
00011 #include "PhysicsTools/Utilities/interface/Simplify_begin.h"
00012 
00013 namespace funct {
00014 
00015   struct no_var;
00016 
00017   struct UndefinedIntegral { };
00018   
00019   template<typename X, typename F, bool independent = Independent<X, F>::value> 
00020   struct ConstPrimitive {
00021     typedef UndefinedIntegral type;
00022     inline static type get(const F& f) { return type(); }
00023   };
00024 
00025   //  / 
00026   //  | c dx = c * x
00027   //  / 
00028   template<typename X, typename F>
00029   struct ConstPrimitive<X, F, true> {
00030     typedef PROD(F, X) type;
00031     inline static type get(const F& f) { return f * X(); }
00032   };
00033   
00034   template<typename F, typename X = no_var>
00035   struct Primitive : public ConstPrimitive<X, F> { };
00036 
00037   template<typename F>
00038   struct Primitive<F> {  };
00039   
00040   template<typename X, typename F>
00041   typename Primitive<F, X>::type primitive(const F& f) { 
00042     return Primitive<F, X>::get(f); 
00043   }
00044 
00045   template<typename F>
00046   typename Primitive<F>::type primitive(const F& f) { 
00047     return Primitive<F>::get(f); 
00048   }
00049 
00050   //  /
00051   //  | f ^ g dx : UNDEFINED
00052   //  /
00053   PRIMIT_RULE(TYPXT2, POWER_S(A, B), UndefinedIntegral, type());
00054   
00055   //  /
00056   //  | x dx = x ^ 2 / 2
00057   //  /
00058   PRIMIT_RULE(TYPX, X, RATIO(POWER(X, NUM(2)), NUM(2)), pow(_, num<2>()) / num<2>());
00059   
00060   //  /
00061   //  | x ^ n dx = x ^ (n + 1) / (n + 1)
00062   //  /
00063   PRIMIT_RULE(TYPXN1, POWER_S(X, NUM(n)), 
00064               RATIO(POWER(X, NUM(n + 1)), NUM(n + 1)),
00065               pow(_._1, num<n + 1>()) / num<n + 1>());
00066   
00067   //  /
00068   //  | 1 / x ^ n dx = (- 1) / ((n - 1)  x ^ (n - 1))
00069   //  /
00070   PRIMIT_RULE(TYPXN1, RATIO_S(NUM(1), POWER_S(X, NUM(n))),
00071               RATIO(NUM(-1), PROD(NUM(n - 1), POWER(X, NUM(n - 1)))),
00072               num<-1>()/(num<n - 1>() * pow(_._2._1, num<n - 1>())));
00073   
00074   PRIMIT_RULE(TYPXN1, POWER_S(RATIO_S(NUM(1), X), NUM(n)),
00075               RATIO(NUM(-1), PROD(NUM(n - 1), POWER(X, NUM(n - 1)))),
00076               num<-1>()/(num<n - 1>() * pow(_._1._2, num<n - 1>())));
00077   
00078   //  /
00079   //  | x ^ n/m dx = m / (n + m) (x)^ (n + m / m)
00080   //  /
00081   PRIMIT_RULE(TYPXN2, POWER_S(X, FRACT_S(n, m)),
00082               PROD(FRACT(m, n + m), POWER(X, FRACT(n + m, m))),
00083               (fract<m, n + m>() * pow(_._1, fract<n + m, m>())));
00084   
00085   //  /
00086   //  | sqrt(x) dx = 2/3 (x)^ 3/2
00087   //  /
00088   PRIMIT_RULE(TYPX, SQRT_S(X), PRIMIT(X, POWER_S(X, FRACT_S(1, 2))),
00089               (fract<2, 3>() * pow(_._, fract<3, 2>())));
00090 
00091   //  /
00092   //  | exp(x) dx = exp(x)
00093   //  /
00094   PRIMIT_RULE(TYPX, EXP_S(X), EXP(X), _);
00095   
00096   //  /
00097   //  | log(x) dx = x(log(x) - 1)
00098   //  /
00099   PRIMIT_RULE(TYPX, LOG_S(X), PROD(X, DIFF(LOG(X), NUM(1))),
00100               _._ * (_ - num<1>()));
00101   
00102   //  /
00103   //  | sgn(x) dx = abs(x)
00104   //  /
00105   PRIMIT_RULE(TYPX, SGN_S(X), ABS(X), abs(_._));
00106   
00107   
00108   //  /
00109   //  | sin(x) dx = - cos(x)
00110   //  /
00111   PRIMIT_RULE(TYPX, SIN_S(X), MINUS(COS(X)), - cos(_._));
00112 
00113   //  /
00114   //  | cos(x) dx = sin(x)
00115   //  /
00116   PRIMIT_RULE(TYPX, COS_S(X), SIN(X), sin(_._));
00117 
00118   //  /
00119   //  | tan(x) dx = - log(abs(cos(x)))
00120   //  /
00121   PRIMIT_RULE(TYPX, TAN_S(X), MINUS(LOG(ABS(COS(X)))), - log(abs(cos(_._))));
00122 
00123   //  /
00124   //  | 1 / x dx = log(abs(x))
00125   //  /
00126   PRIMIT_RULE(TYPX, RATIO_S(NUM(1), X), LOG(ABS(X)), log(abs(_._2)));
00127 
00128   PRIMIT_RULE(TYPX, POWER_S(X, NUM(-1)), LOG(ABS(X)), log(abs(_._1)));
00129 
00130   //  /
00131   //  | 1 / cos(x)^2 dx = tan(x)
00132   //  /
00133   PRIMIT_RULE(TYPX, RATIO_S(NUM(1), POWER_S(COS_S(X), NUM(2))), TAN(X), tan(_._2._1._));
00134   
00135   //  /
00136   //  | 1 / sin(x)^2 dx = - 1 / tan(x)
00137   //  /
00138   PRIMIT_RULE(TYPX, RATIO_S(NUM(1), POWER_S(SIN_S(X), NUM(2))), 
00139               RATIO(NUM(-1), TAN(X)), num<-1>() / tan(_._2._1._));
00140 
00141   // composite primitives
00142   
00143   //  /                    /           /
00144   //  | (f(x) + g(x)) dx = | f(x) dx + | g(x) dx
00145   //  /                    /           /
00146   PRIMIT_RULE(TYPXT2, SUM_S(A, B), SUM(PRIMIT(X, A), PRIMIT(X, B)),
00147               primitive<X>(_._1) + primitive<X>(_._2));
00148 
00149   //  /                 /          
00150   //  | (- f(x)) dx = - | f(x) dx
00151   //  /                 /          
00152   PRIMIT_RULE(TYPXT1, MINUS_S(A), MINUS(PRIMIT(X, A)), - primitive<X>(_._));
00153   
00154   //  /
00155   //  | f * g dx : defined only for f or g indep. of x or part. int.
00156   //  /
00157   
00158   template <TYPXT2,
00159     bool bint = ::boost::type_traits::ice_not<
00160     ::boost::is_same<PRIMIT(X, B), UndefinedIntegral>::value>::value,
00161     bool aint = ::boost::type_traits::ice_not<
00162     ::boost::is_same<PRIMIT(X, A), UndefinedIntegral>::value>::value>
00163     struct PartIntegral {
00164       typedef UndefinedIntegral type;
00165       GET(PROD_S(A, B), type());
00166     };
00167 
00168   TEMPL(XT2) struct PartIntegral<X, A, B, true, false> {
00169     typedef PRIMIT(X, B) B1;
00170     typedef DERIV(X, A) A1;
00171     typedef PRIMIT(X, PROD(A1, B1)) AB1;
00172     typedef DIFF(PROD(A, B1), PRIMIT(X, PROD(A1, B1))) type;
00173     inline static type get(const PROD_S(A, B)& _) { 
00174       const A& a = _._1;
00175       B1 b = primitive<X>(_._2);
00176       return a * b - primitive<X>(derivative<X>(a) * b); 
00177     }
00178   };
00179 
00180   TEMPL(XT2) struct PartIntegral<X, B, A, false, true> {
00181     typedef PRIMIT(X, B) B1;
00182     typedef DERIV(X, A) A1;
00183     typedef PRIMIT(X, PROD(A1, B1)) AB1;
00184     typedef DIFF(PROD(A, B1), PRIMIT(X, PROD(A1, B1))) type;
00185     inline static type get(const PROD_S(B, A)& _) { 
00186       const A& a = _._2;
00187       B1 b = primitive<X>(_._1);
00188       return a * b - primitive<X>(derivative<X>(a) * b); 
00189     }
00190   };
00191 
00192   TEMPL(XT2) struct PartIntegral<X, A, B, true, true> : 
00193     public PartIntegral<X, A, B, true, false> { };
00194   
00195   template <TYPXT2, bool indepf = Independent<X, A>::value, 
00196     bool indepg = Independent<X, B>::value>
00197     struct ProductPrimitive : public PartIntegral<X, A, B> { };
00198   
00199   TEMPL(XT2) struct ProductPrimitive<X, A, B, true, false> {
00200     typedef PROD(A, PRIMIT(X, B)) type;
00201     GET(PROD_S(A, B), _._1 * primitive<X>(_._2));
00202   };
00203   
00204   TEMPL(XT2) struct ProductPrimitive<X, A, B, false, true> {
00205     typedef PROD(B, PRIMIT(X, A)) type;
00206     GET(PROD_S(A, B), _._2 * primitive<X>(_._1));
00207   };
00208   
00209   TEMPL(XT2) struct ProductPrimitive<X, A, B, true, true> {
00210     typedef PROD(PROD(A, B), X) type;
00211     GET(PROD_S(A, B), _ * X());
00212   };
00213   
00214   TEMPL(XT2) struct Primitive<PROD_S(A, B), X> : 
00215     public ProductPrimitive<X, A, B> { };
00216   
00217   //  /
00218   //  | f / g dx : defined only for f or g indep. of x; try part. int.
00219   //  /
00220   
00221   template <TYPXT2,
00222     bool bint = ::boost::type_traits::ice_not<
00223     ::boost::is_same<PRIMIT(X, RATIO(NUM(1), B)), 
00224     UndefinedIntegral>::value>::value,
00225     bool aint = ::boost::type_traits::ice_not<
00226     ::boost::is_same<PRIMIT(X, A), 
00227     UndefinedIntegral>::value>::value>
00228     struct PartIntegral2 {
00229       typedef UndefinedIntegral type;
00230       GET(RATIO_S(A, B), type());
00231     };
00232 
00233   TEMPL(XT2) struct PartIntegral2<X, A, B, true, false> {
00234     typedef PRIMIT(X, RATIO(NUM(1), B)) B1;
00235     typedef DERIV(X, A) A1;
00236     typedef PRIMIT(X, PROD(A1, B1)) AB1;
00237     typedef DIFF(PROD(A, B1), AB1) type;
00238     inline static type get(const RATIO_S(A, B)& _) { 
00239       const A& a = _._1;
00240       B1 b = primitive<X>(num<1>() / _._2);
00241       return a * b - primitive<X>(derivative<X>(a) * b); 
00242     }
00243   };
00244   
00245   TEMPL(XT2) struct PartIntegral2<X, B, A, false, true> {
00246     typedef PRIMIT(X, RATIO(NUM(1), B)) B1;
00247     typedef DERIV(X, A) A1;
00248     typedef PRIMIT(X, PROD(A1, B1)) AB1;
00249     typedef DIFF(PROD(A, B1), AB1) type;
00250     inline static type get(const RATIO_S(B, A)& _) { 
00251       const A& a = _._1;
00252       B1 b = primitive<X>(num<1>() / _._2);
00253       return a * b - primitive<X>(derivative<X>(a) * b); 
00254     }
00255   };
00256 
00257   // should be improved: try both...
00258   TEMPL(XT2) struct PartIntegral2<X, A, B, true, true> : 
00259     public PartIntegral2<X, A, B, true, false> { };
00260   
00261   template <TYPXT2, bool indepa = Independent<X, A>::value, 
00262     bool indepb = Independent<X, B>::value>
00263     struct RatioPrimitive : public PartIntegral2<X, A, B> { };
00264   
00265   TEMPL(XT2) struct RatioPrimitive<X, A, B, true, false> {
00266     typedef PROD(A, PRIMIT(X, RATIO(NUM(1), B))) type;
00267     GET(RATIO_S(A, B), _._1 * primitive<X>(num<1> / _._2));
00268   };
00269 
00270   TEMPL(XT2) struct RatioPrimitive<X, A, B, false, true> {
00271     typedef RATIO(PRIMIT(X, A), B) type;
00272     GET(RATIO_S(A, B), primitive<X>(_._1) / _._2);
00273   };
00274   
00275   TEMPL(XT2) struct RatioPrimitive<X, A, B, true, true> {
00276     typedef RATIO(RATIO(A, B), X) type;
00277     GET(RATIO_S(A, B), _ * X());
00278   };
00279   
00280   TEMPL(XT2) struct Primitive<RATIO_S(A, B), X> :
00281     public RatioPrimitive<X, A, B> { };
00282 
00283   // Function integrals
00284 
00285   //  / 
00286   //  | c dx = c * x
00287   //  / 
00288   template<>
00289   struct Primitive<Parameter> {
00290     typedef Product<Parameter, Identity>::type type;
00291     inline static type get(const Parameter & p) {
00292       return p * Identity();
00293     }
00294   };
00295 
00296 }
00297 
00298 #define DECLARE_PRIMITIVE(X, F, P) \
00299 namespace funct { \
00300 template<typename X> struct Primitive<F, X> { \
00301   typedef P type; \
00302   inline static type get(const F& _) \
00303   { return type(_._); } \
00304 }; \
00305 } \
00306 struct __useless_ignoreme
00307 
00308 #define DECLARE_FUNCT_PRIMITIVE(F, P) \
00309 namespace funct { \
00310 template<> struct Primitive<F> { \
00311   typedef P type; \
00312   inline static type get(const F& _) \
00313   { return type(); } \
00314 }; \
00315 } \
00316 struct __useless_ignoreme
00317 
00318 #include "PhysicsTools/Utilities/interface/Simplify_end.h"
00319 
00320 #endif