50constexpr int nPoints = 5;
59double addMidpoints(std::function<
double(
double)>
const &func,
double savedResult,
int n,
double xmin,
double xmax)
65 return range * func(xmid);
69 for (
int j = 1; j <
n - 1; j++) {
73 double del = range / (3. * tnm);
77 for (
int j = 1; j <= it; j++) {
83 return (savedResult + range *
sum / tnm) / 3.;
92double addTrapezoids(std::function<
double(
double)>
const &func,
double savedResult,
int n,
double xmin,
double xmax)
98 return 0.5 * range * (func(
xmin) + func(
xmax));
103 const int nInt = 1 << (
n - 2);
104 const double del = range / nInt;
108 for (
int j = 0; j < nInt; ++j) {
113 return 0.5 * (savedResult + range *
sum / nInt);
119std::pair<double, double> extrapolate(
int n,
double const *
h,
double const *s,
double *
c,
double *
d)
121 double const *xa = &
h[
n - nPoints];
122 double const *ya = &s[
n - nPoints];
125 double dif = std::abs(xa[1]);
126 for (
int i = 1; i <= nPoints; i++) {
127 double dift = std::abs(xa[i]);
135 double extrapError = 0.0;
136 double extrapValue = ya[ns--];
137 for (
int m = 1;
m < nPoints;
m++) {
138 for (
int i = 1; i <= nPoints -
m; i++) {
140 double hp = xa[i +
m];
141 double w =
c[i + 1] -
d[i];
142 double den = ho - hp;
144 throw std::runtime_error(
"RooRombergIntegrator::extrapolate: internal error");
150 extrapError = 2 * ns < (nPoints -
m) ?
c[ns + 1] :
d[ns--];
151 extrapValue += extrapError;
153 return {extrapValue, extrapError};
161std::pair<double, int> integrate1d(std::function<
double(
double)> func,
bool doTrapezoid,
int maxSteps,
int minStepsZero,
162 int fixSteps,
double epsAbs,
double epsRel,
bool doExtrap,
double xmin,
double xmax,
163 std::span<double> hArr, std::span<double> sArr)
165 assert(
int(hArr.size()) == maxSteps + 2);
166 assert(
int(sArr.size()) == maxSteps + 2);
171 std::array<double, nPoints + 1> cArr = {};
172 std::array<double, nPoints + 1> dArr = {};
175 double zeroThresh = epsAbs / range;
176 for (
int j = 1; j <= maxSteps; ++j) {
179 doTrapezoid ? addTrapezoids(func, sArr[j - 1], j,
xmin,
xmax) : addMidpoints(func, sArr[j - 1], j,
xmin,
xmax);
181 if (j >= minStepsZero) {
183 for (
int jj = 0; jj <= j; jj++) {
184 if (sArr[j] >= zeroThresh) {
203 }
else if (j >= nPoints) {
205 double extrapValue = 0.0;
206 double extrapError = 0.0;
210 std::tie(extrapValue, extrapError) = extrapolate(j, hArr.data(), sArr.data(), cArr.data(), dArr.data());
212 extrapValue = sArr[j];
213 extrapError = sArr[j] - sArr[j - 1];
216 if (std::abs(extrapError) <= epsRel * std::abs(extrapValue)) {
217 return {extrapValue, j};
219 if (std::abs(extrapError) <= epsAbs) {
220 return {extrapValue, j};
224 hArr[j + 1] = doTrapezoid ? hArr[j] / 4. : hArr[j] / 9.;
227 return {sArr[maxSteps], maxSteps};
242 sumRule.defineType(
"Trapezoid", RooRombergIntegrator::Trapezoid);
243 sumRule.defineType(
"Midpoint", RooRombergIntegrator::Midpoint);
244 sumRule.setLabel(
"Trapezoid");
245 RooCategory extrap(
"extrapolation",
"Extrapolation procedure");
246 extrap.defineType(
"None", 0);
247 extrap.defineType(
"Wynn-Epsilon", 1);
248 extrap.setLabel(
"Wynn-Epsilon");
249 RooRealVar maxSteps(
"maxSteps",
"Maximum number of steps", 20);
250 RooRealVar minSteps(
"minSteps",
"Minimum number of steps", 999);
251 RooRealVar fixSteps(
"fixSteps",
"Fixed number of steps", 0);
252 RooRealVar numSeg(
"numSeg",
"Number of segments", 3);
254 std::string
name =
"RooIntegrator1D";
257 return std::make_unique<RooRombergIntegrator>(function, config, 1,
false);
269 return std::make_unique<RooRombergIntegrator>(function, config, 2,
false);
271 std::string name2d =
"RooIntegrator2D";
281 return std::make_unique<RooRombergIntegrator>(function, config, 1,
true);
284 fact.
registerPlugin(
"RooSegmentedIntegrator1D", creatorSeg, {numSeg},
292 return std::make_unique<RooRombergIntegrator>(function, config, 2,
true);
300 "RooSegmentedIntegrator1D");
308RooRombergIntegrator::RooRombergIntegrator(
const RooAbsFunc &function, SummationRule rule,
int maxSteps,
double eps)
309 :
RooAbsIntegrator(function), _useIntegrandLimits(true), _rule(rule), _maxSteps(maxSteps), _epsAbs(eps), _epsRel(eps)
320RooRombergIntegrator::RooRombergIntegrator(
const RooAbsFunc &function,
double xmin,
double xmax, SummationRule rule,
321 int maxSteps,
double eps)
323 _useIntegrandLimits(false),
329 _xmin.push_back(
xmin);
330 _xmax.push_back(
xmax);
343 _epsAbs(config.epsAbs()),
344 _epsRel(config.epsRel())
348 _rule = (SummationRule)configSet.
getCatIndex(
"sumRule", Trapezoid);
353 if (doSegmentation) {
355 _epsAbs /= std::sqrt(_nSeg);
356 _epsRel /= std::sqrt(_nSeg);
359 if (_fixSteps > _maxSteps) {
360 oocoutE(
nullptr, Integration) <<
"RooRombergIntegrator::ctor() ERROR: fixSteps>maxSteps, fixSteps set to maxSteps"
362 _fixSteps = _maxSteps;
365 _useIntegrandLimits =
true;
373RooRombergIntegrator::RooRombergIntegrator(
const RooAbsFunc &function,
double xmin,
double xmax,
376 _useIntegrandLimits(false),
378 _epsAbs(config.epsAbs()),
379 _epsRel(config.epsRel())
383 _rule = (SummationRule)configSet.
getCatIndex(
"sumRule", Trapezoid);
389 _xmin.push_back(
xmin);
390 _xmax.push_back(
xmax);
397bool RooRombergIntegrator::initialize()
400 if (_maxSteps <= 0) {
401 _maxSteps = (_rule == Trapezoid) ? 20 : 14;
411 oocoutE(
nullptr, Integration) <<
"RooRombergIntegrator::initialize: cannot integrate invalid function"
417 _x.resize(_function->getDimension());
420 _wksp.resize(_nDim * 2 * _maxSteps + 4);
422 return checkLimits();
430bool RooRombergIntegrator::setLimits(
double *
xmin,
double *
xmax)
432 if (_useIntegrandLimits) {
433 oocoutE(
nullptr, Integration) <<
"RooRombergIntegrator::setLimits: cannot override integrand's limits"
439 for (
int iDim = 0; iDim < _nDim; ++iDim) {
440 _xmin[iDim] =
xmin[iDim];
441 _xmax[iDim] =
xmax[iDim];
443 return checkLimits();
450bool RooRombergIntegrator::checkLimits()
const
452 if (_useIntegrandLimits) {
453 assert(
nullptr != integrand() && integrand()->isValid());
454 const_cast<std::vector<double> &
>(_xmin).resize(_nDim);
455 const_cast<std::vector<double> &
>(_xmax).resize(_nDim);
456 for (
int iDim = 0; iDim < _nDim; ++iDim) {
457 const_cast<double &
>(_xmin[iDim]) = integrand()->getMinLimit(iDim);
458 const_cast<double &
>(_xmax[iDim]) = integrand()->getMaxLimit(iDim);
461 for (
int iDim = 0; iDim < _nDim; ++iDim) {
462 const double xmin = _xmin[iDim];
463 const double xmax = _xmax[iDim];
466 oocoutE(
nullptr, Integration) <<
"RooRombergIntegrator::checkLimits: bad range with min > max (_xmin[" << iDim
467 <<
"] = " <<
xmin <<
" _xmax[" << iDim <<
"] = " <<
xmax <<
")" << std::endl;
477double RooRombergIntegrator::integral(
const double *yvec)
481 for (
unsigned int i = 0; i < _function->getDimension() - 1; i++) {
482 _x[i + _nDim] = yvec[i];
486 return integral(_nDim - 1, _nSeg, _wksp);
492double RooRombergIntegrator::integral(
int iDim,
int nSeg, std::span<double> wksp)
496 const double xmin = _xmin[iDim];
497 const double xmax = _xmax[iDim];
505 const double segSize = (
xmax -
xmin) / nSeg;
507 for (
int iSeg = 0; iSeg < nSeg; iSeg++) {
508 _xmin[iDim] =
xmin + iSeg * segSize;
509 _xmax[iDim] =
xmin + (iSeg + 1) * segSize;
510 double part = integral(iDim, 1, wksp);
522 std::size_t nWorkingArr = _maxSteps + 2;
523 double *hArr = wksp.data();
524 double *sArr = wksp.data() + nWorkingArr;
529 std::span<double> nextWksp{wksp.data() + 2 * _maxSteps + 4, wksp.data() + wksp.size()};
531 auto func = [&](
double x) {
534 return iDim == 0 ? integrand(_x.data()) : integral(iDim - 1, _nSeg, nextWksp);
537 std::tie(output, steps) =
538 RooFit::Detail::integrate1d(func, _rule == Trapezoid, _maxSteps, _minStepsZero, _fixSteps, _epsAbs, _epsRel,
539 _doExtrap,
xmin,
xmax, {hArr, nWorkingArr}, {sArr, nWorkingArr});
541 if (steps == _maxSteps) {
543 oocoutW(
nullptr, Integration) <<
"RooRombergIntegrator::integral: integral of " << _function->getName()
544 <<
" over range (" <<
xmin <<
"," <<
xmax <<
") did not converge after "
545 << _maxSteps <<
" steps" << std::endl;
546 for (
int j = 1; j <= _maxSteps; ++j) {
547 ooccoutW(
nullptr, Integration) <<
" [" << j <<
"] h = " << hArr[j] <<
" , s = " << sArr[j] << std::endl;
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t del
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
double getRealValue(const char *name, double defVal=0.0, bool verbose=false) const
Get value of a RooAbsReal stored in set with given name.
Int_t getCatIndex(const char *name, Int_t defVal=0, bool verbose=false) const
Get index value of a RooAbsCategory stored in set with given name.
Abstract interface for evaluating a real-valued function of one real variable and performing numerica...
Abstract interface for integrators of real-valued functions that implement the RooAbsFunc interface.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Object to represent discrete states.
bool setLabel(const char *label, bool printError=true) override
Set value by specifying the name of the desired state.
Holds the configuration parameters of the various numeric integrators used by RooRealIntegral.
const RooArgSet & getConfigSection(const char *name) const
Retrieve configuration information specific to integrator with given name.
static RooNumIntConfig & defaultConfig()
Return reference to instance of default numeric integrator configuration object.
Factory to instantiate numeric integrators from a given function binding and a given configuration.
bool registerPlugin(std::string const &name, Creator const &creator, const RooArgSet &defConfig, bool canIntegrate1D, bool canIntegrate2D, bool canIntegrateND, bool canIntegrateOpenEnded, const char *depName="")
Method accepting registration of a prototype numeric integrator along with a RooArgSet of its default...
static constexpr int isInfinite(double x)
Return true if x is infinite by RooNumber internal specification.
Variable that can be changed from the outside.
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
void initialize(typename Architecture_t::Matrix_t &A, EInitialization m)
static uint64_t sum(uint64_t i)