00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "Math/GaussLegendreIntegrator.h"
00012 #include <cmath>
00013 #include <string.h>
00014 #include <algorithm>
00015
00016 namespace ROOT {
00017 namespace Math {
00018
00019 GaussLegendreIntegrator::GaussLegendreIntegrator(int num, double eps) :
00020 GaussIntegrator(eps)
00021 {
00022
00023 fNum = num;
00024 fX = 0;
00025 fW = 0;
00026
00027 CalcGaussLegendreSamplingPoints();
00028 }
00029
00030 GaussLegendreIntegrator::~GaussLegendreIntegrator()
00031 {
00032
00033
00034
00035 delete [] fX;
00036 delete [] fW;
00037 }
00038
00039 void GaussLegendreIntegrator::SetNumberPoints(int num)
00040 {
00041
00042
00043 fNum = num;
00044 CalcGaussLegendreSamplingPoints();
00045 }
00046
00047 void GaussLegendreIntegrator::GetWeightVectors(double *x, double *w) const
00048 {
00049
00050
00051 std::copy(fX,fX+fNum, x);
00052 std::copy(fW,fW+fNum, w);
00053 }
00054
00055
00056 double GaussLegendreIntegrator::DoIntegral(double a, double b, const IGenFunction* function)
00057 {
00058
00059
00060 if (fNum<=0 || fX == 0 || fW == 0)
00061 return 0;
00062
00063 fUsedOnce = true;
00064
00065 const double a0 = (b + a)/2;
00066 const double b0 = (b - a)/2;
00067
00068 double xx[1];
00069
00070 double result = 0.0;
00071 for (int i=0; i<fNum; i++)
00072 {
00073 xx[0] = a0 + b0*fX[i];
00074 result += fW[i] * (*function)(xx);
00075 }
00076
00077 fLastResult = result*b0;
00078 return fLastResult;
00079 }
00080
00081
00082 void GaussLegendreIntegrator::SetRelTolerance (double eps)
00083 {
00084
00085 fEpsilon = eps;
00086 CalcGaussLegendreSamplingPoints();
00087 }
00088
00089 void GaussLegendreIntegrator::SetAbsTolerance (double)
00090 { MATH_WARN_MSG("ROOT::Math::GaussLegendreIntegrator", "There is no Absolute Tolerance!"); }
00091
00092
00093
00094 void GaussLegendreIntegrator::CalcGaussLegendreSamplingPoints()
00095 {
00096
00097
00098
00099 if (fNum<=0 || fEpsilon<=0)
00100 return;
00101
00102 if ( fX == 0 )
00103 delete [] fX;
00104
00105 if ( fW == 0 )
00106 delete [] fW;
00107
00108 fX = new double[fNum];
00109 fW = new double[fNum];
00110
00111
00112 const unsigned int m = (fNum+1)/2;
00113
00114 double z, pp, p1,p2, p3;
00115
00116
00117 for (unsigned int i=0; i<m; i++) {
00118 z = std::cos(3.14159265358979323846*(i+0.75)/(fNum+0.5));
00119
00120
00121
00122 do {
00123 p1=1.0;
00124 p2=0.0;
00125
00126
00127
00128 for (int j=0; j<fNum; j++)
00129 {
00130 p3 = p2;
00131 p2 = p1;
00132 p1 = ((2.0*j+1.0)*z*p2-j*p3)/(j+1.0);
00133 }
00134
00135
00136
00137 pp = fNum*(z*p1-p2)/(z*z-1.0);
00138
00139 z -= p1/pp;
00140
00141 } while (std::fabs(p1/pp) > fEpsilon);
00142
00143
00144 fX[i] = -z;
00145 fX[fNum-i-1] = z;
00146
00147
00148 fW[i] = 2.0/((1.0-z*z)*pp*pp);
00149 fW[fNum-i-1] = fW[i];
00150 }
00151 }
00152
00153 ROOT::Math::IntegratorOneDimOptions GaussLegendreIntegrator::Options() const {
00154 ROOT::Math::IntegratorOneDimOptions opt;
00155 opt.SetAbsTolerance(fEpsilon);
00156 opt.SetRelTolerance(fEpsilon);
00157 opt.SetWKSize(0);
00158 opt.SetNPoints(fNum);
00159 opt.SetIntegrator("GaussLegendre");
00160 return opt;
00161 }
00162
00163 void GaussLegendreIntegrator::SetOptions(const ROOT::Math::IntegratorOneDimOptions & opt)
00164 {
00165
00166
00167
00168
00169 fEpsilon = opt.RelTolerance();
00170
00171 fNum = opt.NPoints();
00172 if (fNum <= 7) MATH_WARN_MSGVAL("GaussLegendreIntegrator::SetOptions","setting a low number of points ",fNum);
00173 CalcGaussLegendreSamplingPoints();
00174 }
00175
00176 }
00177 }