// RooRealIntegral performs hybrid numerical/analytical integrals of RooAbsReal objects
// The class performs none of the actual integration, but only manages the logic
// of what variables can be integrated analytically, accounts for eventual jacobian
// terms and defines what numerical integrations needs to be done to complement the
// analytical integral.
// <p>
// The actual analytical integrations (if any) are done in the PDF themselves, the numerical
// integration is performed in the various implemenations of the RooAbsIntegrator base class.
// END_HTML
#include "RooFit.h"
#include "TClass.h"
#include "RooMsgService.h"
#include "Riostream.h"
#include "TObjString.h"
#include "TH1.h"
#include "RooRealIntegral.h"
#include "RooArgSet.h"
#include "RooAbsRealLValue.h"
#include "RooAbsCategoryLValue.h"
#include "RooRealBinding.h"
#include "RooRealAnalytic.h"
#include "RooInvTransform.h"
#include "RooSuperCategory.h"
#include "RooNumIntFactory.h"
#include "RooNumIntConfig.h"
#include "RooNameReg.h"
#include "RooExpensiveObjectCache.h"
#include "RooConstVar.h"
#include "RooDouble.h"
using namespace std;
ClassImp(RooRealIntegral)
;
Int_t RooRealIntegral::_cacheAllNDim(2) ;
RooRealIntegral::RooRealIntegral() :
_valid(kFALSE),
_funcNormSet(0),
_iconfig(0),
_sumCatIter(0),
_mode(0),
_intOperMode(Hybrid),
_restartNumIntEngine(kFALSE),
_numIntEngine(0),
_numIntegrand(0),
_rangeName(0),
_params(0),
_cacheNum(kFALSE)
{
_facListIter = _facList.createIterator() ;
_jacListIter = _jacList.createIterator() ;
}
RooRealIntegral::RooRealIntegral(const char *name, const char *title,
const RooAbsReal& function, const RooArgSet& depList,
const RooArgSet* funcNormSet, const RooNumIntConfig* config,
const char* rangeName) :
RooAbsReal(name,title),
_valid(kTRUE),
_sumList("!sumList","Categories to be summed numerically",this,kFALSE,kFALSE),
_intList("!intList","Variables to be integrated numerically",this,kFALSE,kFALSE),
_anaList("!anaList","Variables to be integrated analytically",this,kFALSE,kFALSE),
_jacList("!jacList","Jacobian product term",this,kFALSE,kFALSE),
_facList("!facList","Variables independent of function",this,kFALSE,kTRUE),
_facListIter(_facList.createIterator()),
_jacListIter(_jacList.createIterator()),
_function("!func","Function to be integrated",this,
const_cast<RooAbsReal&>(function),kFALSE,kFALSE),
_iconfig((RooNumIntConfig*)config),
_sumCat("!sumCat","SuperCategory for summation",this,kFALSE,kFALSE),
_sumCatIter(0),
_mode(0),
_intOperMode(Hybrid),
_restartNumIntEngine(kFALSE),
_numIntEngine(0),
_numIntegrand(0),
_rangeName((TNamed*)RooNameReg::ptr(rangeName)),
_params(0),
_cacheNum(kFALSE)
{
oocxcoutI(&function,Integration) << "RooRealIntegral::ctor(" << GetName() << ") Constructing integral of function "
<< function.GetName() << " over observables" << depList << " with normalization "
<< (funcNormSet?*funcNormSet:RooArgSet()) << " with range identifier "
<< (rangeName?rangeName:"<none>") << endl ;
setExpensiveObjectCache(function.expensiveObjectCache()) ;
if (!_iconfig) _iconfig = (RooNumIntConfig*) function.getIntegratorConfig() ;
if (funcNormSet) {
_funcNormSet = new RooArgSet ;
TIterator* iter = funcNormSet->createIterator() ;
RooAbsArg* nArg ;
while ((nArg=(RooAbsArg*)iter->Next())) {
if (function.dependsOn(*nArg)) {
_funcNormSet->addClone(*nArg) ;
}
}
delete iter ;
} else {
_funcNormSet = 0 ;
}
RooArgSet intDepList(depList) ;
RooAbsArg *arg ;
TIterator* depIter = intDepList.createIterator() ;
while((arg=(RooAbsArg*)depIter->Next())) {
if(!arg->isLValue()) {
coutE(InputArguments) << ClassName() << "::" << GetName() << ": cannot integrate non-lvalue ";
arg->Print("1");
_valid= kFALSE;
}
if (!function.dependsOn(*arg)) {
RooAbsArg* argClone = (RooAbsArg*) arg->Clone() ;
_facListOwned.addOwned(*argClone) ;
_facList.add(*argClone) ;
addServer(*argClone,kFALSE,kTRUE) ;
}
}
if (_facList.getSize()>0) {
oocxcoutI(&function,Integration) << function.GetName() << ": Factorizing obserables are " << _facList << endl ;
}
RooArgSet exclLVBranches("exclLVBranches") ;
RooArgSet branchList,branchListVD ;
function.branchNodeServerList(&branchList) ;
TIterator* bIter = branchList.createIterator() ;
RooAbsArg* branch ;
while((branch=(RooAbsArg*)bIter->Next())) {
RooAbsRealLValue *realArgLV = dynamic_cast<RooAbsRealLValue*>(branch) ;
RooAbsCategoryLValue *catArgLV = dynamic_cast<RooAbsCategoryLValue*>(branch) ;
if ((realArgLV && (realArgLV->isJacobianOK(intDepList)!=0)) || catArgLV) {
exclLVBranches.add(*branch) ;
}
if (dependsOnValue(*branch)) {
branchListVD.add(*branch) ;
} else {
}
}
delete bIter ;
exclLVBranches.remove(depList,kTRUE,kTRUE) ;
RooArgSet exclLVServers("exclLVServers") ;
exclLVServers.add(intDepList) ;
TIterator *sIter = exclLVServers.createIterator() ;
bIter = exclLVBranches.createIterator() ;
RooAbsArg *server ;
Bool_t converged(kFALSE) ;
while(!converged) {
converged=kTRUE ;
sIter->Reset() ;
while ((server=(RooAbsArg*)sIter->Next())) {
if (!servesExclusively(server,exclLVBranches,branchListVD)) {
exclLVServers.remove(*server) ;
converged=kFALSE ;
}
}
bIter->Reset() ;
while((branch=(RooAbsArg*)bIter->Next())) {
RooArgSet* brDepList = branch->getObservables(&intDepList) ;
RooArgSet bsList(*brDepList,"bsList") ;
delete brDepList ;
bsList.remove(exclLVServers,kTRUE,kTRUE) ;
if (bsList.getSize()>0) {
exclLVBranches.remove(*branch,kTRUE,kTRUE) ;
converged=kFALSE ;
}
}
}
bIter->Reset() ;
while((branch=(RooAbsArg*)bIter->Next())) {
if (!branch->dependsOnValue(exclLVServers)) {
exclLVBranches.remove(*branch,kTRUE,kTRUE) ;
}
}
delete sIter ;
delete bIter ;
if (exclLVServers.getSize()>0) {
intDepList.remove(exclLVServers) ;
intDepList.add(exclLVBranches) ;
}
RooArgSet anIntOKDepList ;
depIter->Reset() ;
while((arg=(RooAbsArg*)depIter->Next())) {
if (function.forceAnalyticalInt(*arg)) {
anIntOKDepList.add(*arg) ;
}
}
delete depIter ;
if (anIntOKDepList.getSize()>0) {
oocxcoutI(&function,Integration) << function.GetName() << ": Observables that function forcibly requires to be integrated internally " << anIntOKDepList << endl ;
}
sIter = function.serverIterator() ;
while((arg=(RooAbsArg*)sIter->Next())) {
if (!arg->dependsOnValue(intDepList)) {
if (function.dependsOnValue(*arg)) {
addServer(*arg,kTRUE,kFALSE) ;
}
continue ;
} else {
RooArgSet argLeafServers ;
arg->leafNodeServerList(&argLeafServers,0,kFALSE) ;
if (!arg->isValueServer(function) && !arg->isShapeServer(function)) {
continue ;
}
TIterator* lIter = argLeafServers.createIterator() ;
RooAbsArg* leaf ;
while((leaf=(RooAbsArg*)lIter->Next())) {
if (depList.find(leaf->GetName()) && function.dependsOnValue(*leaf)) {
RooAbsRealLValue* leaflv = dynamic_cast<RooAbsRealLValue*>(leaf) ;
if (leaflv && leaflv->getBinning(rangeName).isParameterized()) {
oocxcoutD(&function,Integration) << function.GetName() << " : Observable " << leaf->GetName() << " has parameterized binning, add value dependence of boundary objects rather than shape of leaf" << endl ;
if (leaflv->getBinning(rangeName).lowBoundFunc()) {
addServer(*leaflv->getBinning(rangeName).lowBoundFunc(),kTRUE,kFALSE) ;
}
if(leaflv->getBinning(rangeName).highBoundFunc()) {
addServer(*leaflv->getBinning(rangeName).highBoundFunc(),kTRUE,kFALSE) ;
}
} else {
oocxcoutD(&function,Integration) << function.GetName() << ": Adding observable " << leaf->GetName() << " of server "
<< arg->GetName() << " as shape dependent" << endl ;
addServer(*leaf,kFALSE,kTRUE) ;
}
} else if (!depList.find(leaf->GetName())) {
if (function.dependsOnValue(*leaf)) {
oocxcoutD(&function,Integration) << function.GetName() << ": Adding parameter " << leaf->GetName() << " of server " << arg->GetName() << " as value dependent" << endl ;
addServer(*leaf,kTRUE,kFALSE) ;
} else {
oocxcoutD(&function,Integration) << function.GetName() << ": Adding parameter " << leaf->GetName() << " of server " << arg->GetName() << " as shape dependent" << endl ;
addServer(*leaf,kFALSE,kTRUE) ;
}
}
}
delete lIter ;
}
Bool_t depOK(kFALSE) ;
if (arg->isDerived()) {
RooAbsRealLValue *realArgLV = dynamic_cast<RooAbsRealLValue*>(arg) ;
RooAbsCategoryLValue *catArgLV = dynamic_cast<RooAbsCategoryLValue*>(arg) ;
if ((realArgLV && intDepList.find(realArgLV->GetName()) && (realArgLV->isJacobianOK(intDepList)!=0)) || catArgLV) {
depOK = kTRUE ;
Bool_t overlapOK = kTRUE ;
RooAbsArg *otherArg ;
TIterator* sIter2 = function.serverIterator() ;
while((otherArg=(RooAbsArg*)sIter2->Next())) {
if (arg==otherArg) continue ;
if (otherArg->IsA()==RooConstVar::Class()) continue ;
if (arg->overlaps(*otherArg,kTRUE)) {
}
}
if (!overlapOK) depOK=kFALSE ;
delete sIter2 ;
}
} else {
depOK = kTRUE ;
}
if (depOK) {
anIntOKDepList.add(*arg,kTRUE) ;
oocxcoutI(&function,Integration) << function.GetName() << ": Observable " << arg->GetName() << " is suitable for analytical integration (if supported by p.d.f)" << endl ;
}
}
RooArgSet anIntDepList ;
RooArgSet *anaSet = new RooArgSet( _anaList, Form("UniqueCloneOf_%s",_anaList.GetName()));
_mode = ((RooAbsReal&)_function.arg()).getAnalyticalIntegralWN(anIntOKDepList,*anaSet,_funcNormSet,RooNameReg::str(_rangeName)) ;
_anaList.removeAll() ;
_anaList.add(*anaSet);
delete anaSet;
if (_mode==0) {
_anaList.removeAll() ;
}
if (_mode!=0) {
oocxcoutI(&function,Integration) << function.GetName() << ": Function integrated observables " << _anaList << " internally with code " << _mode << endl ;
}
function.getVal(_funcNormSet) ;
RooArgSet numIntDepList ;
TIterator* aiIter = _anaList.createIterator() ;
while ((arg=(RooAbsArg*)aiIter->Next())) {
if (arg->IsA()->InheritsFrom(RooAbsRealLValue::Class()) && arg->isDerived() && !arg->isFundamental()) {
_jacList.add(*arg) ;
RooAbsArg *argDep ;
RooArgSet *argDepList = arg->getObservables(&intDepList) ;
TIterator *adIter = argDepList->createIterator() ;
while ((argDep=(RooAbsArg*)adIter->Next())) {
if (argDep->IsA()->InheritsFrom(RooAbsCategoryLValue::Class()) && intDepList.contains(*argDep)) {
numIntDepList.add(*argDep,kTRUE) ;
}
}
delete adIter ;
delete argDepList ;
}
}
delete aiIter ;
sIter->Reset() ;
while((arg=(RooAbsArg*)sIter->Next())) {
if (!_anaList.find(arg->GetName()) && arg->dependsOn(intDepList)) {
if (dynamic_cast<RooAbsLValue*>(arg) && arg->isDerived() && intDepList.contains(*arg)) {
numIntDepList.add(*arg,kTRUE) ;
} else {
RooArgSet *argDeps = arg->getObservables(&intDepList) ;
TIterator* iter = argDeps->createIterator() ;
RooAbsArg* dep ;
while((dep=(RooAbsArg*)iter->Next())) {
if (!_anaList.find(dep->GetName())) {
numIntDepList.add(*dep,kTRUE) ;
}
}
delete iter ;
delete argDeps ;
}
}
}
delete sIter ;
TIterator* numIter=numIntDepList.createIterator() ;
while ((arg=(RooAbsArg*)numIter->Next())) {
if (arg->IsA()->InheritsFrom(RooAbsRealLValue::Class())) {
_intList.add(*arg) ;
} else if (arg->IsA()->InheritsFrom(RooAbsCategoryLValue::Class())) {
_sumList.add(*arg) ;
}
}
delete numIter ;
if (_anaList.getSize()>0) {
oocxcoutI(&function,Integration) << function.GetName() << ": Observables " << _anaList << " are analytically integrated with code " << _mode << endl ;
}
if (_intList.getSize()>0) {
oocxcoutI(&function,Integration) << function.GetName() << ": Observables " << _intList << " are numerically integrated" << endl ;
}
if (_sumList.getSize()>0) {
oocxcoutI(&function,Integration) << function.GetName() << ": Observables " << _sumList << " are numerically summed" << endl ;
}
if (numIntDepList.getSize()>0) {
_intOperMode = Hybrid ;
} else if (_anaList.getSize()>0) {
_intOperMode = Analytic ;
} else {
_intOperMode = PassThrough ;
}
autoSelectDirtyMode() ;
_intList.snapshot(_saveInt) ;
_sumList.snapshot(_saveSum) ;
if (_sumList.getSize()>0) {
RooSuperCategory *sumCat = new RooSuperCategory(Form("%s_sumCat",GetName()),"sumCat",_sumList) ;
_sumCatIter = sumCat->typeIterator() ;
_sumCat.addOwned(*sumCat) ;
}
}
void RooRealIntegral::autoSelectDirtyMode()
{
TIterator* siter = serverIterator() ;
RooAbsArg* server ;
while((server=(RooAbsArg*)siter->Next())){
if (server->isValueServer(*this)) {
RooArgSet leafSet ;
server->leafNodeServerList(&leafSet) ;
TIterator* liter = leafSet.createIterator() ;
RooAbsArg* leaf ;
while((leaf=(RooAbsArg*)liter->Next())) {
if (leaf->operMode()==ADirty && leaf->isValueServer(*this)) {
setOperMode(ADirty) ;
break ;
}
if (leaf->getAttribute("projectedDependent")) {
setOperMode(ADirty) ;
break ;
}
}
delete liter ;
}
}
delete siter ;
}
Bool_t RooRealIntegral::servesExclusively(const RooAbsArg* server,const RooArgSet& exclLVBranches, const RooArgSet& allBranches) const
{
if (exclLVBranches.getSize()==0) return kFALSE ;
if (server->_clientList.GetSize()==0 && exclLVBranches.find(server->GetName())) {
return kFALSE ;
}
Int_t numLVServ(0) ;
RooAbsArg* client ;
TIterator* cIter = server->valueClientIterator() ;
while((client=(RooAbsArg*)cIter->Next())) {
if (!(exclLVBranches.find(client->GetName())==client)) {
if (allBranches.find(client->GetName())==client) {
if (!servesExclusively(client,exclLVBranches,allBranches)) {
delete cIter ;
return kFALSE ;
}
}
} else {
numLVServ++ ;
}
}
delete cIter ;
return (numLVServ==1) ;
}
Bool_t RooRealIntegral::initNumIntegrator() const
{
if(0 != _numIntEngine) {
if(_numIntEngine->isValid() && _numIntEngine->checkLimits() && !_restartNumIntEngine ) return kTRUE;
delete _numIntEngine ;
_numIntEngine= 0;
if(0 != _numIntegrand) {
delete _numIntegrand;
_numIntegrand= 0;
}
}
if(0 == _intList.getSize()) return kTRUE;
if(_mode != 0) {
_numIntegrand= new RooRealAnalytic(_function.arg(),_intList,_mode,_funcNormSet,_rangeName);
}
else {
_numIntegrand= new RooRealBinding(_function.arg(),_intList,_funcNormSet,kFALSE,_rangeName);
}
if(0 == _numIntegrand || !_numIntegrand->isValid()) {
coutE(Integration) << ClassName() << "::" << GetName() << ": failed to create valid integrand." << endl;
return kFALSE;
}
_numIntEngine = RooNumIntFactory::instance().createIntegrator(*_numIntegrand,*_iconfig) ;
if(0 == _numIntEngine || !_numIntEngine->isValid()) {
coutE(Integration) << ClassName() << "::" << GetName() << ": failed to create valid integrator." << endl;
return kFALSE;
}
cxcoutI(NumIntegration) << "RooRealIntegral::init(" << GetName() << ") using numeric integrator "
<< _numIntEngine->IsA()->GetName() << " to calculate Int" << _intList << endl ;
if (_intList.getSize()>3) {
cxcoutI(NumIntegration) << "RooRealIntegral::init(" << GetName() << ") evaluation requires " << _intList.getSize() << "-D numeric integration step. Evaluation may be slow, sufficient numeric precision for fitting & minimization is not guaranteed" << endl ;
}
_restartNumIntEngine = kFALSE ;
return kTRUE;
}
RooRealIntegral::RooRealIntegral(const RooRealIntegral& other, const char* name) :
RooAbsReal(other,name),
_valid(other._valid),
_sumList("!sumList",this,other._sumList),
_intList("!intList",this,other._intList),
_anaList("!anaList",this,other._anaList),
_jacList("!jacList",this,other._jacList),
_facList("!facList","Variables independent of function",this,kFALSE,kTRUE),
_facListIter(_facList.createIterator()),
_jacListIter(_jacList.createIterator()),
_function("!func",this,other._function),
_iconfig(other._iconfig),
_sumCat("!sumCat",this,other._sumCat),
_sumCatIter(0),
_mode(other._mode),
_intOperMode(other._intOperMode),
_restartNumIntEngine(kFALSE),
_numIntEngine(0),
_numIntegrand(0),
_rangeName(other._rangeName),
_params(0),
_cacheNum(kFALSE)
{
_funcNormSet = other._funcNormSet ? (RooArgSet*)other._funcNormSet->snapshot(kFALSE) : 0 ;
other._facListIter->Reset() ;
RooAbsArg* arg ;
while((arg=(RooAbsArg*)other._facListIter->Next())) {
RooAbsArg* argClone = (RooAbsArg*) arg->Clone() ;
_facListOwned.addOwned(*argClone) ;
_facList.add(*argClone) ;
addServer(*argClone,kFALSE,kTRUE) ;
}
other._intList.snapshot(_saveInt) ;
other._sumList.snapshot(_saveSum) ;
}
RooRealIntegral::~RooRealIntegral()
{
if (_numIntEngine) delete _numIntEngine ;
if (_numIntegrand) delete _numIntegrand ;
if (_funcNormSet) delete _funcNormSet ;
delete _facListIter ;
delete _jacListIter ;
if (_sumCatIter) delete _sumCatIter ;
if (_params) delete _params ;
}
RooAbsReal* RooRealIntegral::createIntegral(const RooArgSet& iset, const RooArgSet* nset, const RooNumIntConfig* cfg, const char* rangeName) const
{
if (iset.getSize()==0) {
return RooAbsReal::createIntegral(iset,nset,cfg,rangeName) ;
}
RooArgSet isetAll(iset) ;
isetAll.add(_sumList) ;
isetAll.add(_intList) ;
isetAll.add(_anaList) ;
isetAll.add(_facList) ;
const RooArgSet* newNormSet(0) ;
RooArgSet* tmp(0) ;
if (nset && !_funcNormSet) {
newNormSet = nset ;
} else if (!nset && _funcNormSet) {
newNormSet = _funcNormSet ;
} else if (nset && _funcNormSet) {
tmp = new RooArgSet ;
tmp->add(*nset) ;
tmp->add(*_funcNormSet,kTRUE) ;
newNormSet = tmp ;
}
RooAbsReal* ret = _function.arg().createIntegral(isetAll,newNormSet,cfg,rangeName) ;
if (tmp) {
delete tmp ;
}
return ret ;
}
Double_t RooRealIntegral::getValV(const RooArgSet* nset) const
{
if (nset && nset!=_lastNSet) {
((RooAbsReal*) this)->setProxyNormSet(nset) ;
_lastNSet = (RooArgSet*) nset ;
}
if (isValueOrShapeDirtyAndClear()) {
_value = traceEval(nset) ;
}
return _value ;
}
Double_t RooRealIntegral::evaluate() const
{
Double_t retVal(0) ;
switch (_intOperMode) {
case Hybrid:
{
RooDouble* cacheVal(0) ;
if ((_cacheNum && _intList.getSize()>0) || _intList.getSize()>=_cacheAllNDim) {
cacheVal = (RooDouble*) expensiveObjectCache().retrieveObject(GetName(),RooDouble::Class(),parameters()) ;
}
if (cacheVal) {
retVal = *cacheVal ;
} else {
Bool_t origState = inhibitDirty() ;
setDirtyInhibit(kTRUE) ;
if(!(_valid= initNumIntegrator())) {
coutE(Integration) << ClassName() << "::" << GetName()
<< ":evaluate: cannot initialize numerical integrator" << endl;
return 0;
}
_saveInt = _intList ;
_saveSum = _sumList ;
retVal = sum() ;
setDirtyInhibit(origState) ;
_intList=_saveInt ;
_sumList=_saveSum ;
if ((_cacheNum && _intList.getSize()>0) || _intList.getSize()>=_cacheAllNDim) {
RooDouble* val = new RooDouble(retVal) ;
expensiveObjectCache().registerObject(_function.arg().GetName(),GetName(),*val,parameters()) ;
}
}
break ;
}
case Analytic:
{
retVal = ((RooAbsReal&)_function.arg()).analyticalIntegralWN(_mode,_funcNormSet,RooNameReg::str(_rangeName)) / jacobianProduct() ;
cxcoutD(Tracing) << "RooRealIntegral::evaluate_analytic(" << GetName()
<< ")func = " << _function.arg().IsA()->GetName() << "::" << _function.arg().GetName()
<< " raw = " << retVal << " _funcNormSet = " << (_funcNormSet?*_funcNormSet:RooArgSet()) << endl ;
break ;
}
case PassThrough:
{
retVal= _function.arg().getVal(_funcNormSet) ;
break ;
}
}
if (_facList.getSize()>0) {
RooAbsArg *arg ;
_facListIter->Reset() ;
while((arg=(RooAbsArg*)_facListIter->Next())) {
if (arg->IsA()->InheritsFrom(RooAbsRealLValue::Class())) {
RooAbsRealLValue* argLV = (RooAbsRealLValue*)arg ;
retVal *= (argLV->getMax() - argLV->getMin()) ;
}
if (arg->IsA()->InheritsFrom(RooAbsCategoryLValue::Class())) {
RooAbsCategoryLValue* argLV = (RooAbsCategoryLValue*)arg ;
retVal *= argLV->numTypes() ;
}
}
}
if (dologD(Tracing)) {
cxcoutD(Tracing) << "RooRealIntegral::evaluate(" << GetName() << ") anaInt = " << _anaList << " numInt = " << _intList << _sumList << " mode = " ;
switch(_mode) {
case Hybrid: ccoutD(Tracing) << "Hybrid" ; break ;
case Analytic: ccoutD(Tracing) << "Analytic" ; break ;
case PassThrough: ccoutD(Tracing) << "PassThrough" ; break ;
}
ccxcoutD(Tracing) << "raw*fact = " << retVal << endl ;
}
return retVal ;
}
Double_t RooRealIntegral::jacobianProduct() const
{
if (_jacList.getSize()==0) {
return 1 ;
}
Double_t jacProd(1) ;
_jacListIter->Reset() ;
RooAbsRealLValue* arg ;
while ((arg=(RooAbsRealLValue*)_jacListIter->Next())) {
jacProd *= arg->jacobian() ;
}
return fabs(jacProd) ;
}
Double_t RooRealIntegral::sum() const
{
if (_sumList.getSize()!=0) {
Double_t total(0) ;
_sumCatIter->Reset() ;
RooCatType* type ;
RooSuperCategory* sumCat = (RooSuperCategory*) _sumCat.first() ;
while((type=(RooCatType*)_sumCatIter->Next())) {
sumCat->setIndex(type->getVal()) ;
if (!_rangeName || sumCat->inRange(RooNameReg::str(_rangeName))) {
total += integrate() / jacobianProduct() ;
}
}
return total ;
} else {
Double_t ret = integrate() / jacobianProduct() ;
return ret ;
}
}
Double_t RooRealIntegral::integrate() const
{
if (!_numIntEngine) {
return ((RooAbsReal&)_function.arg()).analyticalIntegralWN(_mode,_funcNormSet,RooNameReg::str(_rangeName)) ;
}
else {
return _numIntEngine->calculate() ;
}
}
Bool_t RooRealIntegral::redirectServersHook(const RooAbsCollection& ,
Bool_t , Bool_t , Bool_t )
{
_restartNumIntEngine = kTRUE ;
autoSelectDirtyMode() ;
_saveInt.removeAll() ;
_saveSum.removeAll() ;
_intList.snapshot(_saveInt) ;
_sumList.snapshot(_saveSum) ;
if (_params) {
delete _params ;
_params = 0 ;
}
return kFALSE ;
}
const RooArgSet& RooRealIntegral::parameters() const
{
if (!_params) {
_params = new RooArgSet("params") ;
TIterator* siter = serverIterator() ;
RooArgSet params ;
RooAbsArg* server ;
while((server = (RooAbsArg*)siter->Next())) {
if (server->isValueServer(*this)) _params->add(*server) ;
}
delete siter ;
}
return *_params ;
}
void RooRealIntegral::operModeHook()
{
if (_operMode==ADirty) {
}
}
Bool_t RooRealIntegral::isValidReal(Double_t , Bool_t ) const
{
return kTRUE ;
}
void RooRealIntegral::printMetaArgs(ostream& os) const
{
if (intVars().getSize()!=0) {
os << "Int " ;
}
os << _function.arg().GetName() ;
if (_funcNormSet) {
os << "_Norm" ;
os << *_funcNormSet ;
os << " " ;
}
RooArgSet tmp(_anaList) ;
tmp.add(_facList) ;
if (tmp.getSize()>0) {
os << "d[Ana]" ;
os << tmp ;
os << " " ;
}
RooArgSet tmp2(_intList) ;
tmp2.add(_sumList) ;
if (tmp2.getSize()>0) {
os << " d[Num]" ;
os << tmp2 ;
os << " " ;
}
}
void RooRealIntegral::printMultiline(ostream& os, Int_t contents, Bool_t verbose, TString indent) const
{
RooAbsReal::printMultiline(os,contents,verbose,indent) ;
os << indent << "--- RooRealIntegral ---" << endl;
os << indent << " Integrates ";
_function.arg().printStream(os,kName|kArgs,kSingleLine,indent);
TString deeper(indent);
deeper.Append(" ");
os << indent << " operating mode is "
<< (_intOperMode==Hybrid?"Hybrid":(_intOperMode==Analytic?"Analytic":"PassThrough")) << endl ;
os << indent << " Summed discrete args are " << _sumList << endl ;
os << indent << " Numerically integrated args are " << _intList << endl;
os << indent << " Analytically integrated args using mode " << _mode << " are " << _anaList << endl ;
os << indent << " Arguments included in Jacobian are " << _jacList << endl ;
os << indent << " Factorized arguments are " << _facList << endl ;
os << indent << " Function normalization set " ;
if (_funcNormSet)
_funcNormSet->Print("1") ;
else
os << "<none>" ;
os << endl ;
}
void RooRealIntegral::setCacheAllNumeric(Int_t ndim) {
_cacheAllNDim = ndim ;
}
Int_t RooRealIntegral::getCacheAllNumeric()
{
return _cacheAllNDim ;
}