23 bool GaussIntegrator::fgAbsValue =
false;
25 GaussIntegrator::GaussIntegrator(
double epsabs,
double epsrel)
31 if (epsabs < 0 ) fEpsAbs = ROOT::Math::IntegratorOneDimOptions::DefaultAbsTolerance();
32 if (epsrel < 0 || (epsabs == 0 && epsrel == 0)) fEpsRel = ROOT::Math::IntegratorOneDimOptions::DefaultRelTolerance();
33 if (std::max(fEpsRel,fEpsAbs) <= 0.0 ) {
36 MATH_WARN_MSG(
"ROOT::Math::GausIntegrator",
"Invalid tolerance given, use values of 1.E-9");
39 fLastResult = fLastError = 0;
44 GaussIntegrator::~GaussIntegrator()
49 void GaussIntegrator::AbsValue(
bool flag)
50 { fgAbsValue = flag; }
52 double GaussIntegrator::Integral(
double a,
double b) {
53 return DoIntegral(a, b, fFunction);
56 double GaussIntegrator::Integral () {
57 IntegrandTransform it(this->fFunction);
58 return DoIntegral(0., 1., it.Clone());
61 double GaussIntegrator::IntegralUp (
double a) {
62 IntegrandTransform it(a, IntegrandTransform::kPlus, this->fFunction);
63 return DoIntegral(0., 1., it.Clone());
66 double GaussIntegrator::IntegralLow (
double b) {
67 IntegrandTransform it(b, IntegrandTransform::kMinus, this->fFunction);
68 return DoIntegral(0., 1., it.Clone());
71 double GaussIntegrator::DoIntegral(
double a,
double b,
const IGenFunction*
function)
75 if (fEpsRel <=0 || fEpsAbs <= 0) {
76 if (fEpsRel > 0) fEpsAbs = fEpsRel;
77 else if (fEpsAbs > 0) fEpsRel = fEpsAbs;
79 MATH_INFO_MSG(
"ROOT::Math::GausIntegratorOneDim",
"Invalid tolerance given - use default values");
80 fEpsRel = ROOT::Math::IntegratorOneDimOptions::DefaultRelTolerance();
81 fEpsAbs = ROOT::Math::IntegratorOneDimOptions::DefaultAbsTolerance();
85 const double kHF = 0.5;
86 const double kCST = 5./1000;
88 double x[12] = { 0.96028985649753623, 0.79666647741362674,
89 0.52553240991632899, 0.18343464249564980,
90 0.98940093499164993, 0.94457502307323258,
91 0.86563120238783174, 0.75540440835500303,
92 0.61787624440264375, 0.45801677765722739,
93 0.28160355077925891, 0.09501250983763744};
95 double w[12] = { 0.10122853629037626, 0.22238103445337447,
96 0.31370664587788729, 0.36268378337836198,
97 0.02715245941175409, 0.06225352393864789,
98 0.09515851168249278, 0.12462897125553387,
99 0.14959598881657673, 0.16915651939500254,
100 0.18260341504492359, 0.18945061045506850};
102 double h, aconst, bb, aa, c1, c2, u, s8, s16, f1, f2;
106 if ( fFunction == 0 )
108 MATH_ERROR_MSG(
"ROOT::Math::GausIntegratorOneDim",
"A function must be set first!");
114 if (b == a)
return h;
115 aconst = kCST/std::abs(b-a);
127 f1 = (*function)(xx);
128 if (fgAbsValue) f1 = std::abs(f1);
130 f2 = (*function) (xx);
131 if (fgAbsValue) f2 = std::abs(f2);
132 s8 += w[i]*(f1 + f2);
138 f1 = (*function) (xx);
139 if (fgAbsValue) f1 = std::abs(f1);
141 f2 = (*function) (xx);
142 if (fgAbsValue) f2 = std::abs(f2);
143 s16 += w[i]*(f1 + f2);
147 double error = std::abs(s16-c2*s8);
148 if (error <= fEpsAbs || error <= fEpsRel*std::abs(s16)) {
150 if(bb != b)
goto CASE1;
153 if(1. + aconst*std::abs(c2) != 1)
goto CASE2;
154 double maxtol = std::max(fEpsRel, fEpsAbs);
155 MATH_WARN_MSGVAL(
"ROOT::Math::GausIntegrator",
"Failed to reach the desired tolerance ",maxtol);
160 fLastError = std::abs(s16-c2*s8);
166 double GaussIntegrator::Result ()
const
171 MATH_ERROR_MSG(
"ROOT::Math::GaussIntegrator",
"You must calculate the result at least once!");
176 double GaussIntegrator::Error()
const
177 {
return fLastError; }
179 int GaussIntegrator::Status()
const
180 {
return (fUsedOnce) ? 0 : -1; }
182 void GaussIntegrator::SetFunction (
const IGenFunction &
function)
185 fFunction = &
function;
190 double GaussIntegrator::Integral (
const std::vector< double > &)
193 MATH_WARN_MSG(
"ROOT::Math::GaussIntegrator",
"This method is not implemented in this class !");
197 double GaussIntegrator::IntegralCauchy (
double ,
double ,
double )
200 MATH_WARN_MSG(
"ROOT::Math::GaussIntegrator",
"This method is not implemented in this class !");
204 void GaussIntegrator::SetOptions(
const ROOT::Math::IntegratorOneDimOptions & opt) {
206 SetRelTolerance(opt.RelTolerance() );
207 SetAbsTolerance(opt.AbsTolerance() );
210 ROOT::Math::IntegratorOneDimOptions GaussIntegrator::Options()
const {
212 ROOT::Math::IntegratorOneDimOptions opt;
213 opt.SetIntegrator(
"Gauss");
214 opt.SetAbsTolerance(fEpsAbs);
215 opt.SetRelTolerance(fEpsRel);
225 IntegrandTransform::IntegrandTransform(
const IGenFunction* integrand)
226 : fSign(kPlus), fIntegrand(integrand), fBoundary(0.), fInfiniteInterval(true) {
229 IntegrandTransform::IntegrandTransform(
const double boundary, ESemiInfinitySign sign,
const IGenFunction* integrand)
230 : fSign(sign), fIntegrand(integrand), fBoundary(boundary), fInfiniteInterval(false) {
233 double IntegrandTransform::DoEval(
double x)
const {
234 double result = DoEval(x, fBoundary, fSign);
235 return (result += (fInfiniteInterval ? DoEval(x, 0., -1) : 0.));
238 double IntegrandTransform::DoEval(
double x,
double boundary,
int sign)
const {
239 double mappedX = 1. / x - 1.;
240 return (*fIntegrand)(boundary + sign * mappedX) * std::pow(mappedX + 1., 2);;
243 double IntegrandTransform::operator()(
double x)
const {
247 IGenFunction* IntegrandTransform::Clone()
const {
248 return (fInfiniteInterval ?
new IntegrandTransform(fIntegrand) :
new IntegrandTransform(fBoundary, fSign, fIntegrand));