/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitCore                                                       *
 * @(#)root/roofitcore:$Id$
 * Authors:                                                                  *
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
 *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
 *                                                                           *
 * Copyright (c) 2000-2005, 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
// Class RooAbsNumGenerator is the abstract base class for MC event generator
// implementations like RooAcceptReject and RooFoam
// END_HTML
//


#include "RooFit.h"
#include "Riostream.h"

#include "RooAbsNumGenerator.h"
#include "RooAbsReal.h"
#include "RooCategory.h"
#include "RooRealVar.h"
#include "RooDataSet.h"
#include "RooRandom.h"
#include "RooErrorHandler.h"

#include "TString.h"
#include "TIterator.h"
#include "RooMsgService.h"
#include "TClass.h"
#include "RooRealBinding.h"

#include <assert.h>

using namespace std;

ClassImp(RooAbsNumGenerator)
  ;


//_____________________________________________________________________________
RooAbsNumGenerator::RooAbsNumGenerator(const RooAbsReal &func, const RooArgSet &genVars, Bool_t verbose, const RooAbsReal* maxFuncVal) :
  TNamed(func), _cloneSet(0), _funcClone(0), _funcMaxVal(maxFuncVal), _verbose(verbose), _funcValStore(0), _funcValPtr(0), _cache(0)
{
  // Initialize an accept-reject generator for the specified distribution function,
  // which must be non-negative but does not need to be normalized over the
  // variables to be generated, genVars. The function and its dependents are
  // cloned and so will not be disturbed during the generation process.

  // Clone the function and all nodes that it depends on so that this generator
  // is independent of any existing objects.
  RooArgSet nodes(func,func.GetName());
  _cloneSet= (RooArgSet*) nodes.snapshot(kTRUE);
  if (!_cloneSet) {
    coutE(Generation) << "RooAbsNumGenerator::RooAbsNumGenerator(" << GetName() << ") Couldn't deep-clone function, abort," << endl ;
    RooErrorHandler::softAbort() ;
  }

  // Find the clone in the snapshot list
  _funcClone = (RooAbsReal*)_cloneSet->find(func.GetName());


  // Check that each argument is fundamental, and separate them into
  // sets of categories and reals. Check that the area of the generating
  // space is finite.
  _isValid= kTRUE;
  TIterator *iterator= genVars.createIterator();
  const RooAbsArg *found = 0;
  const RooAbsArg *arg   = 0;
  while((arg= (const RooAbsArg*)iterator->Next())) {
    if(!arg->isFundamental()) {
      coutE(Generation) << fName << "::" << ClassName() << ": cannot generate values for derived \""
			<< arg->GetName() << "\"" << endl;
      _isValid= kFALSE;
      continue;
    }
    // look for this argument in the generating function's dependents
    found= (const RooAbsArg*)_cloneSet->find(arg->GetName());
    if(found) {
      arg= found;
    } else {
      // clone any variables we generate that we haven't cloned already
      arg= _cloneSet->addClone(*arg);
    }
    assert(0 != arg);
    // is this argument a category or a real?
    const RooCategory *catVar= dynamic_cast<const RooCategory*>(arg);
    const RooRealVar *realVar= dynamic_cast<const RooRealVar*>(arg);
    if(0 != catVar) {
      _catVars.add(*catVar);
    }
    else if(0 != realVar) {
      if(realVar->hasMin() && realVar->hasMax()) {
	_realVars.add(*realVar);
      }
      else {
	coutE(Generation) << fName << "::" << ClassName() << ": cannot generate values for \""
			  << realVar->GetName() << "\" with unbound range" << endl;
	_isValid= kFALSE;
      }
    }
    else {
      coutE(Generation) << fName << "::" << ClassName() << ": cannot generate values for \""
			<< arg->GetName() << "\" with unexpected type" << endl;
      _isValid= kFALSE;
    }
  }
  delete iterator;
  if(!_isValid) {
    coutE(Generation) << fName << "::" << ClassName() << ": constructor failed with errors" << endl;
    return;
  }

  // create a fundamental type for storing function values
  _funcValStore= dynamic_cast<RooRealVar*>(_funcClone->createFundamental());
  assert(0 != _funcValStore);

  // create a new dataset to cache trial events and function values
  RooArgSet cacheArgs(_catVars);
  cacheArgs.add(_realVars);
  cacheArgs.add(*_funcValStore);
  _cache= new RooDataSet("cache","Accept-Reject Event Cache",cacheArgs);
  assert(0 != _cache);

  // attach our function clone to the cache dataset
  const RooArgSet *cacheVars= _cache->get();
  assert(0 != cacheVars);
  _funcClone->recursiveRedirectServers(*cacheVars,kFALSE);

  // update ours sets of category and real args to refer to the cache dataset
  const RooArgSet *dataVars= _cache->get();
  _catVars.replace(*dataVars);
  _realVars.replace(*dataVars);

  // find the function value in the dataset
  _funcValPtr= (RooRealVar*)dataVars->find(_funcValStore->GetName());

}



//_____________________________________________________________________________
RooAbsNumGenerator::~RooAbsNumGenerator() 
{
  // Destructor
  delete _cloneSet;
  delete _cache ;
  delete _funcValStore ;
}



//_____________________________________________________________________________
void RooAbsNumGenerator::attachParameters(const RooArgSet& vars) 
{
  // Reattach original parameters to function clone

  RooArgSet newParams(vars) ;
  newParams.remove(*_cache->get(),kTRUE,kTRUE) ;
  _funcClone->recursiveRedirectServers(newParams) ;
}





//_____________________________________________________________________________
void RooAbsNumGenerator::printName(ostream& os) const 
{
  // Print name of the generator

  os << GetName() ;
}



//_____________________________________________________________________________
void RooAbsNumGenerator::printTitle(ostream& os) const 
{
  // Print the title of the generator

  os << GetTitle() ;
}



//_____________________________________________________________________________
void RooAbsNumGenerator::printClassName(ostream& os) const 
{
  // Print the class name of the generator

  os << IsA()->GetName() ;
}



//_____________________________________________________________________________
void RooAbsNumGenerator::printArgs(ostream& os) const 
{
  // Print the arguments of the generator

  os << "[ function=" << _funcClone->GetName() << " catobs=" << _catVars << " realobs=" << _realVars << " ]" ;
}

 RooAbsNumGenerator.cxx:1
 RooAbsNumGenerator.cxx:2
 RooAbsNumGenerator.cxx:3
 RooAbsNumGenerator.cxx:4
 RooAbsNumGenerator.cxx:5
 RooAbsNumGenerator.cxx:6
 RooAbsNumGenerator.cxx:7
 RooAbsNumGenerator.cxx:8
 RooAbsNumGenerator.cxx:9
 RooAbsNumGenerator.cxx:10
 RooAbsNumGenerator.cxx:11
 RooAbsNumGenerator.cxx:12
 RooAbsNumGenerator.cxx:13
 RooAbsNumGenerator.cxx:14
 RooAbsNumGenerator.cxx:15
 RooAbsNumGenerator.cxx:16
 RooAbsNumGenerator.cxx:17
 RooAbsNumGenerator.cxx:18
 RooAbsNumGenerator.cxx:19
 RooAbsNumGenerator.cxx:20
 RooAbsNumGenerator.cxx:21
 RooAbsNumGenerator.cxx:22
 RooAbsNumGenerator.cxx:23
 RooAbsNumGenerator.cxx:24
 RooAbsNumGenerator.cxx:25
 RooAbsNumGenerator.cxx:26
 RooAbsNumGenerator.cxx:27
 RooAbsNumGenerator.cxx:28
 RooAbsNumGenerator.cxx:29
 RooAbsNumGenerator.cxx:30
 RooAbsNumGenerator.cxx:31
 RooAbsNumGenerator.cxx:32
 RooAbsNumGenerator.cxx:33
 RooAbsNumGenerator.cxx:34
 RooAbsNumGenerator.cxx:35
 RooAbsNumGenerator.cxx:36
 RooAbsNumGenerator.cxx:37
 RooAbsNumGenerator.cxx:38
 RooAbsNumGenerator.cxx:39
 RooAbsNumGenerator.cxx:40
 RooAbsNumGenerator.cxx:41
 RooAbsNumGenerator.cxx:42
 RooAbsNumGenerator.cxx:43
 RooAbsNumGenerator.cxx:44
 RooAbsNumGenerator.cxx:45
 RooAbsNumGenerator.cxx:46
 RooAbsNumGenerator.cxx:47
 RooAbsNumGenerator.cxx:48
 RooAbsNumGenerator.cxx:49
 RooAbsNumGenerator.cxx:50
 RooAbsNumGenerator.cxx:51
 RooAbsNumGenerator.cxx:52
 RooAbsNumGenerator.cxx:53
 RooAbsNumGenerator.cxx:54
 RooAbsNumGenerator.cxx:55
 RooAbsNumGenerator.cxx:56
 RooAbsNumGenerator.cxx:57
 RooAbsNumGenerator.cxx:58
 RooAbsNumGenerator.cxx:59
 RooAbsNumGenerator.cxx:60
 RooAbsNumGenerator.cxx:61
 RooAbsNumGenerator.cxx:62
 RooAbsNumGenerator.cxx:63
 RooAbsNumGenerator.cxx:64
 RooAbsNumGenerator.cxx:65
 RooAbsNumGenerator.cxx:66
 RooAbsNumGenerator.cxx:67
 RooAbsNumGenerator.cxx:68
 RooAbsNumGenerator.cxx:69
 RooAbsNumGenerator.cxx:70
 RooAbsNumGenerator.cxx:71
 RooAbsNumGenerator.cxx:72
 RooAbsNumGenerator.cxx:73
 RooAbsNumGenerator.cxx:74
 RooAbsNumGenerator.cxx:75
 RooAbsNumGenerator.cxx:76
 RooAbsNumGenerator.cxx:77
 RooAbsNumGenerator.cxx:78
 RooAbsNumGenerator.cxx:79
 RooAbsNumGenerator.cxx:80
 RooAbsNumGenerator.cxx:81
 RooAbsNumGenerator.cxx:82
 RooAbsNumGenerator.cxx:83
 RooAbsNumGenerator.cxx:84
 RooAbsNumGenerator.cxx:85
 RooAbsNumGenerator.cxx:86
 RooAbsNumGenerator.cxx:87
 RooAbsNumGenerator.cxx:88
 RooAbsNumGenerator.cxx:89
 RooAbsNumGenerator.cxx:90
 RooAbsNumGenerator.cxx:91
 RooAbsNumGenerator.cxx:92
 RooAbsNumGenerator.cxx:93
 RooAbsNumGenerator.cxx:94
 RooAbsNumGenerator.cxx:95
 RooAbsNumGenerator.cxx:96
 RooAbsNumGenerator.cxx:97
 RooAbsNumGenerator.cxx:98
 RooAbsNumGenerator.cxx:99
 RooAbsNumGenerator.cxx:100
 RooAbsNumGenerator.cxx:101
 RooAbsNumGenerator.cxx:102
 RooAbsNumGenerator.cxx:103
 RooAbsNumGenerator.cxx:104
 RooAbsNumGenerator.cxx:105
 RooAbsNumGenerator.cxx:106
 RooAbsNumGenerator.cxx:107
 RooAbsNumGenerator.cxx:108
 RooAbsNumGenerator.cxx:109
 RooAbsNumGenerator.cxx:110
 RooAbsNumGenerator.cxx:111
 RooAbsNumGenerator.cxx:112
 RooAbsNumGenerator.cxx:113
 RooAbsNumGenerator.cxx:114
 RooAbsNumGenerator.cxx:115
 RooAbsNumGenerator.cxx:116
 RooAbsNumGenerator.cxx:117
 RooAbsNumGenerator.cxx:118
 RooAbsNumGenerator.cxx:119
 RooAbsNumGenerator.cxx:120
 RooAbsNumGenerator.cxx:121
 RooAbsNumGenerator.cxx:122
 RooAbsNumGenerator.cxx:123
 RooAbsNumGenerator.cxx:124
 RooAbsNumGenerator.cxx:125
 RooAbsNumGenerator.cxx:126
 RooAbsNumGenerator.cxx:127
 RooAbsNumGenerator.cxx:128
 RooAbsNumGenerator.cxx:129
 RooAbsNumGenerator.cxx:130
 RooAbsNumGenerator.cxx:131
 RooAbsNumGenerator.cxx:132
 RooAbsNumGenerator.cxx:133
 RooAbsNumGenerator.cxx:134
 RooAbsNumGenerator.cxx:135
 RooAbsNumGenerator.cxx:136
 RooAbsNumGenerator.cxx:137
 RooAbsNumGenerator.cxx:138
 RooAbsNumGenerator.cxx:139
 RooAbsNumGenerator.cxx:140
 RooAbsNumGenerator.cxx:141
 RooAbsNumGenerator.cxx:142
 RooAbsNumGenerator.cxx:143
 RooAbsNumGenerator.cxx:144
 RooAbsNumGenerator.cxx:145
 RooAbsNumGenerator.cxx:146
 RooAbsNumGenerator.cxx:147
 RooAbsNumGenerator.cxx:148
 RooAbsNumGenerator.cxx:149
 RooAbsNumGenerator.cxx:150
 RooAbsNumGenerator.cxx:151
 RooAbsNumGenerator.cxx:152
 RooAbsNumGenerator.cxx:153
 RooAbsNumGenerator.cxx:154
 RooAbsNumGenerator.cxx:155
 RooAbsNumGenerator.cxx:156
 RooAbsNumGenerator.cxx:157
 RooAbsNumGenerator.cxx:158
 RooAbsNumGenerator.cxx:159
 RooAbsNumGenerator.cxx:160
 RooAbsNumGenerator.cxx:161
 RooAbsNumGenerator.cxx:162
 RooAbsNumGenerator.cxx:163
 RooAbsNumGenerator.cxx:164
 RooAbsNumGenerator.cxx:165
 RooAbsNumGenerator.cxx:166
 RooAbsNumGenerator.cxx:167
 RooAbsNumGenerator.cxx:168
 RooAbsNumGenerator.cxx:169
 RooAbsNumGenerator.cxx:170
 RooAbsNumGenerator.cxx:171
 RooAbsNumGenerator.cxx:172
 RooAbsNumGenerator.cxx:173
 RooAbsNumGenerator.cxx:174
 RooAbsNumGenerator.cxx:175
 RooAbsNumGenerator.cxx:176
 RooAbsNumGenerator.cxx:177
 RooAbsNumGenerator.cxx:178
 RooAbsNumGenerator.cxx:179
 RooAbsNumGenerator.cxx:180
 RooAbsNumGenerator.cxx:181
 RooAbsNumGenerator.cxx:182
 RooAbsNumGenerator.cxx:183
 RooAbsNumGenerator.cxx:184
 RooAbsNumGenerator.cxx:185
 RooAbsNumGenerator.cxx:186
 RooAbsNumGenerator.cxx:187
 RooAbsNumGenerator.cxx:188
 RooAbsNumGenerator.cxx:189
 RooAbsNumGenerator.cxx:190
 RooAbsNumGenerator.cxx:191
 RooAbsNumGenerator.cxx:192
 RooAbsNumGenerator.cxx:193
 RooAbsNumGenerator.cxx:194
 RooAbsNumGenerator.cxx:195
 RooAbsNumGenerator.cxx:196
 RooAbsNumGenerator.cxx:197
 RooAbsNumGenerator.cxx:198
 RooAbsNumGenerator.cxx:199
 RooAbsNumGenerator.cxx:200
 RooAbsNumGenerator.cxx:201
 RooAbsNumGenerator.cxx:202
 RooAbsNumGenerator.cxx:203
 RooAbsNumGenerator.cxx:204
 RooAbsNumGenerator.cxx:205
 RooAbsNumGenerator.cxx:206
 RooAbsNumGenerator.cxx:207
 RooAbsNumGenerator.cxx:208
 RooAbsNumGenerator.cxx:209
 RooAbsNumGenerator.cxx:210
 RooAbsNumGenerator.cxx:211
 RooAbsNumGenerator.cxx:212
 RooAbsNumGenerator.cxx:213
 RooAbsNumGenerator.cxx:214