43 class RooProduct::ProdMap :
public std::vector<std::pair<RooArgSet*,RooArgList*> > {} ;
47 typedef RooProduct::ProdMap::iterator RPPMIter ;
48 std::pair<RPPMIter,RPPMIter> findOverlap2nd(RPPMIter i, RPPMIter end) ;
49 void dump_map(ostream& os, RPPMIter i, RPPMIter end) ;
57 RooProduct::RooProduct()
67 RooProduct::~RooProduct()
77 RooProduct::RooProduct(
const char* name,
const char* title,
const RooArgList& prodSet) :
78 RooAbsReal(name, title),
79 _compRSet(
"!compRSet",
"Set of real product components",this),
80 _compCSet(
"!compCSet",
"Set of category product components",this),
83 for (
auto comp : prodSet) {
84 if (dynamic_cast<RooAbsReal*>(comp)) {
85 _compRSet.add(*comp) ;
86 }
else if (dynamic_cast<RooAbsCategory*>(comp)) {
87 _compCSet.add(*comp) ;
89 coutE(InputArguments) <<
"RooProduct::ctor(" << GetName() <<
") ERROR: component " << comp->GetName()
90 <<
" is not of type RooAbsReal or RooAbsCategory" << endl ;
91 RooErrorHandler::softAbort() ;
102 RooProduct::RooProduct(
const RooProduct& other,
const char* name) :
103 RooAbsReal(other, name),
104 _compRSet(
"!compRSet",this,other._compRSet),
105 _compCSet(
"!compCSet",this,other._compCSet),
106 _cacheMgr(other._cacheMgr,this)
117 Bool_t RooProduct::forceAnalyticalInt(
const RooAbsArg& dep)
const
122 RooFIter compRIter = _compRSet.fwdIterator() ;
124 Bool_t depends(kFALSE);
125 while((rcomp=(RooAbsReal*)compRIter.next())&&!depends) {
126 depends = rcomp->dependsOn(dep);
137 RooProduct::ProdMap* RooProduct::groupProductTerms(
const RooArgSet& allVars)
const
139 ProdMap* map =
new ProdMap ;
144 RooFIter compRIter = _compRSet.fwdIterator() ;
145 RooArgList *indep =
new RooArgList();
146 while((rcomp=(RooAbsReal*) compRIter.next())) {
147 if( !rcomp->dependsOn(allVars) ) indep->add(*rcomp);
149 if (indep->getSize()!=0) {
150 map->push_back( std::make_pair(
new RooArgSet(),indep) );
154 RooFIter allVarsIter = allVars.fwdIterator() ;
156 while((var=(RooAbsReal*)allVarsIter.next())) {
157 RooArgSet *vars =
new RooArgSet(); vars->add(*var);
158 RooArgList *comps =
new RooArgList();
161 compRIter = _compRSet.fwdIterator() ;
162 while((rcomp2=(RooAbsReal*) compRIter.next())) {
163 if( rcomp2->dependsOn(*var) ) comps->add(*rcomp2);
165 map->push_back( std::make_pair(vars,comps) );
171 std::pair<ProdMap::iterator,ProdMap::iterator> i = findOverlap2nd(map->begin(),map->end());
172 overlap = (i.first!=i.second);
174 i.first->first->add(*i.second->first);
177 RooFIter it = i.second->second->fwdIterator() ;
179 while ((targ = it.next())) {
180 if (!i.first->second->find(*targ)) {
181 i.first->second->add(*targ) ;
186 delete i.second->first;
187 delete i.second->second;
188 map->erase(i.second);
194 int nVar=0;
int nFunc=0;
195 for (ProdMap::iterator i = map->begin();i!=map->end();++i) {
196 nVar+=i->first->getSize();
197 nFunc+=i->second->getSize();
199 assert(nVar==allVars.getSize());
200 assert(nFunc==_compRSet.getSize());
211 Int_t RooProduct::getPartIntList(
const RooArgSet* iset,
const char *isetRange)
const
215 Int_t sterileIndex(-1);
216 CacheElem* cache = (CacheElem*) _cacheMgr.getObj(iset,iset,&sterileIndex,RooNameReg::ptr(isetRange));
218 Int_t code = _cacheMgr.lastIndex();
222 ProdMap* map = groupProductTerms(*iset);
224 cxcoutD(Integration) <<
"RooProduct::getPartIntList(" << GetName() <<
") groupProductTerms returned map" ;
225 if (dologD(Integration)) {
226 dump_map(ccoutD(Integration),map->begin(),map->end());
227 ccoutD(Integration) << endl;
233 for (ProdMap::iterator iter = map->begin() ; iter != map->end() ; ++iter) {
235 delete iter->second ;
241 cache =
new CacheElem();
243 for (ProdMap::const_iterator i = map->begin();i!=map->end();++i) {
245 if (i->second->getSize()>1) {
246 const char *name = makeFPName(
"SUBPROD_",*i->second);
247 term =
new RooProduct(name,name,*i->second);
248 cache->_ownedList.addOwned(*term);
249 cxcoutD(Integration) <<
"RooProduct::getPartIntList(" << GetName() <<
") created subexpression " << term->GetName() << endl;
251 assert(i->second->getSize()==1);
252 RooFIter j = i->second->fwdIterator();
253 term = (RooAbsReal*)j.next();
256 if (i->first->getSize()==0) {
257 cache->_prodList.add(*term);
258 cxcoutD(Integration) <<
"RooProduct::getPartIntList(" << GetName() <<
") adding simple factor " << term->GetName() << endl;
260 RooAbsReal *integral = term->createIntegral(*i->first,isetRange);
261 cache->_prodList.add(*integral);
262 cache->_ownedList.addOwned(*integral);
263 cxcoutD(Integration) <<
"RooProduct::getPartIntList(" << GetName() <<
") adding integral for " << term->GetName() <<
" : " << integral->GetName() << endl;
267 Int_t code = _cacheMgr.setObj(iset,iset,(RooAbsCacheElement*)cache,RooNameReg::ptr(isetRange));
269 cxcoutD(Integration) <<
"RooProduct::getPartIntList(" << GetName() <<
") created list " << cache->_prodList <<
" with code " << code+1 << endl
270 <<
" for iset=" << *iset <<
" @" << iset <<
" range: " << (isetRange?isetRange:
"<none>") << endl ;
272 for (ProdMap::iterator iter = map->begin() ; iter != map->end() ; ++iter) {
274 delete iter->second ;
284 Int_t RooProduct::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars,
286 const char* rangeName)
const
288 if (_forceNumInt)
return 0 ;
293 assert(analVars.getSize()==0);
294 analVars.add(allVars) ;
295 Int_t code = getPartIntList(&analVars,rangeName)+1;
303 Double_t RooProduct::analyticalIntegral(Int_t code,
const char* rangeName)
const
306 CacheElem *cache = (CacheElem*) _cacheMgr.getObjByIndex(code-1);
309 std::unique_ptr<RooArgSet> vars( getParameters(RooArgSet()) );
310 std::unique_ptr<RooArgSet> iset( _cacheMgr.nameSet2ByIndex(code-1)->select(*vars) );
311 Int_t code2 = getPartIntList(iset.get(),rangeName)+1;
313 return analyticalIntegral(code2,rangeName);
317 return calculate(cache->_prodList);
324 Double_t RooProduct::calculate(
const RooArgList& partIntList)
const
328 RooFIter i = partIntList.fwdIterator() ;
329 while((term=(RooAbsReal*)i.next())) {
330 double x = term->getVal();
340 const char* RooProduct::makeFPName(
const char *pfx,
const RooArgSet& terms)
const
342 static TString pname;
344 RooFIter i = terms.fwdIterator();
347 while((arg=(RooAbsArg*)i.next())) {
348 if (first) { first=kFALSE;}
349 else pname.Append(
"_X_");
350 pname.Append(arg->GetName());
360 Double_t RooProduct::evaluate()
const
364 const RooArgSet* nset = _compRSet.nset() ;
365 for (
const auto item : _compRSet) {
366 auto rcomp =
static_cast<const RooAbsReal*
>(item);
368 prod *= rcomp->getVal(nset) ;
371 for (
const auto item : _compCSet) {
372 auto ccomp =
static_cast<const RooAbsCategory*
>(item);
374 prod *= ccomp->getIndex() ;
385 std::list<Double_t>* RooProduct::binBoundaries(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi)
const
387 for (
const auto item : _compRSet) {
388 auto func =
static_cast<const RooAbsReal*
>(item);
390 list<Double_t>* binb = func->binBoundaries(obs,xlo,xhi) ;
401 Bool_t RooProduct::isBinnedDistribution(
const RooArgSet& obs)
const
405 for (
const auto item : _compRSet) {
406 auto func =
static_cast<const RooAbsReal*
>(item);
408 if (func->dependsOn(obs) && !func->isBinnedDistribution(obs)) {
421 std::list<Double_t>* RooProduct::plotSamplingHint(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi)
const
423 for (
const auto item : _compRSet) {
424 auto func =
static_cast<const RooAbsReal*
>(item);
426 list<Double_t>* hint = func->plotSamplingHint(obs,xlo,xhi) ;
440 RooProduct::CacheElem::~CacheElem()
448 RooArgList RooProduct::CacheElem::containedArgs(Action)
450 RooArgList ret(_ownedList) ;
460 void RooProduct::setCacheAndTrackHints(RooArgSet& trackNodes)
462 RooArgSet comp(components()) ;
463 for (
const auto parg : comp) {
464 if (parg->isDerived()) {
465 if (parg->canNodeBeCached()==Always) {
466 trackNodes.add(*parg) ;
481 void RooProduct::printMetaArgs(ostream& os)
const
483 Bool_t first(kTRUE) ;
485 for (
const auto rcomp : _compRSet) {
486 if (!first) { os <<
" * " ; }
else { first = kFALSE ; }
487 os << rcomp->GetName() ;
490 for (
const auto item : _compCSet) {
491 auto ccomp =
static_cast<const RooAbsCategory*
>(item);
493 if (!first) { os <<
" * " ; }
else { first = kFALSE ; }
494 os << ccomp->GetName() ;
506 std::pair<RPPMIter,RPPMIter> findOverlap2nd(RPPMIter i, RPPMIter end)
509 for (; i!=end; ++i)
for ( RPPMIter j(i+1); j!=end; ++j) {
510 if (i->second->overlaps(*j->second)) {
511 return std::make_pair(i,j);
514 return std::make_pair(end,end);
518 void dump_map(ostream& os, RPPMIter i, RPPMIter end)
524 if (first) { first=kFALSE; }
525 else { os <<
" , " ; }
526 os << *(i->first) <<
" -> " << *(i->second) ;