Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RooNumIntFactory.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 RooNumIntFactory.cxx
19 \class RooNumIntFactory
20 \ingroup Roofitcore
21 
22 RooNumIntFactory is a factory to instantiate numeric integrators
23 from a given function binding and a given configuration. The factory
24 searches for a numeric integrator registered with the factory that
25 has the ability to perform the numeric integration. The choice of
26 method may depend on the number of dimensions integrated,
27 the nature of the integration limits (closed or open ended) and
28 the preference of the caller as encoded in the configuration object.
29 **/
30 
31 #include "TClass.h"
32 #include "TSystem.h"
33 #include "Riostream.h"
34 
35 #include "RooFit.h"
36 
37 #include "RooNumIntFactory.h"
38 #include "RooArgSet.h"
39 #include "RooAbsFunc.h"
40 #include "RooNumIntConfig.h"
41 #include "RooNumber.h"
42 
43 #include "RooIntegrator1D.h"
44 #include "RooBinIntegrator.h"
45 #include "RooIntegrator2D.h"
49 #include "RooMCIntegrator.h"
50 //#include "RooGaussKronrodIntegrator1D.h"
51 //#include "RooAdaptiveGaussKronrodIntegrator1D.h"
53 
54 #include "RooMsgService.h"
55 
56 using namespace std ;
57 
58 ClassImp(RooNumIntFactory)
59 
60 
61 
62 ////////////////////////////////////////////////////////////////////////////////
63 /// Register all known integrators by calling
64 /// their static registration functions
65 void RooNumIntFactory::init() {
66  RooBinIntegrator::registerIntegrator(*this) ;
67  RooIntegrator1D::registerIntegrator(*this) ;
68  RooIntegrator2D::registerIntegrator(*this) ;
69  RooSegmentedIntegrator1D::registerIntegrator(*this) ;
70  RooSegmentedIntegrator2D::registerIntegrator(*this) ;
71  RooImproperIntegrator1D::registerIntegrator(*this) ;
72  RooMCIntegrator::registerIntegrator(*this) ;
73  // GSL integrator is now in RooFitMore and it register itself
74  //RooAdaptiveGaussKronrodIntegrator1D::registerIntegrator(*this) ;
75  //RooGaussKronrodIntegrator1D::registerIntegrator(*this) ;
76  RooAdaptiveIntegratorND::registerIntegrator(*this) ;
77 
78  RooNumIntConfig::defaultConfig().method1D().setLabel("RooIntegrator1D") ;
79  RooNumIntConfig::defaultConfig().method1DOpen().setLabel("RooImproperIntegrator1D") ;
80  RooNumIntConfig::defaultConfig().method2D().setLabel("RooAdaptiveIntegratorND") ;
81  RooNumIntConfig::defaultConfig().methodND().setLabel("RooAdaptiveIntegratorND") ;
82 
83  //if GSL is available load (and register GSL integrator)
84 #ifdef R__HAS_MATHMORE
85  int iret = gSystem->Load("libRooFitMore");
86  if (iret < 0) {
87  oocoutE((TObject*)nullptr, Integration) << " RooNumIntFactory::Init : libRooFitMore cannot be loaded. GSL integrators will not beavailable ! " << std::endl;
88  }
89 #endif
90 }
91 
92 
93 ////////////////////////////////////////////////////////////////////////////////
94 /// Static method returning reference to singleton instance of factory
95 
96 RooNumIntFactory& RooNumIntFactory::instance()
97 {
98  static unique_ptr<RooNumIntFactory> instance;
99 
100  if (!instance) {
101  // This is needed to break a deadlock. During init(),
102  // other functions may call back to this one here. So we need to construct first,
103  // and ensure that we can return an instance while we are waiting for init()
104  // to finish.
105  instance.reset(new RooNumIntFactory);
106  instance->init();
107  }
108 
109  return *instance;
110 }
111 
112 
113 
114 ////////////////////////////////////////////////////////////////////////////////
115 /// Method accepting registration of a prototype numeric integrator along with a RooArgSet of its
116 /// default configuration options and an optional list of names of other numeric integrators
117 /// on which this integrator depends. Returns true if integrator was previously registered
118 
119 Bool_t RooNumIntFactory::storeProtoIntegrator(RooAbsIntegrator* proto, const RooArgSet& defConfig, const char* depName)
120 {
121  TString name = proto->IsA()->GetName() ;
122 
123  if (getProtoIntegrator(name)) {
124  //cout << "RooNumIntFactory::storeIntegrator() ERROR: integrator '" << name << "' already registered" << endl ;
125  return kTRUE ;
126  }
127 
128  // Add to factory
129  _map[name.Data()] = std::make_pair(unique_ptr<RooAbsIntegrator>(proto), std::string(depName));
130 
131  // Add default config to master config
132  RooNumIntConfig::defaultConfig().addConfigSection(proto,defConfig) ;
133 
134  return kFALSE ;
135 }
136 
137 
138 
139 ////////////////////////////////////////////////////////////////////////////////
140 /// Return prototype integrator with given (class) name
141 
142 const RooAbsIntegrator* RooNumIntFactory::getProtoIntegrator(const char* name) const
143 {
144  auto item = _map.find(name);
145 
146  return item == _map.end() ? nullptr : item->second.first.get();
147 }
148 
149 
150 
151 ////////////////////////////////////////////////////////////////////////////////
152 /// Get list of class names of integrators needed by integrator named 'name'
153 
154 const char* RooNumIntFactory::getDepIntegratorName(const char* name) const
155 {
156  auto item = _map.find(name);
157 
158  return item == _map.end() ? nullptr : item->second.second.c_str();
159 }
160 
161 
162 
163 ////////////////////////////////////////////////////////////////////////////////
164 /// Construct a numeric integrator instance that operates on function 'func' and is configured
165 /// with 'config'. If ndimPreset is greater than zero that number is taken as the dimensionality
166 /// of the integration, otherwise it is queried from 'func'. This function iterators over list
167 /// of available prototype integrators and returns an clone attached to the given function of
168 /// the first class that matches the specifications of the requested integration considering
169 /// the number of dimensions, the nature of the limits (open ended vs closed) and the user
170 /// preference stated in 'config'
171 
172 RooAbsIntegrator* RooNumIntFactory::createIntegrator(RooAbsFunc& func, const RooNumIntConfig& config, Int_t ndimPreset, Bool_t isBinned) const
173 {
174  // First determine dimensionality and domain of integrand
175  Int_t ndim = ndimPreset>0 ? ndimPreset : ((Int_t)func.getDimension()) ;
176 
177  Bool_t openEnded = kFALSE ;
178  Int_t i ;
179  for (i=0 ; i<ndim ; i++) {
180  if(RooNumber::isInfinite(func.getMinLimit(i)) ||
181  RooNumber::isInfinite(func.getMaxLimit(i))) {
182  openEnded = kTRUE ;
183  }
184  }
185 
186  // Find method defined configuration
187  TString method ;
188  switch(ndim) {
189  case 1:
190  method = openEnded ? config.method1DOpen().getLabel() : config.method1D().getLabel() ;
191  break ;
192 
193  case 2:
194  method = openEnded ? config.method2DOpen().getLabel() : config.method2D().getLabel() ;
195  break ;
196 
197  default:
198  method = openEnded ? config.methodNDOpen().getLabel() : config.methodND().getLabel() ;
199  break ;
200  }
201 
202  // If distribution is binned and not open-ended override with bin integrator
203  if (isBinned & !openEnded) {
204  method = "RooBinIntegrator" ;
205  }
206 
207  // Check that a method was defined for this case
208  if (!method.CompareTo("N/A")) {
209  oocoutE((TObject*)0,Integration) << "RooNumIntFactory::createIntegrator: No integration method has been defined for "
210  << (openEnded?"an open ended ":"a ") << ndim << "-dimensional integral" << endl ;
211  return 0 ;
212  }
213 
214  // Retrieve proto integrator and return clone configured for the requested integration task
215  const RooAbsIntegrator* proto = getProtoIntegrator(method) ;
216  RooAbsIntegrator* engine = proto->clone(func,config) ;
217  if (config.printEvalCounter()) {
218  engine->setPrintEvalCounter(kTRUE) ;
219  }
220  return engine ;
221 }