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 <ostream>
38
39// Register this class with RooNumIntConfig
40
41////////////////////////////////////////////////////////////////////////////////
42/// Register RooImproperIntegrator1D, its parameters and capabilities with RooNumIntFactory
43
44void RooImproperIntegrator1D::registerIntegrator(RooNumIntFactory &fact)
45{
46 auto creator = [](const RooAbsFunc &function, const RooNumIntConfig &config) {
47 return std::make_unique<RooImproperIntegrator1D>(function, config);
48 };
49
50 fact.registerPlugin("RooImproperIntegrator1D", creator, {},
51 /*canIntegrate1D=*/true,
52 /*canIntegrate2D=*/false,
53 /*canIntegrateND=*/false,
54 /*canIntegrateOpenEnded=*/true,
55 /*depName=*/"RooIntegrator1D");
56}
57
58
59////////////////////////////////////////////////////////////////////////////////
60/// Constructor with function binding. The integration range is taken from the
61/// definition in the function binding
62
63RooImproperIntegrator1D::RooImproperIntegrator1D(const RooAbsFunc& function) :
64 RooAbsIntegrator(function),
65 _useIntegrandLimits(true),
66 _origFunc(const_cast<RooAbsFunc*>(&function))
67{
68 initialize(&function) ;
69}
70
71
72
73////////////////////////////////////////////////////////////////////////////////
74/// Constructor with function binding and configuration object. The integration range is taken
75/// from the definition in the function binding
76
77RooImproperIntegrator1D::RooImproperIntegrator1D(const RooAbsFunc& function, const RooNumIntConfig& config) :
78 RooAbsIntegrator(function),
79 _useIntegrandLimits(true),
80 _origFunc(const_cast<RooAbsFunc*>(&function)),
81 _config(config)
82{
83 initialize(&function) ;
84}
85
86
87
88////////////////////////////////////////////////////////////////////////////////
89/// Constructor with function binding, definition of integration range and configuration object
90
91RooImproperIntegrator1D::RooImproperIntegrator1D(const RooAbsFunc& function, double xmin, double xmax, const RooNumIntConfig& config) :
92 RooAbsIntegrator(function),
93 _xmin(xmin),
94 _xmax(xmax),
95 _useIntegrandLimits(false),
96 _origFunc(const_cast<RooAbsFunc*>(&function)),
97 _config(config)
98{
99 initialize(&function) ;
100}
101
102
103
104////////////////////////////////////////////////////////////////////////////////
105/// Initialize the integrator, construct and initialize subintegrators
106
107void RooImproperIntegrator1D::initialize(const RooAbsFunc* function)
108{
109 if(!isValid()) {
110 oocoutE(nullptr,Integration) << "RooImproperIntegrator: cannot integrate invalid function" << std::endl;
111 return;
112 }
113 // Create a new function object that uses the change of vars: x -> 1/x
114 if (function) {
115 _function= std::make_unique<RooInvTransform>(*function);
116 } else {
117 function = _origFunc ;
118 _integrator1.reset();
119 _integrator2.reset();
120 _integrator3.reset();
121 }
122
123 // Helper function to create a new configuration that is just like the one
124 // associated to this integrator, but with a different summation rule.
125 auto makeIntegrator1D = [&](RooAbsFunc const& func,
126 double xmin, double xmax,
127 RooRombergIntegrator::SummationRule rule) {
128 RooNumIntConfig newConfig{_config}; // copy default configuration
129 newConfig.getConfigSection("RooIntegrator1D").setCatIndex("sumRule", rule);
130 return std::make_unique<RooRombergIntegrator>(func, xmin, xmax, newConfig);
131 };
132
133 // partition the integration range into subranges that can each be
134 // handled by RooIntegrator1D
135 switch(_case= limitsCase()) {
136 case ClosedBothEnds:
137 // both limits are finite: use the plain trapezoid integrator
138 _integrator1 = std::make_unique<RooRombergIntegrator>(*function,_xmin,_xmax,_config);
139 break;
140 case OpenBothEnds:
141 // both limits are infinite: integrate over (-1,+1) using
142 // the plain trapezoid integrator...
143 _integrator1 = makeIntegrator1D(*function,-1,+1,RooRombergIntegrator::Trapezoid);
144 // ...and integrate the infinite tails using the midpoint integrator
145 _integrator2 = makeIntegrator1D(*_function,-1,0,RooRombergIntegrator::Midpoint);
146 _integrator3 = makeIntegrator1D(*_function,0,+1,RooRombergIntegrator::Midpoint);
147 break;
149 // xmax >= 0 so integrate from (-inf,-1) and (-1,xmax)
150 _integrator1 = makeIntegrator1D(*_function,-1,0,RooRombergIntegrator::Midpoint);
151 _integrator2 = makeIntegrator1D(*function,-1,_xmax,RooRombergIntegrator::Trapezoid);
152 break;
153 case OpenBelow:
154 // xmax < 0 so integrate from (-inf,xmax)
155 _integrator1 = makeIntegrator1D(*_function,1/_xmax,0,RooRombergIntegrator::Midpoint);
156 break;
158 // xmin <= 0 so integrate from (xmin,+1) and (+1,+inf)
159 _integrator1 = makeIntegrator1D(*_function,0,+1,RooRombergIntegrator::Midpoint);
160 _integrator2 = makeIntegrator1D(*function,_xmin,+1,RooRombergIntegrator::Trapezoid);
161 break;
162 case OpenAbove:
163 // xmin > 0 so integrate from (xmin,+inf)
164 _integrator1 = makeIntegrator1D(*_function,0,1/_xmin,RooRombergIntegrator::Midpoint);
165 break;
166 case Invalid:
167 default:
168 _valid= false;
169 }
170}
171
172
173////////////////////////////////////////////////////////////////////////////////
174/// Change our integration limits. Return true if the new limits are
175/// ok, or otherwise false. Always returns false and does nothing
176/// if this object was constructed to always use our integrand's limits.
177
178bool RooImproperIntegrator1D::setLimits(double *xmin, double *xmax)
179{
180 if(_useIntegrandLimits) {
181 oocoutE(nullptr,Integration) << "RooImproperIntegrator1D::setLimits: cannot override integrand's limits" << std::endl;
182 return false;
183 }
184
185 _xmin= *xmin;
186 _xmax= *xmax;
187 return checkLimits();
188}
189
190
191////////////////////////////////////////////////////////////////////////////////
192/// Check if the limits are valid. For this integrator all limit configurations
193/// are valid, but if the limits change between two calculate() calls it
194/// may be necessary to reconfigure (e.g. if an open ended range becomes
195/// a closed range
196
197bool RooImproperIntegrator1D::checkLimits() const
198{
199 // Has either limit changed?
200 if (_useIntegrandLimits) {
201 if(_xmin == integrand()->getMinLimit(0) &&
202 _xmax == integrand()->getMaxLimit(0)) return true;
203 }
204
205 // The limits have changed: can we use the same strategy?
206 if(limitsCase() != _case) {
207 // Reinitialize embedded integrators, will automatically propagate new limits
208 const_cast<RooImproperIntegrator1D*>(this)->initialize() ;
209 return true ;
210 }
211
212 // Reuse our existing integrators by updating their limits
213 switch(_case) {
214 case ClosedBothEnds:
215 _integrator1->setLimits(_xmin,_xmax);
216 break;
217 case OpenBothEnds:
218 // nothing has changed
219 break;
221 _integrator2->setLimits(-1,_xmax);
222 break;
223 case OpenBelow:
224 _integrator1->setLimits(1/_xmax,0);
225 break;
227 _integrator2->setLimits(_xmin,+1);
228 break;
229 case OpenAbove:
230 _integrator1->setLimits(0,1/_xmin);
231 break;
232 case Invalid:
233 default:
234 return false;
235 }
236 return true;
237}
238
239
240////////////////////////////////////////////////////////////////////////////////
241/// Classify the type of limits we have: OpenBothEnds,ClosedBothEnds,OpenBelow or OpenAbove.
242
243RooImproperIntegrator1D::LimitsCase RooImproperIntegrator1D::limitsCase() const
244{
245 // Analyze the specified limits to determine which case applies.
246 if(nullptr == integrand() || !integrand()->isValid()) return Invalid;
247
248 if (_useIntegrandLimits) {
249 _xmin= integrand()->getMinLimit(0);
250 _xmax= integrand()->getMaxLimit(0);
251 }
252
253 bool inf1= RooNumber::isInfinite(_xmin);
254 bool inf2= RooNumber::isInfinite(_xmax);
255 if(!inf1 && !inf2) {
256 // both limits are finite
257 return ClosedBothEnds;
258 }
259 else if(inf1 && inf2) {
260 // both limits are infinite
261 return OpenBothEnds;
262 }
263 else if(inf1) { // inf2==false
264 if(_xmax >= 0) {
265 return OpenBelowSpansZero;
266 }
267 else {
268 return OpenBelow;
269 }
270 }
271 else { // inf1==false && inf2==true
272 if(_xmin <= 0) {
273 return OpenAboveSpansZero;
274 }
275 else {
276 return OpenAbove;
277 }
278 }
279 // return Invalid; OSF-CC: Statement unreachable
280}
281
282
283////////////////////////////////////////////////////////////////////////////////
284/// Calculate the integral at the given parameter values of the function binding
285
286double RooImproperIntegrator1D::integral(const double* yvec)
287{
288 double result(0);
289 if(_integrator1) result+= _integrator1->integral(yvec);
290 if(_integrator2) result+= _integrator2->integral(yvec);
291 if(_integrator3) result+= _integrator3->integral(yvec);
292 return result;
293}
294
295/// \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 initialize(typename Architecture_t::Matrix_t &A, EInitialization m)
Definition Functions.h:282