ROOT  6.06/08
Reference Guide
GaussIntegrator.cxx
Go to the documentation of this file.
1 // @(#)root/mathcore:$Id$
2 // Authors: David Gonzalez Maline 01/2008
3 
4 /**********************************************************************
5  * *
6  * Copyright (c) 2006 , LCG ROOT MathLib Team *
7  * *
8  * *
9  **********************************************************************/
10 
11 #include "Math/GaussIntegrator.h"
12 #include "Math/IntegratorOptions.h"
13 #include <cmath>
14 
15 namespace ROOT {
16 namespace Math {
17 
18 
19 bool GaussIntegrator::fgAbsValue = false;
20 
21  GaussIntegrator::GaussIntegrator(double epsabs, double epsrel)
22 {
23 // Default Constructor. If tolerances are not given use default values from ROOT::Math::IntegratorOneDimOptions
24 
25  fEpsAbs = epsabs;
26  fEpsRel = epsrel;
28  if (epsrel < 0 || (epsabs == 0 && epsrel == 0)) fEpsRel = ROOT::Math::IntegratorOneDimOptions::DefaultRelTolerance();
29  if (std::max(fEpsRel,fEpsAbs) <= 0.0 ) {
30  fEpsRel = 1.E-9;
31  fEpsAbs = 1.E-9;
32  MATH_WARN_MSG("ROOT::Math::GausIntegrator", "Invalid tolerance given, use values of 1.E-9");
33  }
34 
35  fLastResult = fLastError = 0;
36  fUsedOnce = false;
37  fFunction = 0;
38 }
39 
41 {
42  // Destructor. (no - operations)
43 }
44 
46 { fgAbsValue = flag; }
47 
48 double GaussIntegrator::Integral(double a, double b) {
49  return DoIntegral(a, b, fFunction);
50 }
51 
53  IntegrandTransform it(this->fFunction);
54  return DoIntegral(0., 1., it.Clone());
55 }
56 
57 double GaussIntegrator::IntegralUp (double a) {
59  return DoIntegral(0., 1., it.Clone());
60 }
61 
62 double GaussIntegrator::IntegralLow (double b) {
64  return DoIntegral(0., 1., it.Clone());
65 }
66 
67 double GaussIntegrator::DoIntegral(double a, double b, const IGenFunction* function)
68 {
69  // Return Integral of function between a and b.
70 
71  if (fEpsRel <=0 || fEpsAbs <= 0) {
72  if (fEpsRel > 0) fEpsAbs = fEpsRel;
73  else if (fEpsAbs > 0) fEpsRel = fEpsAbs;
74  else {
75  MATH_INFO_MSG("ROOT::Math::GausIntegratorOneDim", "Invalid tolerance given - use default values");
78  }
79  }
80 
81  const double kHF = 0.5;
82  const double kCST = 5./1000;
83 
84  double x[12] = { 0.96028985649753623, 0.79666647741362674,
85  0.52553240991632899, 0.18343464249564980,
86  0.98940093499164993, 0.94457502307323258,
87  0.86563120238783174, 0.75540440835500303,
88  0.61787624440264375, 0.45801677765722739,
89  0.28160355077925891, 0.09501250983763744};
90 
91  double w[12] = { 0.10122853629037626, 0.22238103445337447,
92  0.31370664587788729, 0.36268378337836198,
93  0.02715245941175409, 0.06225352393864789,
94  0.09515851168249278, 0.12462897125553387,
95  0.14959598881657673, 0.16915651939500254,
96  0.18260341504492359, 0.18945061045506850};
97 
98  double h, aconst, bb, aa, c1, c2, u, s8, s16, f1, f2;
99  double xx[1];
100  int i;
101 
102  if ( fFunction == 0 )
103  {
104  MATH_ERROR_MSG("ROOT::Math::GausIntegratorOneDim", "A function must be set first!");
105  return 0.0;
106  }
107 
108  h = 0;
109  fUsedOnce = true;
110  if (b == a) return h;
111  aconst = kCST/std::abs(b-a);
112  bb = a;
113 CASE1:
114  aa = bb;
115  bb = b;
116 CASE2:
117  c1 = kHF*(bb+aa);
118  c2 = kHF*(bb-aa);
119  s8 = 0;
120  for (i=0;i<4;i++) {
121  u = c2*x[i];
122  xx[0] = c1+u;
123  f1 = (*function)(xx);
124  if (fgAbsValue) f1 = std::abs(f1);
125  xx[0] = c1-u;
126  f2 = (*function) (xx);
127  if (fgAbsValue) f2 = std::abs(f2);
128  s8 += w[i]*(f1 + f2);
129  }
130  s16 = 0;
131  for (i=4;i<12;i++) {
132  u = c2*x[i];
133  xx[0] = c1+u;
134  f1 = (*function) (xx);
135  if (fgAbsValue) f1 = std::abs(f1);
136  xx[0] = c1-u;
137  f2 = (*function) (xx);
138  if (fgAbsValue) f2 = std::abs(f2);
139  s16 += w[i]*(f1 + f2);
140  }
141  s16 = c2*s16;
142  //if (std::abs(s16-c2*s8) <= fEpsilon*(1. + std::abs(s16))) {
143  double error = std::abs(s16-c2*s8);
144  if (error <= fEpsAbs || error <= fEpsRel*std::abs(s16)) {
145  h += s16;
146  if(bb != b) goto CASE1;
147  } else {
148  bb = c1;
149  if(1. + aconst*std::abs(c2) != 1) goto CASE2;
150  double maxtol = std::max(fEpsRel, fEpsAbs);
151  MATH_WARN_MSGVAL("ROOT::Math::GausIntegrator", "Failed to reach the desired tolerance ",maxtol);
152  h = s8; //this is a crude approximation (cernlib function returned 0 !)
153  }
154 
155  fLastResult = h;
156  fLastError = std::abs(s16-c2*s8);
157 
158  return h;
159 }
160 
161 
162 double GaussIntegrator::Result () const
163 {
164  // Returns the result of the last Integral calculation.
165 
166  if (!fUsedOnce)
167  MATH_ERROR_MSG("ROOT::Math::GaussIntegrator", "You must calculate the result at least once!");
168 
169  return fLastResult;
170 }
171 
173 { return fLastError; }
174 
176 { return (fUsedOnce) ? 0 : -1; }
177 
179 {
180  // Set integration function
181  fFunction = &function;
182  // reset fUsedOne flag
183  fUsedOnce = false;
184 }
185 
186 double GaussIntegrator::Integral (const std::vector< double > &/*pts*/)
187 {
188  // not impl.
189  MATH_WARN_MSG("ROOT::Math::GaussIntegrator", "This method is not implemented in this class !");
190  return -1.0;
191 }
192 
193 double GaussIntegrator::IntegralCauchy (double /*a*/, double /*b*/, double /*c*/)
194 {
195  // not impl.
196  MATH_WARN_MSG("ROOT::Math::GaussIntegrator", "This method is not implemented in this class !");
197  return -1.0;
198 }
199 
201  // set options
204 }
205 
207  // retrieve options
209  opt.SetIntegrator("Gauss");
212  opt.SetWKSize(0);
213  opt.SetNPoints(0);
214  return opt;
215 }
216 
217 
218 
219 //implementation of IntegrandTransform class
220 
222  : fSign(kPlus), fIntegrand(integrand), fBoundary(0.), fInfiniteInterval(true) {
223 }
224 
226  : fSign(sign), fIntegrand(integrand), fBoundary(boundary), fInfiniteInterval(false) {
227 }
228 
229 double IntegrandTransform::DoEval(double x) const {
230  double result = DoEval(x, fBoundary, fSign);
231  return (result += (fInfiniteInterval ? DoEval(x, 0., -1) : 0.));
232 }
233 
234 double IntegrandTransform::DoEval(double x, double boundary, int sign) const {
235  double mappedX = 1. / x - 1.;
236  return (*fIntegrand)(boundary + sign * mappedX) * std::pow(mappedX + 1., 2);;
237 }
238 
239 double IntegrandTransform::operator()(double x) const {
240  return DoEval(x);
241 }
242 
245 }
246 
247 
248 } // end namespace Math
249 } // end namespace ROOT
virtual void SetAbsTolerance(double eps)
This method is not implemented.
double IntegralUp(double a)
Returns Integral of function on an upper semi-infinite interval.
double Error() const
Return the estimate of the absolute Error of the last Integral calculation.
Interface (abstract class) for generic functions objects of one-dimension Provides a method to evalua...
Definition: IFunction.h:133
Namespace for new ROOT classes and functions.
Definition: ROOT.py:1
double Integral()
Returns Integral of function on an infinite interval.
return c1
Definition: legend1.C:41
void SetWKSize(unsigned int size)
set workspace size
IGenFunction * Clone() const
Clone a function.
TH1 * h
Definition: legend2.C:5
GaussIntegrator(double absTol=-1, double relTol=-1)
Default Constructor.
TArc * a
Definition: textangle.C:12
void SetNPoints(unsigned int n)
set number of points rule values of 1,2,3,4,5,6 corresponds to 15,21,31,41,51,61 and they are used in...
virtual double DoIntegral(double a, double b, const IGenFunction *func)
Integration surrugate method.
#define MATH_WARN_MSG(loc, str)
Definition: Error.h:47
double RelTolerance() const
absolute tolerance
double IntegralLow(double b)
Returns Integral of function on a lower semi-infinite interval.
virtual void SetRelTolerance(double eps)
Set the desired relative Error.
Double_t x[n]
Definition: legend1.C:17
double IntegralCauchy(double a, double b, double c)
This method is not implemented.
double pow(double, double)
static Vc_ALWAYS_INLINE Vector< T > abs(const Vector< T > &x)
Definition: vector.h:450
double operator()(double x) const
#define MATH_ERROR_MSG(loc, str)
Definition: Error.h:50
int Status() const
return the status of the last integration - 0 in case of success
double DoEval(double x) const
implementation of the evaluation function. Must be implemented by derived classes ...
void AbsValue(bool flag)
Static function: set the fgAbsValue flag.
#define MATH_INFO_MSG(loc, str)
Definition: Error.h:44
const IGenFunction * fIntegrand
double AbsTolerance() const
non-static methods for retrivieng options
virtual ~GaussIntegrator()
Destructor.
Numerical one dimensional integration options.
virtual void SetOptions(const ROOT::Math::IntegratorOneDimOptions &opt)
set the options (should be re-implemented by derived classes -if more options than tolerance exist ...
double Result() const
Returns the result of the last Integral calculation.
return c2
Definition: legend2.C:14
void SetFunction(const IGenFunction &)
Set integration function (flag control if function must be copied inside).
virtual ROOT::Math::IntegratorOneDimOptions Options() const
get the option used for the integration
#define MATH_WARN_MSGVAL(loc, str, x)
Definition: Error.h:67
Auxillary inner class for mapping infinite and semi-infinite integrals.
static Vc_ALWAYS_INLINE int_v max(const int_v &x, const int_v &y)
Definition: vector.h:440
Namespace for new Math classes and functions.
double f2(const double *x)
TF1 * f1
Definition: legend1.C:11
double result[121]
Int_t sign(Double_t x)
Definition: CsgOps.cxx:89
IntegrandTransform(const IGenFunction *integrand)
void SetIntegrator(const char *name)
set 1D integrator name
void SetRelTolerance(double tol)
set the relative tolerance
const IGenFunction * fFunction
void SetAbsTolerance(double tol)
non-static methods for setting options