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