00001 #ifndef PhysicsTools_Utilities_NumericalIntegration_h
00002 #define PhysicsTools_Utilities_NumericalIntegration_h
00003
00004
00005
00006
00007
00008
00009
00010 #include "Math/Functor.h"
00011 #include "Math/Integrator.h"
00012 #include "Math/AllIntegrationTypes.h"
00013 #include <vector>
00014 #include <cmath>
00015 #include <memory>
00016
00017 namespace funct {
00018
00019 template<typename F>
00020 double trapezoid_integral(const F& f, double min, double max, unsigned int samples) {
00021 const double l = max - min, delta = l / samples;
00022 double sum = 0;
00023 for(unsigned int i = 0; i < samples; ++i) {
00024 sum += f(min + (i + 0.5) * delta);
00025 }
00026 return sum * delta;
00027 }
00028
00029 class TrapezoidIntegrator {
00030 public:
00031 TrapezoidIntegrator() : samples_(0) { }
00032 explicit TrapezoidIntegrator(unsigned int samples) : samples_(samples) { }
00033 template<typename F>
00034 double operator()(const F& f, double min, double max) const {
00035 return trapezoid_integral(f, min, max, samples_);
00036 }
00037 private:
00038 unsigned int samples_;
00039 };
00040
00041 class GaussLegendreIntegrator {
00042 public:
00043 GaussLegendreIntegrator() : samples_(0) { }
00044 GaussLegendreIntegrator(unsigned int samples, double epsilon);
00045 template<typename F>
00046 double operator()(const F& f, double min, double max) const {
00047 a0 = 0.5*(max + min);
00048 b0 = 0.5*(max - min);
00049 result = 0.0;
00050 for (i = 0; i < samples_; ++i) {
00051 result += w[i] * f(a0 + b0*x[i]);
00052 }
00053
00054 return result * b0;
00055 }
00056 private:
00057 unsigned int samples_;
00058 std::vector<double> x, w;
00059 mutable double a0, b0, result;
00060 mutable unsigned int i;
00061 };
00062
00063 class GaussIntegrator {
00064 public:
00065 GaussIntegrator() { }
00066 GaussIntegrator(double epsilon) : epsilon_(epsilon) { }
00067 template<typename F>
00068 double operator()(const F& f, double a, double b) const {
00069 h = 0;
00070 if (b == a) return h;
00071 aconst = kCST/std::abs(b - a);
00072 bb = a;
00073 CASE1:
00074 aa = bb;
00075 bb = b;
00076 CASE2:
00077 c1 = kHF*(bb + aa);
00078 c2 = kHF*(bb - aa);
00079 s8 = 0;
00080 for(i = 0; i < 4; ++i) {
00081 u = c2*x[i];
00082 xx = c1 + u;
00083 f1 = f(xx);
00084 xx = c1-u;
00085 f2 = f(xx);
00086 s8 += w[i]*(f1 + f2);
00087 }
00088 s16 = 0;
00089 for(i = 4; i < 12; ++i) {
00090 u = c2*x[i];
00091 xx = c1+u;
00092 f1 = f(xx);
00093 xx = c1-u;
00094 f2 = f(xx);
00095 s16 += w[i]*(f1 + f2);
00096 }
00097 s16 = c2*s16;
00098 if (std::abs(s16 - c2*s8) <= epsilon_*(1. + std::abs(s16))) {
00099 h += s16;
00100 if(bb != b) goto CASE1;
00101 } else {
00102 bb = c1;
00103 if(1. + aconst*std::abs(c2) != 1) goto CASE2;
00104 h = s8;
00105 }
00106
00107 error_ = std::abs(s16 - c2*s8);
00108 return h;
00109 }
00110 double error() const { return error_; }
00111 private:
00112 mutable double error_;
00113 double epsilon_;
00114 static const double x[12], w[12];
00115 static const double kHF;
00116 static const double kCST;
00117 mutable double h, aconst, bb, aa, c1, c2, u, s8, s16, f1, f2, xx;
00118 mutable unsigned int i;
00119 };
00120
00121 struct RootIntegrator {
00122 RootIntegrator(ROOT::Math::IntegrationOneDim::Type type = ROOT::Math::IntegrationOneDim::kADAPTIVE,
00123 double absTol = 1e-9, double relTol = 1e-6, unsigned int size = 1000, unsigned int rule = 3) :
00124 type_(type), absTol_(absTol), relTol_(relTol), size_(size), rule_(rule),
00125 integrator_(new ROOT::Math::Integrator(type, absTol, relTol, size, rule)) { }
00126 RootIntegrator(const RootIntegrator & o) {
00127 type_ = o.type_;
00128 absTol_ = o.absTol_; relTol_ = o.relTol_;
00129 size_ = o.size_; rule_ = o.rule_;
00130 integrator_.reset(new ROOT::Math::Integrator(type_, absTol_, relTol_, size_, rule_));
00131 }
00132 RootIntegrator & operator=(const RootIntegrator & o) {
00133 type_ = o.type_;
00134 absTol_ = o.absTol_; relTol_ = o.relTol_;
00135 size_ = o.size_; rule_ = o.rule_;
00136 integrator_.reset(new ROOT::Math::Integrator(type_, absTol_, relTol_, size_, rule_));
00137 return * this;
00138 }
00139 template<typename F>
00140 double operator()(const F& f, double a, double b) const {
00141 ROOT::Math::Functor1D wrapper(&f, &F::operator());
00142 integrator_->SetFunction(wrapper);
00143 return integrator_->Integral(a, b);
00144 }
00145 private:
00146 ROOT::Math::IntegrationOneDim::Type type_;
00147 double absTol_, relTol_;
00148 unsigned int size_, rule_;
00149 mutable std::auto_ptr<ROOT::Math::Integrator> integrator_;
00150 };
00151 }
00152
00153 #endif