/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitCore                                                       *
 * @(#)root/roofitcore:$Id$
 * Authors:                                                                  *
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
 *   GR, Gerhard Raven,   VU Amsterdan,     graven@nikhef.nl                 *
 *                                                                           *
 * Copyright (c) 2000-2007, Regents of the University of California          *
 *                          and Stanford University. All rights reserved.    *
 *                                                                           *
 * Redistribution and use in source and binary forms,                        *
 * with or without modification, are permitted according to the terms        *
 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
 *****************************************************************************/

//////////////////////////////////////////////////////////////////////////////
//
// BEGIN_HTML
//
// RooProduct a RooAbsReal implementation that represent the product
// of a given set of other RooAbsReal objects
//
// END_HTML
//


#include "RooFit.h"

#include "Riostream.h"
#include "Riostream.h"
#include <math.h>
#include <vector>
#include <utility>
#include <memory>
#include <algorithm>

#include "RooProduct.h"
#include "RooNameReg.h"
#include "RooAbsReal.h"
#include "RooAbsCategory.h"
#include "RooErrorHandler.h"
#include "RooMsgService.h"
#include "RooTrace.h"

using namespace std ;

ClassImp(RooProduct)
;

class RooProduct::ProdMap : public  std::vector<std::pair<RooArgSet*,RooArgList*> > {} ;

// Namespace with helper functions that have STL stuff that we don't want to expose to CINT
namespace {
  typedef RooProduct::ProdMap::iterator RPPMIter ;
  std::pair<RPPMIter,RPPMIter> findOverlap2nd(RPPMIter i, RPPMIter end)  ;
  void dump_map(ostream& os, RPPMIter i, RPPMIter end) ;
}



//_____________________________________________________________________________
RooProduct::RooProduct() :
  _compRIter( _compRSet.createIterator() ),
  _compCIter( _compCSet.createIterator() )
{
  // Default constructor
  TRACE_CREATE
}



//_____________________________________________________________________________
RooProduct::~RooProduct()
{
  // Destructor

  if (_compRIter) {
    delete _compRIter ;
  }

  if (_compCIter) {
    delete _compCIter ;
  }
  TRACE_DESTROY
}



//_____________________________________________________________________________
RooProduct::RooProduct(const char* name, const char* title, const RooArgList& prodSet) :
  RooAbsReal(name, title),
  _compRSet("!compRSet","Set of real product components",this),
  _compCSet("!compCSet","Set of category product components",this),
  _compRIter( _compRSet.createIterator() ),
  _compCIter( _compCSet.createIterator() ),
  _cacheMgr(this,10)
{
  // Construct function representing the product of functions in prodSet

  TIterator* compIter = prodSet.createIterator() ;
  RooAbsArg* comp ;
  while((comp = (RooAbsArg*)compIter->Next())) {
    if (dynamic_cast<RooAbsReal*>(comp)) {
      _compRSet.add(*comp) ;
    } else if (dynamic_cast<RooAbsCategory*>(comp)) {
      _compCSet.add(*comp) ;
    } else {
      coutE(InputArguments) << "RooProduct::ctor(" << GetName() << ") ERROR: component " << comp->GetName() 
			    << " is not of type RooAbsReal or RooAbsCategory" << endl ;
      RooErrorHandler::softAbort() ;
    }
  }
  delete compIter ;
  TRACE_CREATE
}



//_____________________________________________________________________________
RooProduct::RooProduct(const RooProduct& other, const char* name) :
  RooAbsReal(other, name), 
  _compRSet("!compRSet",this,other._compRSet),
  _compCSet("!compCSet",this,other._compCSet),
  _compRIter(_compRSet.createIterator()),
  _compCIter(_compCSet.createIterator()),
  _cacheMgr(other._cacheMgr,this)
{
  // Copy constructor
  TRACE_CREATE
}



//_____________________________________________________________________________
Bool_t RooProduct::forceAnalyticalInt(const RooAbsArg& dep) const
{
  // Force internal handling of integration of given observable if any
  // of the product terms depend on it.

  _compRIter->Reset() ;
  RooAbsReal* rcomp ;
  Bool_t depends(kFALSE);
  while((rcomp=(RooAbsReal*)_compRIter->Next())&&!depends) {
        depends = rcomp->dependsOn(dep);
  }
  return depends ;
}



//_____________________________________________________________________________
RooProduct::ProdMap* RooProduct::groupProductTerms(const RooArgSet& allVars) const 
{
  // Group observables into subsets in which the product factorizes
  // and that can thus be integrated separately

  ProdMap* map = new ProdMap ;

  // Do we have any terms which do not depend on the
  // on the variables we integrate over?
  RooAbsReal* rcomp ; _compRIter->Reset() ;
  RooArgList *indep = new RooArgList();
  while((rcomp=(RooAbsReal*)_compRIter->Next())) {
    if( !rcomp->dependsOn(allVars) ) indep->add(*rcomp);
  }
  if (indep->getSize()!=0) {
    map->push_back( std::make_pair(new RooArgSet(),indep) );
  }

  // Map observables -> functions ; start with individual observables
  TIterator *allVarsIter = allVars.createIterator() ;
  RooAbsReal* var ;
  while((var=(RooAbsReal*)allVarsIter->Next())) {
    RooArgSet *vars  = new RooArgSet(); vars->add(*var);
    RooArgList *comps = new RooArgList();
    RooAbsReal* rcomp2 ; 
    
    _compRIter->Reset() ;
    while((rcomp2=(RooAbsReal*)_compRIter->Next())) {
      if( rcomp2->dependsOn(*var) ) comps->add(*rcomp2);
    }
    map->push_back( std::make_pair(vars,comps) );
  }
  delete allVarsIter ;

  // Merge groups with overlapping dependents
  Bool_t overlap;
  do {
    std::pair<ProdMap::iterator,ProdMap::iterator> i = findOverlap2nd(map->begin(),map->end());
    overlap = (i.first!=i.second);
    if (overlap) {
      i.first->first->add(*i.second->first);

      // In the merging step, make sure not to duplicate
      RooFIter it = i.second->second->fwdIterator() ;
      RooAbsArg* targ ;
      while ((targ = it.next())) {
	if (!i.first->second->find(*targ)) {
	  i.first->second->add(*targ) ;
	}
      }
      //i.first->second->add(*i.second->second);

      delete i.second->first;
      delete i.second->second;
      map->erase(i.second);
    }
  } while (overlap);
  
  // check that we have all variables to be integrated over on the LHS
  // of the map, and all terms in the product do appear on the RHS
  int nVar=0; int nFunc=0;
  for (ProdMap::iterator i = map->begin();i!=map->end();++i) {
    nVar+=i->first->getSize();
    nFunc+=i->second->getSize();
  }
  assert(nVar==allVars.getSize());
  assert(nFunc==_compRSet.getSize());
  return map;
}



//_____________________________________________________________________________
Int_t RooProduct::getPartIntList(const RooArgSet* iset, const char *isetRange) const
{
  // Return list of (partial) integrals whose product defines the integral of this
  // RooProduct over the observables in iset in range isetRange. If no such list
  // exists, create it now and store it in the cache for future use.


  // check if we already have integrals for this combination of factors
  Int_t sterileIndex(-1);
  CacheElem* cache = (CacheElem*) _cacheMgr.getObj(iset,iset,&sterileIndex,RooNameReg::ptr(isetRange));
  if (cache!=0) {
    Int_t code = _cacheMgr.lastIndex();
    return code;
  }
  
  ProdMap* map = groupProductTerms(*iset);

  cxcoutD(Integration) << "RooProduct::getPartIntList(" << GetName() << ") groupProductTerms returned map" ;
  if (dologD(Integration)) {
    dump_map(ccoutD(Integration),map->begin(),map->end()); 
    ccoutD(Integration) << endl;
  }
  
  // did we find any factorizable terms?
  if (map->size()<2) {
    
    for (ProdMap::iterator iter = map->begin() ; iter != map->end() ; ++iter) {
      delete iter->first ;
      delete iter->second ;
    }

    delete map ;
    return -1; // RRI caller will zero analVars if return code = 0....
  }
  cache = new CacheElem();

  for (ProdMap::const_iterator i = map->begin();i!=map->end();++i) {
    RooAbsReal *term(0);
    if (i->second->getSize()>1) { // create a RooProd for this subexpression
      const char *name = makeFPName("SUBPROD_",*i->second);
      term = new RooProduct(name,name,*i->second);
      cache->_ownedList.addOwned(*term);
      cxcoutD(Integration) << "RooProduct::getPartIntList(" << GetName() << ") created subexpression " << term->GetName() << endl;
    } else {
      assert(i->second->getSize()==1);
      auto_ptr<TIterator> j( i->second->createIterator() );
      term = (RooAbsReal*)j->Next();
    }
    assert(term!=0);
    if (i->first->getSize()==0) { // check whether we need to integrate over this term or not...
      cache->_prodList.add(*term);
      cxcoutD(Integration) << "RooProduct::getPartIntList(" << GetName() << ") adding simple factor " << term->GetName() << endl;
    } else {
      RooAbsReal *integral = term->createIntegral(*i->first,isetRange);
      cache->_prodList.add(*integral);
      cache->_ownedList.addOwned(*integral);
      cxcoutD(Integration) << "RooProduct::getPartIntList(" << GetName() << ") adding integral for " << term->GetName() << " : " << integral->GetName() << endl;
    }
  }
  // add current set-up to cache, and return index..
  Int_t code = _cacheMgr.setObj(iset,iset,(RooAbsCacheElement*)cache,RooNameReg::ptr(isetRange));

  cxcoutD(Integration) << "RooProduct::getPartIntList(" << GetName() << ") created list " << cache->_prodList << " with code " << code+1 << endl
		       << " for iset=" << *iset << " @" << iset << " range: " << (isetRange?isetRange:"<none>") << endl ;

  for (ProdMap::iterator iter = map->begin() ; iter != map->end() ; ++iter) {
    delete iter->first ;
    delete iter->second ;
  }
  delete map ;
  return code;
}


//_____________________________________________________________________________
Int_t RooProduct::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars,
					  const RooArgSet* /*normSet*/,
					  const char* rangeName) const
{
  // Declare that we handle all integrations internally

  if (_forceNumInt) return 0 ;

  // Declare that we can analytically integrate all requested observables
  // (basically, we will take care of the problem, and delegate where required)
  //assert(normSet==0);
  assert(analVars.getSize()==0);
  analVars.add(allVars) ;
  Int_t code = getPartIntList(&analVars,rangeName)+1;
  return code ;
}


//_____________________________________________________________________________
Double_t RooProduct::analyticalIntegral(Int_t code, const char* rangeName) const
{
  // Calculate integral internally from appropriate partial integral cache

  // note: rangeName implicit encoded in code: see _cacheMgr.setObj in getPartIntList...
  CacheElem *cache = (CacheElem*) _cacheMgr.getObjByIndex(code-1);
  if (cache==0) { 
    // cache got sterilized, trigger repopulation of this slot, then try again...
    std::auto_ptr<RooArgSet> vars( getParameters(RooArgSet()) );
    std::auto_ptr<RooArgSet> iset(  _cacheMgr.nameSet2ByIndex(code-1)->select(*vars) );
    Int_t code2 = getPartIntList(iset.get(),rangeName)+1;
    assert(code==code2); // must have revived the right (sterilized) slot...
    return analyticalIntegral(code2,rangeName);
  }
  assert(cache!=0);
  
  return calculate(cache->_prodList);
}


//_____________________________________________________________________________
Double_t RooProduct::calculate(const RooArgList& partIntList) const
{
  // Calculate and return product of partial terms in partIntList

  RooAbsReal *term(0);
  Double_t val=1;
  RooFIter i = partIntList.fwdIterator() ;
  while((term=(RooAbsReal*)i.next())) {
    double x = term->getVal();
    val*= x;
  }
  return val;
}


//_____________________________________________________________________________
const char* RooProduct::makeFPName(const char *pfx,const RooArgSet& terms) const
{
  // Construct automatic name for internal product terms

  static TString pname;
  pname = pfx;
  std::auto_ptr<TIterator> i( terms.createIterator() );
  RooAbsArg *arg;
  Bool_t first(kTRUE);
  while((arg=(RooAbsArg*)i->Next())) {
    if (first) { first=kFALSE;}
    else pname.Append("_X_");
    pname.Append(arg->GetName());
  }
  return pname.Data();
}



//_____________________________________________________________________________
Double_t RooProduct::evaluate() const 
{
  // Evaluate product of input functions

  Double_t prod(1) ;

  RooFIter compRIter = _compRSet.fwdIterator() ;
  RooAbsReal* rcomp ;
  const RooArgSet* nset = _compRSet.nset() ;
  while((rcomp=(RooAbsReal*)compRIter.next())) {
    prod *= rcomp->getVal(nset) ;
  }
  
  RooFIter compCIter = _compCSet.fwdIterator() ;
  RooAbsCategory* ccomp ;
  while((ccomp=(RooAbsCategory*)compCIter.next())) {
    prod *= ccomp->getIndex() ;
  }
  
  return prod ;
}



//_____________________________________________________________________________
std::list<Double_t>* RooProduct::binBoundaries(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
{
  // Forward the plot sampling hint from the p.d.f. that defines the observable obs  
  RooFIter iter = _compRSet.fwdIterator() ;
  RooAbsReal* func ;
  while((func=(RooAbsReal*)iter.next())) {
    list<Double_t>* binb = func->binBoundaries(obs,xlo,xhi) ;      
    if (binb) {
      return binb ;
    }
  }
  
  return 0 ;  
}


//_____________________________________________________________________________B
Bool_t RooProduct::isBinnedDistribution(const RooArgSet& obs) const 
{
  // If all components that depend on obs are binned that so is the product
  
  RooFIter iter = _compRSet.fwdIterator() ;
  RooAbsReal* func ;
  while((func=(RooAbsReal*)iter.next())) {
    if (func->dependsOn(obs) && !func->isBinnedDistribution(obs)) {
      return kFALSE ;
    }
  }
  
  return kTRUE  ;  
}



//_____________________________________________________________________________
std::list<Double_t>* RooProduct::plotSamplingHint(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
{
  // Forward the plot sampling hint from the p.d.f. that defines the observable obs  
  RooFIter iter = _compRSet.fwdIterator() ;
  RooAbsReal* func ;
  while((func=(RooAbsReal*)iter.next())) {
    list<Double_t>* hint = func->plotSamplingHint(obs,xlo,xhi) ;      
    if (hint) {
      return hint ;
    }
  }
  
  return 0 ;
}



//_____________________________________________________________________________
RooProduct::CacheElem::~CacheElem() 
{
  // Destructor
}


//_____________________________________________________________________________
RooArgList RooProduct::CacheElem::containedArgs(Action) 
{
  // Return list of all RooAbsArgs in cache element
  RooArgList ret(_ownedList) ;
  return ret ;
}




//_____________________________________________________________________________
void RooProduct::setCacheAndTrackHints(RooArgSet& trackNodes) 
{
  // Label OK'ed components of a RooProduct with cache-and-track

  RooArgSet comp(components()) ;
  RooFIter piter = comp.fwdIterator() ;
  RooAbsArg* parg ;
  while ((parg=piter.next())) {
    if (parg->isDerived()) {
      if (parg->canNodeBeCached()==Always) {
	trackNodes.add(*parg) ;
	//cout << "tracking node RooProduct component " << parg->IsA()->GetName() << "::" << parg->GetName() << endl ;
      }
    }
  }
}							    





//_____________________________________________________________________________
void RooProduct::printMetaArgs(ostream& os) const 
{
  // Customized printing of arguments of a RooProduct to more intuitively reflect the contents of the
  // product operator construction

  Bool_t first(kTRUE) ;

  _compRIter->Reset() ;
  RooAbsReal* rcomp ;
  while((rcomp=(RooAbsReal*)_compRIter->Next())) {
    if (!first) {  os << " * " ; } else {  first = kFALSE ; }
    os << rcomp->GetName() ;
  }
  
  _compCIter->Reset() ;
  RooAbsCategory* ccomp ;
  while((ccomp=(RooAbsCategory*)_compCIter->Next())) {
    if (!first) {  os << " * " ; } else {  first = kFALSE ; }
    os << ccomp->GetName() ;
  }

  os << " " ;    
}





namespace {

std::pair<RPPMIter,RPPMIter> findOverlap2nd(RPPMIter i, RPPMIter end) 
{
  // Utility function finding pairs of overlapping input functions
  for (; i!=end; ++i) for ( RPPMIter j(i+1); j!=end; ++j) {
    if (i->second->overlaps(*j->second)) {
      return std::make_pair(i,j);
    }
  }
  return std::make_pair(end,end);
}

  
void dump_map(ostream& os, RPPMIter i, RPPMIter end) 
{
  // Utility dump function for debugging
  Bool_t first(kTRUE);
  os << " [ " ;
  for(; i!=end;++i) {
    if (first) { first=kFALSE; }
    else { os << " , " ; }
    os << *(i->first) << " -> " << *(i->second) ;
  }
  os << " ] " ; 
}

}




 RooProduct.cxx:1
 RooProduct.cxx:2
 RooProduct.cxx:3
 RooProduct.cxx:4
 RooProduct.cxx:5
 RooProduct.cxx:6
 RooProduct.cxx:7
 RooProduct.cxx:8
 RooProduct.cxx:9
 RooProduct.cxx:10
 RooProduct.cxx:11
 RooProduct.cxx:12
 RooProduct.cxx:13
 RooProduct.cxx:14
 RooProduct.cxx:15
 RooProduct.cxx:16
 RooProduct.cxx:17
 RooProduct.cxx:18
 RooProduct.cxx:19
 RooProduct.cxx:20
 RooProduct.cxx:21
 RooProduct.cxx:22
 RooProduct.cxx:23
 RooProduct.cxx:24
 RooProduct.cxx:25
 RooProduct.cxx:26
 RooProduct.cxx:27
 RooProduct.cxx:28
 RooProduct.cxx:29
 RooProduct.cxx:30
 RooProduct.cxx:31
 RooProduct.cxx:32
 RooProduct.cxx:33
 RooProduct.cxx:34
 RooProduct.cxx:35
 RooProduct.cxx:36
 RooProduct.cxx:37
 RooProduct.cxx:38
 RooProduct.cxx:39
 RooProduct.cxx:40
 RooProduct.cxx:41
 RooProduct.cxx:42
 RooProduct.cxx:43
 RooProduct.cxx:44
 RooProduct.cxx:45
 RooProduct.cxx:46
 RooProduct.cxx:47
 RooProduct.cxx:48
 RooProduct.cxx:49
 RooProduct.cxx:50
 RooProduct.cxx:51
 RooProduct.cxx:52
 RooProduct.cxx:53
 RooProduct.cxx:54
 RooProduct.cxx:55
 RooProduct.cxx:56
 RooProduct.cxx:57
 RooProduct.cxx:58
 RooProduct.cxx:59
 RooProduct.cxx:60
 RooProduct.cxx:61
 RooProduct.cxx:62
 RooProduct.cxx:63
 RooProduct.cxx:64
 RooProduct.cxx:65
 RooProduct.cxx:66
 RooProduct.cxx:67
 RooProduct.cxx:68
 RooProduct.cxx:69
 RooProduct.cxx:70
 RooProduct.cxx:71
 RooProduct.cxx:72
 RooProduct.cxx:73
 RooProduct.cxx:74
 RooProduct.cxx:75
 RooProduct.cxx:76
 RooProduct.cxx:77
 RooProduct.cxx:78
 RooProduct.cxx:79
 RooProduct.cxx:80
 RooProduct.cxx:81
 RooProduct.cxx:82
 RooProduct.cxx:83
 RooProduct.cxx:84
 RooProduct.cxx:85
 RooProduct.cxx:86
 RooProduct.cxx:87
 RooProduct.cxx:88
 RooProduct.cxx:89
 RooProduct.cxx:90
 RooProduct.cxx:91
 RooProduct.cxx:92
 RooProduct.cxx:93
 RooProduct.cxx:94
 RooProduct.cxx:95
 RooProduct.cxx:96
 RooProduct.cxx:97
 RooProduct.cxx:98
 RooProduct.cxx:99
 RooProduct.cxx:100
 RooProduct.cxx:101
 RooProduct.cxx:102
 RooProduct.cxx:103
 RooProduct.cxx:104
 RooProduct.cxx:105
 RooProduct.cxx:106
 RooProduct.cxx:107
 RooProduct.cxx:108
 RooProduct.cxx:109
 RooProduct.cxx:110
 RooProduct.cxx:111
 RooProduct.cxx:112
 RooProduct.cxx:113
 RooProduct.cxx:114
 RooProduct.cxx:115
 RooProduct.cxx:116
 RooProduct.cxx:117
 RooProduct.cxx:118
 RooProduct.cxx:119
 RooProduct.cxx:120
 RooProduct.cxx:121
 RooProduct.cxx:122
 RooProduct.cxx:123
 RooProduct.cxx:124
 RooProduct.cxx:125
 RooProduct.cxx:126
 RooProduct.cxx:127
 RooProduct.cxx:128
 RooProduct.cxx:129
 RooProduct.cxx:130
 RooProduct.cxx:131
 RooProduct.cxx:132
 RooProduct.cxx:133
 RooProduct.cxx:134
 RooProduct.cxx:135
 RooProduct.cxx:136
 RooProduct.cxx:137
 RooProduct.cxx:138
 RooProduct.cxx:139
 RooProduct.cxx:140
 RooProduct.cxx:141
 RooProduct.cxx:142
 RooProduct.cxx:143
 RooProduct.cxx:144
 RooProduct.cxx:145
 RooProduct.cxx:146
 RooProduct.cxx:147
 RooProduct.cxx:148
 RooProduct.cxx:149
 RooProduct.cxx:150
 RooProduct.cxx:151
 RooProduct.cxx:152
 RooProduct.cxx:153
 RooProduct.cxx:154
 RooProduct.cxx:155
 RooProduct.cxx:156
 RooProduct.cxx:157
 RooProduct.cxx:158
 RooProduct.cxx:159
 RooProduct.cxx:160
 RooProduct.cxx:161
 RooProduct.cxx:162
 RooProduct.cxx:163
 RooProduct.cxx:164
 RooProduct.cxx:165
 RooProduct.cxx:166
 RooProduct.cxx:167
 RooProduct.cxx:168
 RooProduct.cxx:169
 RooProduct.cxx:170
 RooProduct.cxx:171
 RooProduct.cxx:172
 RooProduct.cxx:173
 RooProduct.cxx:174
 RooProduct.cxx:175
 RooProduct.cxx:176
 RooProduct.cxx:177
 RooProduct.cxx:178
 RooProduct.cxx:179
 RooProduct.cxx:180
 RooProduct.cxx:181
 RooProduct.cxx:182
 RooProduct.cxx:183
 RooProduct.cxx:184
 RooProduct.cxx:185
 RooProduct.cxx:186
 RooProduct.cxx:187
 RooProduct.cxx:188
 RooProduct.cxx:189
 RooProduct.cxx:190
 RooProduct.cxx:191
 RooProduct.cxx:192
 RooProduct.cxx:193
 RooProduct.cxx:194
 RooProduct.cxx:195
 RooProduct.cxx:196
 RooProduct.cxx:197
 RooProduct.cxx:198
 RooProduct.cxx:199
 RooProduct.cxx:200
 RooProduct.cxx:201
 RooProduct.cxx:202
 RooProduct.cxx:203
 RooProduct.cxx:204
 RooProduct.cxx:205
 RooProduct.cxx:206
 RooProduct.cxx:207
 RooProduct.cxx:208
 RooProduct.cxx:209
 RooProduct.cxx:210
 RooProduct.cxx:211
 RooProduct.cxx:212
 RooProduct.cxx:213
 RooProduct.cxx:214
 RooProduct.cxx:215
 RooProduct.cxx:216
 RooProduct.cxx:217
 RooProduct.cxx:218
 RooProduct.cxx:219
 RooProduct.cxx:220
 RooProduct.cxx:221
 RooProduct.cxx:222
 RooProduct.cxx:223
 RooProduct.cxx:224
 RooProduct.cxx:225
 RooProduct.cxx:226
 RooProduct.cxx:227
 RooProduct.cxx:228
 RooProduct.cxx:229
 RooProduct.cxx:230
 RooProduct.cxx:231
 RooProduct.cxx:232
 RooProduct.cxx:233
 RooProduct.cxx:234
 RooProduct.cxx:235
 RooProduct.cxx:236
 RooProduct.cxx:237
 RooProduct.cxx:238
 RooProduct.cxx:239
 RooProduct.cxx:240
 RooProduct.cxx:241
 RooProduct.cxx:242
 RooProduct.cxx:243
 RooProduct.cxx:244
 RooProduct.cxx:245
 RooProduct.cxx:246
 RooProduct.cxx:247
 RooProduct.cxx:248
 RooProduct.cxx:249
 RooProduct.cxx:250
 RooProduct.cxx:251
 RooProduct.cxx:252
 RooProduct.cxx:253
 RooProduct.cxx:254
 RooProduct.cxx:255
 RooProduct.cxx:256
 RooProduct.cxx:257
 RooProduct.cxx:258
 RooProduct.cxx:259
 RooProduct.cxx:260
 RooProduct.cxx:261
 RooProduct.cxx:262
 RooProduct.cxx:263
 RooProduct.cxx:264
 RooProduct.cxx:265
 RooProduct.cxx:266
 RooProduct.cxx:267
 RooProduct.cxx:268
 RooProduct.cxx:269
 RooProduct.cxx:270
 RooProduct.cxx:271
 RooProduct.cxx:272
 RooProduct.cxx:273
 RooProduct.cxx:274
 RooProduct.cxx:275
 RooProduct.cxx:276
 RooProduct.cxx:277
 RooProduct.cxx:278
 RooProduct.cxx:279
 RooProduct.cxx:280
 RooProduct.cxx:281
 RooProduct.cxx:282
 RooProduct.cxx:283
 RooProduct.cxx:284
 RooProduct.cxx:285
 RooProduct.cxx:286
 RooProduct.cxx:287
 RooProduct.cxx:288
 RooProduct.cxx:289
 RooProduct.cxx:290
 RooProduct.cxx:291
 RooProduct.cxx:292
 RooProduct.cxx:293
 RooProduct.cxx:294
 RooProduct.cxx:295
 RooProduct.cxx:296
 RooProduct.cxx:297
 RooProduct.cxx:298
 RooProduct.cxx:299
 RooProduct.cxx:300
 RooProduct.cxx:301
 RooProduct.cxx:302
 RooProduct.cxx:303
 RooProduct.cxx:304
 RooProduct.cxx:305
 RooProduct.cxx:306
 RooProduct.cxx:307
 RooProduct.cxx:308
 RooProduct.cxx:309
 RooProduct.cxx:310
 RooProduct.cxx:311
 RooProduct.cxx:312
 RooProduct.cxx:313
 RooProduct.cxx:314
 RooProduct.cxx:315
 RooProduct.cxx:316
 RooProduct.cxx:317
 RooProduct.cxx:318
 RooProduct.cxx:319
 RooProduct.cxx:320
 RooProduct.cxx:321
 RooProduct.cxx:322
 RooProduct.cxx:323
 RooProduct.cxx:324
 RooProduct.cxx:325
 RooProduct.cxx:326
 RooProduct.cxx:327
 RooProduct.cxx:328
 RooProduct.cxx:329
 RooProduct.cxx:330
 RooProduct.cxx:331
 RooProduct.cxx:332
 RooProduct.cxx:333
 RooProduct.cxx:334
 RooProduct.cxx:335
 RooProduct.cxx:336
 RooProduct.cxx:337
 RooProduct.cxx:338
 RooProduct.cxx:339
 RooProduct.cxx:340
 RooProduct.cxx:341
 RooProduct.cxx:342
 RooProduct.cxx:343
 RooProduct.cxx:344
 RooProduct.cxx:345
 RooProduct.cxx:346
 RooProduct.cxx:347
 RooProduct.cxx:348
 RooProduct.cxx:349
 RooProduct.cxx:350
 RooProduct.cxx:351
 RooProduct.cxx:352
 RooProduct.cxx:353
 RooProduct.cxx:354
 RooProduct.cxx:355
 RooProduct.cxx:356
 RooProduct.cxx:357
 RooProduct.cxx:358
 RooProduct.cxx:359
 RooProduct.cxx:360
 RooProduct.cxx:361
 RooProduct.cxx:362
 RooProduct.cxx:363
 RooProduct.cxx:364
 RooProduct.cxx:365
 RooProduct.cxx:366
 RooProduct.cxx:367
 RooProduct.cxx:368
 RooProduct.cxx:369
 RooProduct.cxx:370
 RooProduct.cxx:371
 RooProduct.cxx:372
 RooProduct.cxx:373
 RooProduct.cxx:374
 RooProduct.cxx:375
 RooProduct.cxx:376
 RooProduct.cxx:377
 RooProduct.cxx:378
 RooProduct.cxx:379
 RooProduct.cxx:380
 RooProduct.cxx:381
 RooProduct.cxx:382
 RooProduct.cxx:383
 RooProduct.cxx:384
 RooProduct.cxx:385
 RooProduct.cxx:386
 RooProduct.cxx:387
 RooProduct.cxx:388
 RooProduct.cxx:389
 RooProduct.cxx:390
 RooProduct.cxx:391
 RooProduct.cxx:392
 RooProduct.cxx:393
 RooProduct.cxx:394
 RooProduct.cxx:395
 RooProduct.cxx:396
 RooProduct.cxx:397
 RooProduct.cxx:398
 RooProduct.cxx:399
 RooProduct.cxx:400
 RooProduct.cxx:401
 RooProduct.cxx:402
 RooProduct.cxx:403
 RooProduct.cxx:404
 RooProduct.cxx:405
 RooProduct.cxx:406
 RooProduct.cxx:407
 RooProduct.cxx:408
 RooProduct.cxx:409
 RooProduct.cxx:410
 RooProduct.cxx:411
 RooProduct.cxx:412
 RooProduct.cxx:413
 RooProduct.cxx:414
 RooProduct.cxx:415
 RooProduct.cxx:416
 RooProduct.cxx:417
 RooProduct.cxx:418
 RooProduct.cxx:419
 RooProduct.cxx:420
 RooProduct.cxx:421
 RooProduct.cxx:422
 RooProduct.cxx:423
 RooProduct.cxx:424
 RooProduct.cxx:425
 RooProduct.cxx:426
 RooProduct.cxx:427
 RooProduct.cxx:428
 RooProduct.cxx:429
 RooProduct.cxx:430
 RooProduct.cxx:431
 RooProduct.cxx:432
 RooProduct.cxx:433
 RooProduct.cxx:434
 RooProduct.cxx:435
 RooProduct.cxx:436
 RooProduct.cxx:437
 RooProduct.cxx:438
 RooProduct.cxx:439
 RooProduct.cxx:440
 RooProduct.cxx:441
 RooProduct.cxx:442
 RooProduct.cxx:443
 RooProduct.cxx:444
 RooProduct.cxx:445
 RooProduct.cxx:446
 RooProduct.cxx:447
 RooProduct.cxx:448
 RooProduct.cxx:449
 RooProduct.cxx:450
 RooProduct.cxx:451
 RooProduct.cxx:452
 RooProduct.cxx:453
 RooProduct.cxx:454
 RooProduct.cxx:455
 RooProduct.cxx:456
 RooProduct.cxx:457
 RooProduct.cxx:458
 RooProduct.cxx:459
 RooProduct.cxx:460
 RooProduct.cxx:461
 RooProduct.cxx:462
 RooProduct.cxx:463
 RooProduct.cxx:464
 RooProduct.cxx:465
 RooProduct.cxx:466
 RooProduct.cxx:467
 RooProduct.cxx:468
 RooProduct.cxx:469
 RooProduct.cxx:470
 RooProduct.cxx:471
 RooProduct.cxx:472
 RooProduct.cxx:473
 RooProduct.cxx:474
 RooProduct.cxx:475
 RooProduct.cxx:476
 RooProduct.cxx:477
 RooProduct.cxx:478
 RooProduct.cxx:479
 RooProduct.cxx:480
 RooProduct.cxx:481
 RooProduct.cxx:482
 RooProduct.cxx:483
 RooProduct.cxx:484
 RooProduct.cxx:485
 RooProduct.cxx:486
 RooProduct.cxx:487
 RooProduct.cxx:488
 RooProduct.cxx:489
 RooProduct.cxx:490
 RooProduct.cxx:491
 RooProduct.cxx:492
 RooProduct.cxx:493
 RooProduct.cxx:494
 RooProduct.cxx:495
 RooProduct.cxx:496
 RooProduct.cxx:497
 RooProduct.cxx:498
 RooProduct.cxx:499
 RooProduct.cxx:500
 RooProduct.cxx:501
 RooProduct.cxx:502
 RooProduct.cxx:503
 RooProduct.cxx:504
 RooProduct.cxx:505
 RooProduct.cxx:506
 RooProduct.cxx:507
 RooProduct.cxx:508
 RooProduct.cxx:509
 RooProduct.cxx:510
 RooProduct.cxx:511
 RooProduct.cxx:512
 RooProduct.cxx:513
 RooProduct.cxx:514
 RooProduct.cxx:515
 RooProduct.cxx:516
 RooProduct.cxx:517
 RooProduct.cxx:518
 RooProduct.cxx:519
 RooProduct.cxx:520
 RooProduct.cxx:521
 RooProduct.cxx:522
 RooProduct.cxx:523
 RooProduct.cxx:524
 RooProduct.cxx:525
 RooProduct.cxx:526
 RooProduct.cxx:527
 RooProduct.cxx:528
 RooProduct.cxx:529
 RooProduct.cxx:530
 RooProduct.cxx:531
 RooProduct.cxx:532
 RooProduct.cxx:533
 RooProduct.cxx:534
 RooProduct.cxx:535
 RooProduct.cxx:536
 RooProduct.cxx:537
 RooProduct.cxx:538
 RooProduct.cxx:539
 RooProduct.cxx:540
 RooProduct.cxx:541
 RooProduct.cxx:542
 RooProduct.cxx:543
 RooProduct.cxx:544
 RooProduct.cxx:545
 RooProduct.cxx:546
 RooProduct.cxx:547
 RooProduct.cxx:548
 RooProduct.cxx:549
 RooProduct.cxx:550
 RooProduct.cxx:551
 RooProduct.cxx:552
 RooProduct.cxx:553
 RooProduct.cxx:554