Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooImproperIntegrator1D.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16
17/**
18\file RooImproperIntegrator1D.cxx
19\class RooImproperIntegrator1D
20\ingroup Roofitcore
21
22Special numeric integrator that can handle integrals over open domains.
23To this end the range is cut in up three pieces: [-inf,-1],[-1,+1] and [+1,inf]
24and the outer two pieces, if required are calculated using a 1/x transform
25**/
26
29#include "RooInvTransform.h"
30#include "RooNumber.h"
31#include "RooNumIntFactory.h"
32#include "RooArgSet.h"
33#include "RooMsgService.h"
34
35#include "Riostream.h"
36#include <cmath>
37#include "TClass.h"
38
39
41
42// Register this class with RooNumIntConfig
43
44////////////////////////////////////////////////////////////////////////////////
45/// Register RooImproperIntegrator1D, its parameters and capabilities with RooNumIntFactory
46
48{
49 auto creator = [](const RooAbsFunc &function, const RooNumIntConfig &config) {
50 return std::make_unique<RooImproperIntegrator1D>(function, config);
51 };
52
53 fact.registerPlugin("RooImproperIntegrator1D", creator, {},
54 /*canIntegrate1D=*/true,
55 /*canIntegrate2D=*/false,
56 /*canIntegrateND=*/false,
57 /*canIntegrateOpenEnded=*/true,
58 /*depName=*/"RooIntegrator1D");
59}
60
61
62////////////////////////////////////////////////////////////////////////////////
63/// Constructor with function binding. The integration range is taken from the
64/// definition in the function binding
65
67 RooAbsIntegrator(function),
68 _useIntegrandLimits(true),
69 _origFunc((RooAbsFunc*)&function)
70{
71 initialize(&function) ;
72}
73
74
75
76////////////////////////////////////////////////////////////////////////////////
77/// Constructor with function binding and configuration object. The integration range is taken
78/// from the definition in the function binding
79
81 RooAbsIntegrator(function),
82 _useIntegrandLimits(true),
83 _origFunc((RooAbsFunc*)&function),
84 _config(config)
85{
86 initialize(&function) ;
87}
88
89
90
91////////////////////////////////////////////////////////////////////////////////
92/// Constructor with function binding, definition of integration range and configuration object
93
95 RooAbsIntegrator(function),
96 _xmin(xmin),
97 _xmax(xmax),
98 _useIntegrandLimits(false),
99 _origFunc((RooAbsFunc*)&function),
100 _config(config)
101{
102 initialize(&function) ;
103}
104
105
106
107////////////////////////////////////////////////////////////////////////////////
108/// Initialize the integrator, construct and initialize subintegrators
109
111{
112 if(!isValid()) {
113 oocoutE(nullptr,Integration) << "RooImproperIntegrator: cannot integrate invalid function" << std::endl;
114 return;
115 }
116 // Create a new function object that uses the change of vars: x -> 1/x
117 if (function) {
118 _function= std::make_unique<RooInvTransform>(*function);
119 } else {
120 function = _origFunc ;
121 _integrator1.reset();
122 _integrator2.reset();
123 _integrator3.reset();
124 }
125
126 // Helper function to create a new configuration that is just like the one
127 // associated to this integrator, but with a different summation rule.
128 auto makeIntegrator1D = [&](RooAbsFunc const& func,
129 double xmin, double xmax,
131 RooNumIntConfig newConfig{_config}; // copy default configuration
132 newConfig.getConfigSection("RooIntegrator1D").setCatIndex("sumRule", rule);
133 return std::make_unique<RooRombergIntegrator>(func, xmin, xmax, newConfig);
134 };
135
136 // partition the integration range into subranges that can each be
137 // handled by RooIntegrator1D
138 switch(_case= limitsCase()) {
139 case ClosedBothEnds:
140 // both limits are finite: use the plain trapezoid integrator
141 _integrator1 = std::make_unique<RooRombergIntegrator>(*function,_xmin,_xmax,_config);
142 break;
143 case OpenBothEnds:
144 // both limits are infinite: integrate over (-1,+1) using
145 // the plain trapezoid integrator...
146 _integrator1 = makeIntegrator1D(*function,-1,+1,RooRombergIntegrator::Trapezoid);
147 // ...and integrate the infinite tails using the midpoint integrator
148 _integrator2 = makeIntegrator1D(*_function,-1,0,RooRombergIntegrator::Midpoint);
149 _integrator3 = makeIntegrator1D(*_function,0,+1,RooRombergIntegrator::Midpoint);
150 break;
152 // xmax >= 0 so integrate from (-inf,-1) and (-1,xmax)
153 _integrator1 = makeIntegrator1D(*_function,-1,0,RooRombergIntegrator::Midpoint);
154 _integrator2 = makeIntegrator1D(*function,-1,_xmax,RooRombergIntegrator::Trapezoid);
155 break;
156 case OpenBelow:
157 // xmax < 0 so integrate from (-inf,xmax)
159 break;
161 // xmin <= 0 so integrate from (xmin,+1) and (+1,+inf)
162 _integrator1 = makeIntegrator1D(*_function,0,+1,RooRombergIntegrator::Midpoint);
163 _integrator2 = makeIntegrator1D(*function,_xmin,+1,RooRombergIntegrator::Trapezoid);
164 break;
165 case OpenAbove:
166 // xmin > 0 so integrate from (xmin,+inf)
168 break;
169 case Invalid:
170 default:
171 _valid= false;
172 }
173}
174
175
176////////////////////////////////////////////////////////////////////////////////
177/// Change our integration limits. Return true if the new limits are
178/// ok, or otherwise false. Always returns false and does nothing
179/// if this object was constructed to always use our integrand's limits.
180
182{
184 oocoutE(nullptr,Integration) << "RooImproperIntegrator1D::setLimits: cannot override integrand's limits" << std::endl;
185 return false;
186 }
187
188 _xmin= *xmin;
189 _xmax= *xmax;
190 return checkLimits();
191}
192
193
194////////////////////////////////////////////////////////////////////////////////
195/// Check if the limits are valid. For this integrator all limit configurations
196/// are valid, but if the limits change between two calculate() calls it
197/// may be necessary to reconfigure (e.g. if an open ended range becomes
198/// a closed range
199
201{
202 // Has either limit changed?
204 if(_xmin == integrand()->getMinLimit(0) &&
205 _xmax == integrand()->getMaxLimit(0)) return true;
206 }
207
208 // The limits have changed: can we use the same strategy?
209 if(limitsCase() != _case) {
210 // Reinitialize embedded integrators, will automatically propagate new limits
211 const_cast<RooImproperIntegrator1D*>(this)->initialize() ;
212 return true ;
213 }
214
215 // Reuse our existing integrators by updating their limits
216 switch(_case) {
217 case ClosedBothEnds:
219 break;
220 case OpenBothEnds:
221 // nothing has changed
222 break;
224 _integrator2->setLimits(-1,_xmax);
225 break;
226 case OpenBelow:
227 _integrator1->setLimits(1/_xmax,0);
228 break;
230 _integrator2->setLimits(_xmin,+1);
231 break;
232 case OpenAbove:
233 _integrator1->setLimits(0,1/_xmin);
234 break;
235 case Invalid:
236 default:
237 return false;
238 }
239 return true;
240}
241
242
243////////////////////////////////////////////////////////////////////////////////
244/// Classify the type of limits we have: OpenBothEnds,ClosedBothEnds,OpenBelow or OpenAbove.
245
247{
248 // Analyze the specified limits to determine which case applies.
249 if(nullptr == integrand() || !integrand()->isValid()) return Invalid;
250
254 }
255
256 bool inf1= RooNumber::isInfinite(_xmin);
257 bool inf2= RooNumber::isInfinite(_xmax);
258 if(!inf1 && !inf2) {
259 // both limits are finite
260 return ClosedBothEnds;
261 }
262 else if(inf1 && inf2) {
263 // both limits are infinite
264 return OpenBothEnds;
265 }
266 else if(inf1) { // inf2==false
267 if(_xmax >= 0) {
268 return OpenBelowSpansZero;
269 }
270 else {
271 return OpenBelow;
272 }
273 }
274 else { // inf1==false && inf2==true
275 if(_xmin <= 0) {
276 return OpenAboveSpansZero;
277 }
278 else {
279 return OpenAbove;
280 }
281 }
282 // return Invalid; OSF-CC: Statement unreachable
283}
284
285
286////////////////////////////////////////////////////////////////////////////////
287/// Calculate the integral at the given parameter values of the function binding
288
289double RooImproperIntegrator1D::integral(const double* yvec)
290{
291 double result(0);
292 if(_integrator1) result+= _integrator1->integral(yvec);
293 if(_integrator2) result+= _integrator2->integral(yvec);
294 if(_integrator3) result+= _integrator3->integral(yvec);
295 return result;
296}
#define oocoutE(o, a)
#define ClassImp(name)
Definition Rtypes.h:377
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
float xmin
float xmax
bool setCatIndex(const char *name, Int_t newVal=0, bool verbose=false)
Set index value of a RooAbsCategoryLValue stored in set with given name to newVal.
Abstract interface for evaluating a real-valued function of one real variable and performing numerica...
Definition RooAbsFunc.h:27
virtual double getMaxLimit(UInt_t dimension) const =0
virtual double getMinLimit(UInt_t dimension) const =0
Abstract interface for integrators of real-valued functions that implement the RooAbsFunc interface.
bool isValid() const
Is integrator in valid state.
const RooAbsFunc * integrand() const
Return integrand function binding.
bool _valid
Is integrator in valid state?
Special numeric integrator that can handle integrals over open domains.
std::unique_ptr< RooRombergIntegrator > _integrator1
Piece integrator 1.
std::unique_ptr< RooInvTransform > _function
Binding with inverse of function.
LimitsCase limitsCase() const
Classify the type of limits we have: OpenBothEnds,ClosedBothEnds,OpenBelow or OpenAbove.
double integral(const double *yvec=nullptr) override
Calculate the integral at the given parameter values of the function binding.
RooImproperIntegrator1D(const RooAbsFunc &function)
Constructor with function binding.
LimitsCase _case
Configuration of limits.
double _xmax
Value of limits.
bool checkLimits() const override
Check if the limits are valid.
RooAbsFunc * _origFunc
Original function binding.
std::unique_ptr< RooRombergIntegrator > _integrator3
Piece integrator 3.
void initialize(const RooAbsFunc *function=nullptr)
Initialize the integrator, construct and initialize subintegrators.
bool setLimits(double *xmin, double *xmax) override
Change our integration limits.
std::unique_ptr< RooRombergIntegrator > _integrator2
Piece integrator 2.
RooNumIntConfig _config
Configuration object.
static void registerIntegrator(RooNumIntFactory &fact)
Register RooImproperIntegrator1D, its parameters and capabilities with RooNumIntFactory.
bool _useIntegrandLimits
Use limits in function binding?
RooNumIntConfig holds the configuration parameters of the various numeric integrators used by RooReal...
const RooArgSet & getConfigSection(const char *name) const
Retrieve configuration information specific to integrator with given name.
RooNumIntFactory is a factory to instantiate numeric integrators from a given function binding and a ...
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.
Definition RooNumber.h:27