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
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
00052
00053 PRIMIT_RULE(TYPXT2, POWER_S(A, B), UndefinedIntegral, type());
00054
00055
00056
00057
00058 PRIMIT_RULE(TYPX, X, RATIO(POWER(X, NUM(2)), NUM(2)), pow(_, num<2>()) / num<2>());
00059
00060
00061
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
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
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
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
00093
00094 PRIMIT_RULE(TYPX, EXP_S(X), EXP(X), _);
00095
00096
00097
00098
00099 PRIMIT_RULE(TYPX, LOG_S(X), PROD(X, DIFF(LOG(X), NUM(1))),
00100 _._ * (_ - num<1>()));
00101
00102
00103
00104
00105 PRIMIT_RULE(TYPX, SGN_S(X), ABS(X), abs(_._));
00106
00107
00108
00109
00110
00111 PRIMIT_RULE(TYPX, SIN_S(X), MINUS(COS(X)), - cos(_._));
00112
00113
00114
00115
00116 PRIMIT_RULE(TYPX, COS_S(X), SIN(X), sin(_._));
00117
00118
00119
00120
00121 PRIMIT_RULE(TYPX, TAN_S(X), MINUS(LOG(ABS(COS(X)))), - log(abs(cos(_._))));
00122
00123
00124
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
00132
00133 PRIMIT_RULE(TYPX, RATIO_S(NUM(1), POWER_S(COS_S(X), NUM(2))), TAN(X), tan(_._2._1._));
00134
00135
00136
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
00142
00143
00144
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
00151
00152 PRIMIT_RULE(TYPXT1, MINUS_S(A), MINUS(PRIMIT(X, A)), - primitive<X>(_._));
00153
00154
00155
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
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
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
00284
00285
00286
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