17 AdaptiveIntegratorMultiDim::AdaptiveIntegratorMultiDim(
double absTol,
double relTol,
unsigned int maxpts,
unsigned int size):
25 fError(0), fRelError(0),
31 if (fAbsTol < 0) fAbsTol = ROOT::Math::IntegratorMultiDimOptions::DefaultAbsTolerance();
32 if (fRelTol < 0) fRelTol = ROOT::Math::IntegratorMultiDimOptions::DefaultRelTolerance();
33 if (fMaxPts == 0) fMaxPts = ROOT::Math::IntegratorMultiDimOptions::DefaultNCalls();
34 if (fSize == 0) fSize = ROOT::Math::IntegratorMultiDimOptions::DefaultWKSize();
37 AdaptiveIntegratorMultiDim::AdaptiveIntegratorMultiDim(
const IMultiGenFunction &f,
double absTol,
double relTol,
unsigned int maxpts,
unsigned int size):
45 fError(0), fRelError(0),
52 if (fAbsTol < 0) fAbsTol = ROOT::Math::IntegratorMultiDimOptions::DefaultAbsTolerance();
53 if (fRelTol < 0) fRelTol = ROOT::Math::IntegratorMultiDimOptions::DefaultRelTolerance();
54 if (fMaxPts == 0) fMaxPts = ROOT::Math::IntegratorMultiDimOptions::DefaultNCalls();
55 if (fSize == 0) fSize = ROOT::Math::IntegratorMultiDimOptions::DefaultWKSize();
63 void AdaptiveIntegratorMultiDim::SetFunction(
const IMultiGenFunction &f)
70 void AdaptiveIntegratorMultiDim::SetRelTolerance(
double relTol){ this->fRelTol = relTol; }
73 void AdaptiveIntegratorMultiDim::SetAbsTolerance(
double absTol){ this->fAbsTol = absTol; }
76 double AdaptiveIntegratorMultiDim::DoIntegral(
const double* xmin,
const double * xmax,
bool absValue)
91 double epsrel = fRelTol;
92 double epsabs = fAbsTol;
99 double ctr[15], wth[15], wthl[15], z[15];
101 static const double xl2 = 0.358568582800318073;
102 static const double xl4 = 0.948683298050513796;
103 static const double xl5 = 0.688247201611685289;
104 static const double w2 = 980./6561;
105 static const double w4 = 200./19683;
106 static const double wp2 = 245./486;
107 static const double wp4 = 25./729;
109 static const double wn1[14] = { -0.193872885230909911, -0.555606360818980835,
110 -0.876695625666819078, -1.15714067977442459, -1.39694152314179743,
111 -1.59609815576893754, -1.75461057765584494, -1.87247878880251983,
112 -1.94970278920896201, -1.98628257887517146, -1.98221815780114818,
113 -1.93750952598689219, -1.85215668343240347, -1.72615963013768225};
115 static const double wn3[14] = { 0.0518213686937966768, 0.0314992633236803330,
116 0.0111771579535639891,-0.00914494741655235473,-0.0294670527866686986,
117 -0.0497891581567850424,-0.0701112635269013768, -0.0904333688970177241,
118 -0.110755474267134071, -0.131077579637250419, -0.151399685007366752,
119 -0.171721790377483099, -0.192043895747599447, -0.212366001117715794};
121 static const double wn5[14] = { 0.871183254585174982e-01, 0.435591627292587508e-01,
122 0.217795813646293754e-01, 0.108897906823146873e-01, 0.544489534115734364e-02,
123 0.272244767057867193e-02, 0.136122383528933596e-02, 0.680611917644667955e-03,
124 0.340305958822333977e-03, 0.170152979411166995e-03, 0.850764897055834977e-04,
125 0.425382448527917472e-04, 0.212691224263958736e-04, 0.106345612131979372e-04};
127 static const double wpn1[14] = { -1.33196159122085045, -2.29218106995884763,
128 -3.11522633744855959, -3.80109739368998611, -4.34979423868312742,
129 -4.76131687242798352, -5.03566529492455417, -5.17283950617283939,
130 -5.17283950617283939, -5.03566529492455417, -4.76131687242798352,
131 -4.34979423868312742, -3.80109739368998611, -3.11522633744855959};
133 static const double wpn3[14] = { 0.0445816186556927292, -0.0240054869684499309,
134 -0.0925925925925925875, -0.161179698216735251, -0.229766803840877915,
135 -0.298353909465020564, -0.366941015089163228, -0.435528120713305891,
136 -0.504115226337448555, -0.572702331961591218, -0.641289437585733882,
137 -0.709876543209876532, -0.778463648834019195, -0.847050754458161859};
145 if (n < 2 || n > 15) {
146 MATH_WARN_MSGVAL(
"AdaptiveIntegratorMultiDim::Integral",
"Wrong function dimension",n);
150 double twondm = std::pow(2.0,static_cast<int>(n));
153 unsigned int ifncls = 0;
155 unsigned int irgnst = 2*n+3;
156 unsigned int irlcls = (
unsigned int)(twondm) +2*n*(n+1)+1;
157 unsigned int isbrgn = irgnst;
158 unsigned int isbrgs = irgnst;
161 unsigned int minpts = fMinPts;
162 unsigned int maxpts = std::max(fMaxPts, irlcls) ;
164 if (minpts < 1) minpts = irlcls;
165 if (maxpts < minpts) maxpts = 10*minpts;
171 unsigned int iwk = std::max( fSize, irgnst*(1 +maxpts/irlcls)/2 );
172 double *wk =
new double[iwk+10];
175 for (j=0; j<n; j++) {
176 ctr[j] = (xmax[j] + xmin[j])*0.5;
177 wth[j] = (xmax[j] - xmin[j])*0.5;
180 double rgnvol, sum1, sum2, sum3, sum4, sum5, difmax, f2, f3, dif, aresult;
181 double rgncmp=0, rgnval, rgnerr;
183 unsigned int j1, k, l, m, idvaxn=0, idvax0=0, isbtmp, isbtpp;
189 for (j=0; j<n; j++) {
193 sum1 = (*fFun)((
const double*)z);
200 for (j=0; j<n; j++) {
201 z[j] = ctr[j] - xl2*wth[j];
202 if (absValue) f2 = std::abs((*fFun)(z));
203 else f2 = (*fFun)(z);
204 z[j] = ctr[j] + xl2*wth[j];
205 if (absValue) f2 += std::abs((*fFun)(z));
206 else f2 += (*fFun)(z);
207 wthl[j] = xl4*wth[j];
208 z[j] = ctr[j] - wthl[j];
209 if (absValue) f3 = std::abs((*fFun)(z));
210 else f3 = (*fFun)(z);
211 z[j] = ctr[j] + wthl[j];
212 if (absValue) f3 += std::abs((*fFun)(z));
213 else f3 += (*fFun)(z);
216 dif = std::abs(7*f2-f3-12*sum1);
230 wthl[j1] = -wthl[j1];
231 z[j1] = ctr[j1] + wthl[j1];
234 z[k] = ctr[k] + wthl[k];
235 if (absValue) sum4 += std::abs((*fFun)(z));
236 else sum4 += (*fFun)(z);
247 wthl[j] = -xl5*wth[j];
248 z[j] = ctr[j] + wthl[j];
251 if (absValue) sum5 += std::abs((*fFun)(z));
252 else sum5 += (*fFun)(z);
255 z[j] = ctr[j] + wthl[j];
256 if (wthl[j] > 0)
goto L90;
259 rgncmp = rgnvol*(wpn1[n-2]*sum1+wp2*sum2+wpn3[n-2]*sum3+wp4*sum4);
260 rgnval = wn1[n-2]*sum1+w2*sum2+wn3[n-2]*sum3+w4*sum4+wn5[n-2]*sum5;
265 rgnerr = std::abs(rgnval-rgncmp);
270 aresult = std::abs(result);
281 if (isbtmp > isbrgs)
goto L160;
282 if (isbtmp < isbrgs) {
283 isbtpp = isbtmp + irgnst;
284 if (wk[isbtmp-1] < wk[isbtpp-1]) isbtmp = isbtpp;
286 if (rgnerr >= wk[isbtmp-1])
goto L160;
287 for (k=0;k<irgnst;k++) {
288 wk[isbrgn-k-1] = wk[isbtmp-k-1];
294 isbtmp = (isbrgn/(2*irgnst))*irgnst;
295 if (isbtmp >= irgnst && rgnerr > wk[isbtmp-1]) {
296 for (k=0;k<irgnst;k++) {
297 wk[isbrgn-k-1] = wk[isbtmp-k-1];
304 wk[isbrgn-1] = rgnerr;
305 wk[isbrgn-2] = rgnval;
306 wk[isbrgn-3] = double(idvaxn);
308 isbtmp = isbrgn-2*j-4;
310 wk[isbtmp-1] = wth[j];
314 ctr[idvax0-1] += 2*wth[idvax0-1];
321 if (aresult != 0) relerr = abserr/aresult;
324 if (relerr < 1e-1 && aresult < 1e-20) fStatus = 0;
325 if (relerr < 1e-3 && aresult < 1e-10) fStatus = 0;
326 if (relerr < 1e-5 && aresult < 1e-5) fStatus = 0;
327 if (isbrgs+irgnst > iwk) fStatus = 2;
328 if (ifncls+2*irlcls > maxpts) {
329 if (sum1==0 && sum2==0 && sum3==0 && sum4==0 && sum5==0){
338 if ( ( relerr < epsrel || abserr < epsabs ) && ifncls >= minpts) fStatus = 0;
341 if (ifncls >= minpts) {
342 if (relerr < epsrel ) {
343 printf(
"relative tol reached for value %20.10g an rel error %20.10g \n",aresult, relerr);
346 if (abserr < epsabs ) {
347 printf(
"Absolute tol reached for value %20.10g and abs error %20.10g \n",aresult, abserr);
356 abserr -= wk[isbrgn-1];
357 result -= wk[isbrgn-2];
358 idvax0 = (
unsigned int)(wk[isbrgn-3]);
360 isbtmp = isbrgn-2*j-4;
362 wth[j] = wk[isbtmp-1];
367 MATH_ERROR_MSG(
"AdaptiveIntegratorMultiDim::DoIntegral()",
"Logic error: idvax0 < 1!");
370 wth[idvax0-1] = 0.5*wth[idvax0-1];
371 ctr[idvax0-1] -= wth[idvax0-1];
386 double AdaptiveIntegratorMultiDim::Integral(
const IMultiGenFunction &f,
const double* xmin,
const double * xmax)
390 return Integral(xmin, xmax);
394 ROOT::Math::IntegratorMultiDimOptions AdaptiveIntegratorMultiDim::Options()
const {
396 ROOT::Math::IntegratorMultiDimOptions opt;
397 opt.SetAbsTolerance(fAbsTol);
398 opt.SetRelTolerance(fRelTol);
399 opt.SetNCalls(fMaxPts);
400 opt.SetWKSize(fSize);
401 opt.SetIntegrator(
"ADAPTIVE");
405 void AdaptiveIntegratorMultiDim::SetOptions(
const ROOT::Math::IntegratorMultiDimOptions & opt)
408 if (opt.IntegratorType() != IntegrationMultiDim::kADAPTIVE) {
409 MATH_ERROR_MSG(
"AdaptiveIntegratorMultiDim::SetOptions",
"Invalid options");
412 SetAbsTolerance( opt.AbsTolerance() );
413 SetRelTolerance( opt.RelTolerance() );
414 SetMaxPts( opt.NCalls() );
415 SetSize( opt.WKSize() );