@@ -59,17 +59,25 @@ ClassImp(RooRealIntegral);
5959
6060namespace {
6161
62- void addValueAndShapeServers (RooAbsArg &integral, RooAbsReal const &function, RooArgSet const &depList,
63- RooArgSet const &intDepList, const char *rangeName, RooArgSet &anIntOKDepList)
62+ struct ServerToAdd {
63+ ServerToAdd (RooAbsArg * theArg, bool isShape) : arg{theArg}, isShapeServer{isShape} {}
64+ RooAbsArg * arg = nullptr ;
65+ bool isShapeServer = false ;
66+ };
67+
68+ std::vector<ServerToAdd> getValueAndShapeServers (RooAbsReal const &function, RooArgSet const &depList,
69+ RooArgSet const &intDepList, const char *rangeName,
70+ RooArgSet &anIntOKDepList)
6471{
72+ std::vector<ServerToAdd> serversToAdd;
6573
6674 for (const auto arg : function.servers ()) {
6775
6876 // Dependent or parameter?
6977 if (!arg->dependsOnValue (intDepList)) {
7078
7179 if (function.dependsOnValue (*arg)) {
72- integral. addServer (* arg, true , false );
80+ serversToAdd. emplace_back ( arg, false );
7381 }
7482
7583 continue ;
@@ -107,26 +115,26 @@ void addValueAndShapeServers(RooAbsArg &integral, RooAbsReal const &function, Ro
107115 << " has parameterized binning, add value dependence of boundary objects rather than shape of leaf"
108116 << endl;
109117 if (leaflv->getBinning (rangeName).lowBoundFunc ()) {
110- integral. addServer (* leaflv->getBinning (rangeName).lowBoundFunc (), true , false );
118+ serversToAdd. emplace_back ( leaflv->getBinning (rangeName).lowBoundFunc (), false );
111119 }
112120 if (leaflv->getBinning (rangeName).highBoundFunc ()) {
113- integral. addServer (* leaflv->getBinning (rangeName).highBoundFunc (), true , false );
121+ serversToAdd. emplace_back ( leaflv->getBinning (rangeName).highBoundFunc (), false );
114122 }
115123 } else {
116124 oocxcoutD (&function, Integration) << function.GetName () << " : Adding observable " << leaf->GetName ()
117125 << " of server " << arg->GetName () << " as shape dependent" << endl;
118- integral. addServer (* leaf, false , true );
126+ serversToAdd. emplace_back ( leaf, true );
119127 }
120128 } else if (!depList.find (leaf->GetName ())) {
121129
122130 if (argLeafValueServers.contains (*leaf)) {
123131 oocxcoutD (&function, Integration) << function.GetName () << " : Adding parameter " << leaf->GetName ()
124132 << " of server " << arg->GetName () << " as value dependent" << endl;
125- integral. addServer (* leaf, true , false );
133+ serversToAdd. emplace_back ( leaf, false );
126134 } else {
127135 oocxcoutD (&function, Integration) << function.GetName () << " : Adding parameter " << leaf->GetName ()
128136 << " of server " << arg->GetName () << " as shape dependent" << endl;
129- integral. addServer (* leaf, false , true );
137+ serversToAdd. emplace_back ( leaf, true );
130138 }
131139 }
132140 }
@@ -174,6 +182,8 @@ void addValueAndShapeServers(RooAbsArg &integral, RooAbsReal const &function, Ro
174182 << " is suitable for analytical integration (if supported by p.d.f)" << endl;
175183 }
176184 }
185+
186+ return serversToAdd;
177187}
178188
179189} // namespace
@@ -418,7 +428,10 @@ RooRealIntegral::RooRealIntegral(const char *name, const char *title,
418428 // Add all parameters/dependents as value/shape servers *
419429 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
420430
421- addValueAndShapeServers (*this , function, depList, intDepList, rangeName, anIntOKDepList);
431+ auto serversToAdd = getValueAndShapeServers (function, depList, intDepList, rangeName, anIntOKDepList);
432+ // We will not add the servers just now, because it makes only sense to add
433+ // them once we have made sure that this integral is not operating in
434+ // pass-through mode. It will be done at the end of this constructor.
422435
423436 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
424437 // * E) interact with function to make list of objects actually integrated analytically *
@@ -581,6 +594,14 @@ RooRealIntegral::RooRealIntegral(const char *name, const char *title,
581594 _sumCat.addOwned (*sumCat) ;
582595 }
583596
597+ // Only if we are not in pass-through mode we need to add the shape and value
598+ // servers separately.
599+ if (_intOperMode != PassThrough) {
600+ for (auto const & toAdd : serversToAdd) {
601+ addServer (*toAdd.arg , !toAdd.isShapeServer , toAdd.isShapeServer );
602+ }
603+ }
604+
584605 TRACE_CREATE
585606}
586607
@@ -912,6 +933,10 @@ double RooRealIntegral::evaluate() const
912933 // In pass through mode, the RooRealIntegral should have registered the
913934 // function as a value server, because we directly depend on its value.
914935 assert (_function.isValueServer ());
936+ // There should be no other servers besides the actual function and the
937+ // factorized observables that the function doesn't depend on but are
938+ // integrated over later.
939+ assert (servers ().size () == _facList.size () + 1 );
915940
916941 // setDirtyInhibit(true) ;
917942 retVal= _function.arg ().getVal (_funcNormSet) ;
0 commit comments