00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "RooFit.h"
00027 #include "Riostream.h"
00028
00029 #include "TClass.h"
00030 #include "RooIntegrator1D.h"
00031 #include "RooArgSet.h"
00032 #include "RooRealVar.h"
00033 #include "RooNumber.h"
00034 #include "RooIntegratorBinding.h"
00035 #include "RooNumIntConfig.h"
00036 #include "RooNumIntFactory.h"
00037 #include "RooMsgService.h"
00038
00039 #include <assert.h>
00040
00041
00042
00043 ClassImp(RooIntegrator1D)
00044 ;
00045
00046
00047
00048
00049 void RooIntegrator1D::registerIntegrator(RooNumIntFactory& fact)
00050 {
00051
00052
00053 RooCategory sumRule("sumRule","Summation Rule") ;
00054 sumRule.defineType("Trapezoid",RooIntegrator1D::Trapezoid) ;
00055 sumRule.defineType("Midpoint",RooIntegrator1D::Midpoint) ;
00056 sumRule.setLabel("Trapezoid") ;
00057 RooCategory extrap("extrapolation","Extrapolation procedure") ;
00058 extrap.defineType("None",0) ;
00059 extrap.defineType("Wynn-Epsilon",1) ;
00060 extrap.setLabel("Wynn-Epsilon") ;
00061 RooRealVar maxSteps("maxSteps","Maximum number of steps",20) ;
00062 RooRealVar minSteps("minSteps","Minimum number of steps",999) ;
00063 RooRealVar fixSteps("fixSteps","Fixed number of steps",0) ;
00064
00065 RooIntegrator1D* proto = new RooIntegrator1D() ;
00066 fact.storeProtoIntegrator(proto,RooArgSet(sumRule,extrap,maxSteps,minSteps,fixSteps)) ;
00067 RooNumIntConfig::defaultConfig().method1D().setLabel(proto->IsA()->GetName()) ;
00068 }
00069
00070
00071
00072
00073 RooIntegrator1D::RooIntegrator1D() :
00074 _h(0), _s(0), _c(0), _d(0), _x(0)
00075 {
00076
00077 }
00078
00079
00080
00081 RooIntegrator1D::RooIntegrator1D(const RooAbsFunc& function, SummationRule rule,
00082 Int_t maxSteps, Double_t eps) :
00083 RooAbsIntegrator(function), _rule(rule), _maxSteps(maxSteps), _minStepsZero(999), _fixSteps(0), _epsAbs(eps), _epsRel(eps), _doExtrap(kTRUE)
00084 {
00085
00086
00087
00088
00089 _useIntegrandLimits= kTRUE;
00090 _valid= initialize();
00091 }
00092
00093
00094
00095 RooIntegrator1D::RooIntegrator1D(const RooAbsFunc& function, Double_t xmin, Double_t xmax,
00096 SummationRule rule, Int_t maxSteps, Double_t eps) :
00097 RooAbsIntegrator(function),
00098 _rule(rule),
00099 _maxSteps(maxSteps),
00100 _minStepsZero(999),
00101 _fixSteps(0),
00102 _epsAbs(eps),
00103 _epsRel(eps),
00104 _doExtrap(kTRUE)
00105 {
00106
00107
00108
00109
00110
00111 _useIntegrandLimits= kFALSE;
00112 _xmin= xmin;
00113 _xmax= xmax;
00114 _valid= initialize();
00115 }
00116
00117
00118
00119 RooIntegrator1D::RooIntegrator1D(const RooAbsFunc& function, const RooNumIntConfig& config) :
00120 RooAbsIntegrator(function,config.printEvalCounter()),
00121 _epsAbs(config.epsAbs()),
00122 _epsRel(config.epsRel())
00123 {
00124
00125
00126
00127
00128
00129 const RooArgSet& configSet = config.getConfigSection(IsA()->GetName()) ;
00130 _rule = (SummationRule) configSet.getCatIndex("sumRule",Trapezoid) ;
00131 _maxSteps = (Int_t) configSet.getRealValue("maxSteps",20) ;
00132 _minStepsZero = (Int_t) configSet.getRealValue("minSteps",999) ;
00133 _fixSteps = (Int_t) configSet.getRealValue("fixSteps",0) ;
00134 _doExtrap = (Bool_t) configSet.getCatIndex("extrapolation",1) ;
00135
00136 if (_fixSteps>_maxSteps) {
00137 oocoutE((TObject*)0,Integration) << "RooIntegrator1D::ctor() ERROR: fixSteps>maxSteps, fixSteps set to maxSteps" << endl ;
00138 _fixSteps = _maxSteps ;
00139 }
00140
00141 _useIntegrandLimits= kTRUE;
00142 _valid= initialize();
00143 }
00144
00145
00146
00147
00148 RooIntegrator1D::RooIntegrator1D(const RooAbsFunc& function, Double_t xmin, Double_t xmax,
00149 const RooNumIntConfig& config) :
00150 RooAbsIntegrator(function,config.printEvalCounter()),
00151 _epsAbs(config.epsAbs()),
00152 _epsRel(config.epsRel())
00153 {
00154
00155
00156
00157
00158 const RooArgSet& configSet = config.getConfigSection(IsA()->GetName()) ;
00159 _rule = (SummationRule) configSet.getCatIndex("sumRule",Trapezoid) ;
00160 _maxSteps = (Int_t) configSet.getRealValue("maxSteps",20) ;
00161 _minStepsZero = (Int_t) configSet.getRealValue("minSteps",999) ;
00162 _fixSteps = (Int_t) configSet.getRealValue("fixSteps",0) ;
00163 _doExtrap = (Bool_t) configSet.getCatIndex("extrapolation",1) ;
00164
00165 _useIntegrandLimits= kFALSE;
00166 _xmin= xmin;
00167 _xmax= xmax;
00168 _valid= initialize();
00169 }
00170
00171
00172
00173
00174 RooAbsIntegrator* RooIntegrator1D::clone(const RooAbsFunc& function, const RooNumIntConfig& config) const
00175 {
00176
00177 return new RooIntegrator1D(function,config) ;
00178 }
00179
00180
00181
00182
00183 Bool_t RooIntegrator1D::initialize()
00184 {
00185
00186
00187
00188 if(_maxSteps <= 0) {
00189 _maxSteps= (_rule == Trapezoid) ? 20 : 14;
00190 }
00191
00192 if(_epsRel <= 0) _epsRel= 1e-6;
00193 if(_epsAbs <= 0) _epsAbs= 1e-6;
00194
00195
00196 if(!isValid()) {
00197 oocoutE((TObject*)0,Integration) << "RooIntegrator1D::initialize: cannot integrate invalid function" << endl;
00198 return kFALSE;
00199 }
00200
00201
00202 _x = new Double_t[_function->getDimension()] ;
00203
00204
00205
00206 _h= new Double_t[_maxSteps + 2];
00207 _s= new Double_t[_maxSteps + 2];
00208 _c= new Double_t[_nPoints + 1];
00209 _d= new Double_t[_nPoints + 1];
00210
00211 return checkLimits();
00212 }
00213
00214
00215
00216 RooIntegrator1D::~RooIntegrator1D()
00217 {
00218
00219
00220
00221 if(_h) delete[] _h;
00222 if(_s) delete[] _s;
00223 if(_c) delete[] _c;
00224 if(_d) delete[] _d;
00225 if(_x) delete[] _x;
00226 }
00227
00228
00229
00230 Bool_t RooIntegrator1D::setLimits(Double_t *xmin, Double_t *xmax)
00231 {
00232
00233
00234
00235
00236 if(_useIntegrandLimits) {
00237 oocoutE((TObject*)0,Integration) << "RooIntegrator1D::setLimits: cannot override integrand's limits" << endl;
00238 return kFALSE;
00239 }
00240 _xmin= *xmin;
00241 _xmax= *xmax;
00242 return checkLimits();
00243 }
00244
00245
00246
00247 Bool_t RooIntegrator1D::checkLimits() const
00248 {
00249
00250
00251
00252 if(_useIntegrandLimits) {
00253 assert(0 != integrand() && integrand()->isValid());
00254 _xmin= integrand()->getMinLimit(0);
00255 _xmax= integrand()->getMaxLimit(0);
00256 }
00257 _range= _xmax - _xmin;
00258 if(_range < 0) {
00259 oocoutE((TObject*)0,Integration) << "RooIntegrator1D::checkLimits: bad range with min >= max (_xmin = " << _xmin << " _xmax = " << _xmax << ")" << endl;
00260 return kFALSE;
00261 }
00262 return (RooNumber::isInfinite(_xmin) || RooNumber::isInfinite(_xmax)) ? kFALSE : kTRUE;
00263 }
00264
00265
00266
00267 Double_t RooIntegrator1D::integral(const Double_t *yvec)
00268 {
00269
00270
00271 assert(isValid());
00272
00273
00274 if (yvec) {
00275 UInt_t i ; for (i=0 ; i<_function->getDimension()-1 ; i++) {
00276 _x[i+1] = yvec[i] ;
00277 }
00278 }
00279
00280 Int_t j;
00281 _h[1]=1.0;
00282 Double_t zeroThresh = _epsAbs/_range ;
00283 for(j= 1; j<=_maxSteps; j++) {
00284
00285 _s[j]= (_rule == Trapezoid) ? addTrapezoids(j) : addMidpoints(j);
00286
00287 if (j >= _minStepsZero) {
00288 Bool_t allZero(kTRUE) ;
00289 Int_t jj ; for (jj=0 ; jj<=j ; jj++) {
00290 if (_s[j]>=zeroThresh) {
00291 allZero=kFALSE ;
00292 }
00293 }
00294 if (allZero) {
00295
00296 return 0;
00297 }
00298 }
00299
00300 if (_fixSteps>0) {
00301
00302
00303 if (j==_fixSteps) {
00304
00305 return _s[j];
00306 }
00307
00308 } else if(j >= _nPoints) {
00309
00310
00311 if (_doExtrap) {
00312 extrapolate(j);
00313 } else {
00314 _extrapValue = _s[j] ;
00315 _extrapError = _s[j]-_s[j-1] ;
00316 }
00317
00318 if(fabs(_extrapError) <= _epsRel*fabs(_extrapValue)) {
00319 return _extrapValue;
00320 }
00321 if(fabs(_extrapError) <= _epsAbs) {
00322 return _extrapValue ;
00323 }
00324
00325 }
00326
00327 _h[j+1]= (_rule == Trapezoid) ? _h[j]/4. : _h[j]/9.;
00328 }
00329
00330 oocoutW((TObject*)0,Integration) << "RooIntegrator1D::integral: integral of " << _function->getName() << " over range (" << _xmin << "," << _xmax << ") did not converge after "
00331 << _maxSteps << " steps" << endl;
00332 for(j= 1; j <= _maxSteps; j++) {
00333 ooccoutW((TObject*)0,Integration) << " [" << j << "] h = " << _h[j] << " , s = " << _s[j] << endl;
00334 }
00335 return _s[_maxSteps] ;
00336 }
00337
00338
00339
00340 Double_t RooIntegrator1D::addMidpoints(Int_t n)
00341 {
00342
00343
00344
00345
00346
00347
00348 Double_t x,tnm,sum,del,ddel;
00349 Int_t it,j;
00350
00351 if(n == 1) {
00352 Double_t xmid= 0.5*(_xmin + _xmax);
00353 return (_savedResult= _range*integrand(xvec(xmid)));
00354 }
00355 else {
00356 for(it=1, j=1; j < n-1; j++) it*= 3;
00357 tnm= it;
00358 del= _range/(3.*tnm);
00359 ddel= del+del;
00360 x= _xmin + 0.5*del;
00361 for(sum= 0, j= 1; j <= it; j++) {
00362 sum+= integrand(xvec(x));
00363 x+= ddel;
00364 sum+= integrand(xvec(x));
00365 x+= del;
00366 }
00367 return (_savedResult= (_savedResult + _range*sum/tnm)/3.);
00368 }
00369 }
00370
00371
00372
00373 Double_t RooIntegrator1D::addTrapezoids(Int_t n)
00374 {
00375
00376
00377
00378
00379
00380 Double_t x,tnm,sum,del;
00381 Int_t it,j;
00382
00383 if (n == 1) {
00384
00385 return (_savedResult= 0.5*_range*(integrand(xvec(_xmin)) + integrand(xvec(_xmax))));
00386 }
00387 else {
00388
00389
00390 for(it=1, j=1; j < n-1; j++) it <<= 1;
00391 tnm= it;
00392 del= _range/tnm;
00393 x= _xmin + 0.5*del;
00394 for(sum=0.0, j=1; j<=it; j++, x+=del) sum += integrand(xvec(x));
00395 return (_savedResult= 0.5*(_savedResult + _range*sum/tnm));
00396 }
00397 }
00398
00399
00400
00401
00402 void RooIntegrator1D::extrapolate(Int_t n)
00403 {
00404
00405
00406 Double_t *xa= &_h[n-_nPoints];
00407 Double_t *ya= &_s[n-_nPoints];
00408 Int_t i,m,ns=1;
00409 Double_t den,dif,dift,ho,hp,w;
00410
00411 dif=fabs(xa[1]);
00412 for (i= 1; i <= _nPoints; i++) {
00413 if ((dift=fabs(xa[i])) < dif) {
00414 ns=i;
00415 dif=dift;
00416 }
00417 _c[i]=ya[i];
00418 _d[i]=ya[i];
00419 }
00420 _extrapValue= ya[ns--];
00421 for(m= 1; m < _nPoints; m++) {
00422 for(i= 1; i <= _nPoints-m; i++) {
00423 ho=xa[i];
00424 hp=xa[i+m];
00425 w=_c[i+1]-_d[i];
00426 if((den=ho-hp) == 0.0) {
00427 oocoutE((TObject*)0,Integration) << "RooIntegrator1D::extrapolate: internal error" << endl;
00428 }
00429 den=w/den;
00430 _d[i]=hp*den;
00431 _c[i]=ho*den;
00432 }
00433 _extrapValue += (_extrapError=(2*ns < (_nPoints-m) ? _c[ns+1] : _d[ns--]));
00434 }
00435 }