52constexpr int nPoints = 5;
61double addMidpoints(std::function<
double(
double)>
const &func,
double savedResult,
int n,
double xmin,
double xmax)
67 return range * func(xmid);
71 for (
int j = 1; j <
n - 1; j++) {
75 double del = range / (3. * tnm);
79 for (
int j = 1; j <= it; j++) {
85 return (savedResult + range *
sum / tnm) / 3.;
94double addTrapezoids(std::function<
double(
double)>
const &func,
double savedResult,
int n,
double xmin,
double xmax)
100 return 0.5 * range * (func(
xmin) + func(
xmax));
105 const int nInt = 1 << (
n - 2);
106 const double del = range / nInt;
110 for (
int j = 0; j < nInt; ++j) {
115 return 0.5 * (savedResult + range *
sum / nInt);
121std::pair<double, double> extrapolate(
int n,
double const *
h,
double const *s,
double *
c,
double *
d)
123 double const *xa = &
h[
n - nPoints];
124 double const *ya = &s[
n - nPoints];
127 double dif = std::abs(xa[1]);
128 for (
int i = 1; i <= nPoints; i++) {
129 double dift = std::abs(xa[i]);
137 double extrapError = 0.0;
138 double extrapValue = ya[ns--];
139 for (
int m = 1;
m < nPoints;
m++) {
140 for (
int i = 1; i <= nPoints -
m; i++) {
142 double hp = xa[i +
m];
143 double w =
c[i + 1] -
d[i];
144 double den = ho - hp;
146 throw std::runtime_error(
"RooRombergIntegrator::extrapolate: internal error");
152 extrapError = 2 * ns < (nPoints -
m) ?
c[ns + 1] :
d[ns--];
153 extrapValue += extrapError;
155 return {extrapValue, extrapError};
163std::pair<double, int> integrate1d(std::function<
double(
double)> func,
bool doTrapezoid,
int maxSteps,
int minStepsZero,
164 int fixSteps,
double epsAbs,
double epsRel,
bool doExtrap,
double xmin,
double xmax,
165 std::span<double> hArr, std::span<double> sArr)
167 assert(
int(hArr.size()) == maxSteps + 2);
168 assert(
int(sArr.size()) == maxSteps + 2);
173 std::array<double, nPoints + 1> cArr = {};
174 std::array<double, nPoints + 1> dArr = {};
177 double zeroThresh = epsAbs / range;
178 for (
int j = 1; j <= maxSteps; ++j) {
181 doTrapezoid ? addTrapezoids(func, sArr[j - 1], j,
xmin,
xmax) : addMidpoints(func, sArr[j - 1], j,
xmin,
xmax);
183 if (j >= minStepsZero) {
185 for (
int jj = 0; jj <= j; jj++) {
186 if (sArr[j] >= zeroThresh) {
205 }
else if (j >= nPoints) {
207 double extrapValue = 0.0;
208 double extrapError = 0.0;
212 std::tie(extrapValue, extrapError) = extrapolate(j, hArr.data(), sArr.data(), cArr.data(), dArr.data());
214 extrapValue = sArr[j];
215 extrapError = sArr[j] - sArr[j - 1];
218 if (std::abs(extrapError) <= epsRel * std::abs(extrapValue)) {
219 return {extrapValue, j};
221 if (std::abs(extrapError) <= epsAbs) {
222 return {extrapValue, j};
226 hArr[j + 1] = doTrapezoid ? hArr[j] / 4. : hArr[j] / 9.;
229 return {sArr[maxSteps], maxSteps};
244 sumRule.defineType(
"Trapezoid", RooRombergIntegrator::Trapezoid);
245 sumRule.defineType(
"Midpoint", RooRombergIntegrator::Midpoint);
246 sumRule.setLabel(
"Trapezoid");
247 RooCategory extrap(
"extrapolation",
"Extrapolation procedure");
248 extrap.defineType(
"None", 0);
249 extrap.defineType(
"Wynn-Epsilon", 1);
250 extrap.setLabel(
"Wynn-Epsilon");
251 RooRealVar maxSteps(
"maxSteps",
"Maximum number of steps", 20);
252 RooRealVar minSteps(
"minSteps",
"Minimum number of steps", 999);
253 RooRealVar fixSteps(
"fixSteps",
"Fixed number of steps", 0);
254 RooRealVar numSeg(
"numSeg",
"Number of segments", 3);
256 std::string
name =
"RooIntegrator1D";
259 return std::make_unique<RooRombergIntegrator>(function, config, 1,
false);
271 return std::make_unique<RooRombergIntegrator>(function, config, 2,
false);
273 std::string name2d =
"RooIntegrator2D";
283 return std::make_unique<RooRombergIntegrator>(function, config, 1,
true);
286 fact.
registerPlugin(
"RooSegmentedIntegrator1D", creatorSeg, {numSeg},
294 return std::make_unique<RooRombergIntegrator>(function, config, 2,
true);
302 "RooSegmentedIntegrator1D");
310RooRombergIntegrator::RooRombergIntegrator(
const RooAbsFunc &function, SummationRule rule,
int maxSteps,
double eps)
311 :
RooAbsIntegrator(function), _useIntegrandLimits(
true), _rule(rule), _maxSteps(maxSteps), _epsAbs(eps), _epsRel(eps)
322RooRombergIntegrator::RooRombergIntegrator(
const RooAbsFunc &function,
double xmin,
double xmax, SummationRule rule,
323 int maxSteps,
double eps)
325 _useIntegrandLimits(false),
331 _xmin.push_back(
xmin);
332 _xmax.push_back(
xmax);
345 _epsAbs(config.epsAbs()),
346 _epsRel(config.epsRel())
350 _rule = (SummationRule)configSet.
getCatIndex(
"sumRule", Trapezoid);
355 if (doSegmentation) {
357 _epsAbs /= std::sqrt(_nSeg);
358 _epsRel /= std::sqrt(_nSeg);
361 if (_fixSteps > _maxSteps) {
362 oocoutE(
nullptr, Integration) <<
"RooRombergIntegrator::ctor() ERROR: fixSteps>maxSteps, fixSteps set to maxSteps"
364 _fixSteps = _maxSteps;
367 _useIntegrandLimits =
true;
375RooRombergIntegrator::RooRombergIntegrator(
const RooAbsFunc &function,
double xmin,
double xmax,
378 _useIntegrandLimits(false),
380 _epsAbs(config.epsAbs()),
381 _epsRel(config.epsRel())
385 _rule = (SummationRule)configSet.
getCatIndex(
"sumRule", Trapezoid);
391 _xmin.push_back(
xmin);
392 _xmax.push_back(
xmax);
399bool RooRombergIntegrator::initialize()
402 if (_maxSteps <= 0) {
403 _maxSteps = (_rule == Trapezoid) ? 20 : 14;
413 oocoutE(
nullptr, Integration) <<
"RooRombergIntegrator::initialize: cannot integrate invalid function"
419 _x.resize(_function->getDimension());
422 _wksp.resize(_nDim * 2 * _maxSteps + 4);
424 return checkLimits();
432bool RooRombergIntegrator::setLimits(
double *
xmin,
double *
xmax)
434 if (_useIntegrandLimits) {
435 oocoutE(
nullptr, Integration) <<
"RooRombergIntegrator::setLimits: cannot override integrand's limits"
441 for (
int iDim = 0; iDim < _nDim; ++iDim) {
442 _xmin[iDim] =
xmin[iDim];
443 _xmax[iDim] =
xmax[iDim];
445 return checkLimits();
452bool RooRombergIntegrator::checkLimits()
const
454 if (_useIntegrandLimits) {
455 assert(
nullptr != integrand() && integrand()->isValid());
456 const_cast<std::vector<double> &
>(_xmin).resize(_nDim);
457 const_cast<std::vector<double> &
>(_xmax).resize(_nDim);
458 for (
int iDim = 0; iDim < _nDim; ++iDim) {
459 const_cast<double &
>(_xmin[iDim]) = integrand()->getMinLimit(iDim);
460 const_cast<double &
>(_xmax[iDim]) = integrand()->getMaxLimit(iDim);
463 for (
int iDim = 0; iDim < _nDim; ++iDim) {
464 const double xmin = _xmin[iDim];
465 const double xmax = _xmax[iDim];
468 oocoutE(
nullptr, Integration) <<
"RooRombergIntegrator::checkLimits: bad range with min > max (_xmin[" << iDim
469 <<
"] = " <<
xmin <<
" _xmax[" << iDim <<
"] = " <<
xmax <<
")" << std::endl;
479double RooRombergIntegrator::integral(
const double *yvec)
483 for (
unsigned int i = 0; i < _function->getDimension() - 1; i++) {
484 _x[i + _nDim] = yvec[i];
488 return integral(_nDim - 1, _nSeg, _wksp);
494double RooRombergIntegrator::integral(
int iDim,
int nSeg, std::span<double> wksp)
498 const double xmin = _xmin[iDim];
499 const double xmax = _xmax[iDim];
507 const double segSize = (
xmax -
xmin) / nSeg;
509 for (
int iSeg = 0; iSeg < nSeg; iSeg++) {
510 _xmin[iDim] =
xmin + iSeg * segSize;
511 _xmax[iDim] =
xmin + (iSeg + 1) * segSize;
512 double part = integral(iDim, 1, wksp);
524 std::size_t nWorkingArr = _maxSteps + 2;
525 double *hArr = wksp.data();
526 double *sArr = wksp.data() + nWorkingArr;
531 std::span<double> nextWksp{wksp.data() + 2 * _maxSteps + 4, wksp.data() + wksp.size()};
533 auto func = [&](
double x) {
536 return iDim == 0 ? integrand(_x.data()) : integral(iDim - 1, _nSeg, nextWksp);
539 std::tie(output, steps) =
540 RooFit::Detail::integrate1d(func, _rule == Trapezoid, _maxSteps, _minStepsZero, _fixSteps, _epsAbs, _epsRel,
541 _doExtrap,
xmin,
xmax, {hArr, nWorkingArr}, {sArr, nWorkingArr});
543 if (steps == _maxSteps) {
545 oocoutW(
nullptr, Integration) <<
"RooRombergIntegrator::integral: integral of " << _function->getName()
546 <<
" over range (" <<
xmin <<
"," <<
xmax <<
") did not converge after "
547 << _maxSteps <<
" steps" << std::endl;
548 for (
int j = 1; j <= _maxSteps; ++j) {
549 ooccoutW(
nullptr, Integration) <<
" [" << j <<
"] h = " << hArr[j] <<
" , s = " << sArr[j] << std::endl;
true
Register systematic variations for multiple existing columns using auto-generated tags.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void w
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...
static uint64_t sum(uint64_t i)