/*****************************************************************************
 * 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
// RooNumGenFactory is a factory to instantiate numeric integrators
// from a given function binding and a given configuration. The factory
// searches for a numeric integrator registered with the factory that
// has the ability to perform the numeric integration. The choice of
// method may depend on the number of dimensions integrated,
// the nature of the integration limits (closed or open ended) and
// the preference of the caller as encoded in the configuration object.
// END_HTML
//

#include "TClass.h"
#include "Riostream.h"

#include "RooFit.h"

#include "RooNumGenFactory.h"
#include "RooArgSet.h"
#include "RooAbsFunc.h"
#include "RooNumGenConfig.h"
#include "RooNumber.h"

#include "RooAcceptReject.h"
#include "RooFoamGenerator.h"
#include "RooSentinel.h"


#include "RooMsgService.h"

using namespace std ;

ClassImp(RooNumGenFactory)
;

RooNumGenFactory* RooNumGenFactory::_instance = 0 ;



//_____________________________________________________________________________
RooNumGenFactory::RooNumGenFactory()
{
  // Constructor. Register all known integrators by calling
  // their static registration functions

  _instance = this ;

  RooAcceptReject::registerSampler(*this) ;
  RooFoamGenerator::registerSampler(*this) ;

  // Prepare default
  RooNumGenConfig::defaultConfig().method1D(kFALSE,kFALSE).setLabel("RooFoamGenerator") ;
  RooNumGenConfig::defaultConfig().method1D(kTRUE ,kFALSE).setLabel("RooAcceptReject") ;
  RooNumGenConfig::defaultConfig().method1D(kFALSE,kTRUE ).setLabel("RooAcceptReject") ;
  RooNumGenConfig::defaultConfig().method1D(kTRUE, kTRUE ).setLabel("RooAcceptReject") ;
  
  RooNumGenConfig::defaultConfig().method2D(kFALSE,kFALSE).setLabel("RooFoamGenerator") ;
  RooNumGenConfig::defaultConfig().method2D(kTRUE ,kFALSE).setLabel("RooAcceptReject") ;
  RooNumGenConfig::defaultConfig().method2D(kFALSE,kTRUE ).setLabel("RooAcceptReject") ;
  RooNumGenConfig::defaultConfig().method2D(kTRUE, kTRUE ).setLabel("RooAcceptReject") ;
  
  RooNumGenConfig::defaultConfig().methodND(kFALSE,kFALSE).setLabel("RooFoamGenerator") ;
  RooNumGenConfig::defaultConfig().methodND(kTRUE ,kFALSE).setLabel("RooAcceptReject") ;
  RooNumGenConfig::defaultConfig().methodND(kFALSE,kTRUE ).setLabel("RooAcceptReject") ;
  RooNumGenConfig::defaultConfig().methodND(kTRUE, kTRUE ).setLabel("RooAcceptReject") ;
  
}



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

  std::map<std::string,RooAbsNumGenerator*>::iterator iter = _map.begin() ;
  while (iter != _map.end()) {
    delete iter->second ;
    ++iter ;
  }  
}


//_____________________________________________________________________________
RooNumGenFactory::RooNumGenFactory(const RooNumGenFactory& other) : TObject(other)
{
  // Copy constructor
}



//_____________________________________________________________________________
RooNumGenFactory& RooNumGenFactory::instance()
{
  // Static method returning reference to singleton instance of factory

  if (_instance==0) {
    new RooNumGenFactory ;
    RooSentinel::activate() ;
  } 
  return *_instance ;
}


//_____________________________________________________________________________
void RooNumGenFactory::cleanup()
{
  // Cleanup routine called by atexit() handler installed by RooSentinel

  if (_instance) {
    delete _instance ;
    _instance = 0 ;
  }
}



//_____________________________________________________________________________
Bool_t RooNumGenFactory::storeProtoSampler(RooAbsNumGenerator* proto, const RooArgSet& defConfig) 
{
  // Method accepting registration of a prototype numeric integrator along with a RooArgSet of its
  // default configuration options and an optional list of names of other numeric integrators
  // on which this integrator depends. Returns true if integrator was previously registered

  TString name = proto->IsA()->GetName() ;

  if (getProtoSampler(name)) {
    //cout << "RooNumGenFactory::storeSampler() ERROR: integrator '" << name << "' already registered" << endl ;
    return kTRUE ;
  }

  // Add to factory 
  _map[name.Data()] = proto ;

  // Add default config to master config
  RooNumGenConfig::defaultConfig().addConfigSection(proto,defConfig) ;
  
  return kFALSE ;
}



//_____________________________________________________________________________
const RooAbsNumGenerator* RooNumGenFactory::getProtoSampler(const char* name) 
{
  // Return prototype integrator with given (class) name

  if (_map.count(name)==0) {
    return 0 ;
  } 
  
  return _map[name] ;
}



//_____________________________________________________________________________
RooAbsNumGenerator* RooNumGenFactory::createSampler(RooAbsReal& func, const RooArgSet& genVars, const RooArgSet& condVars, const RooNumGenConfig& config, Bool_t verbose, RooAbsReal* maxFuncVal) 
{
  // Construct a numeric integrator instance that operates on function 'func' and is configured
  // with 'config'. If ndimPreset is greater than zero that number is taken as the dimensionality
  // of the integration, otherwise it is queried from 'func'. This function iterators over list
  // of available prototype integrators and returns an clone attached to the given function of
  // the first class that matches the specifications of the requested integration considering
  // the number of dimensions, the nature of the limits (open ended vs closed) and the user
  // preference stated in 'config'

  // Find method defined configuration
  Int_t ndim = genVars.getSize() ;
  Bool_t cond = (condVars.getSize() > 0) ? kTRUE : kFALSE ;

  Bool_t hasCat(kFALSE) ;
  TIterator* iter = genVars.createIterator() ;
  RooAbsArg* arg ;
  while ((arg=(RooAbsArg*)iter->Next())) {
    if (arg->IsA()==RooCategory::Class()) {
      hasCat=kTRUE ;
      break ;
    }
  }
  delete iter ;


  TString method ;
  switch(ndim) {
  case 1:
    method = config.method1D(cond,hasCat).getLabel() ;
    break ;

  case 2:
    method = config.method2D(cond,hasCat).getLabel() ;
    break ;

  default:
    method = config.methodND(cond,hasCat).getLabel() ;
    break ;
  }

  // Check that a method was defined for this case
  if (!method.CompareTo("N/A")) {
    oocoutE((TObject*)0,Integration) << "RooNumGenFactory::createSampler: No sampler method has been defined for " 
				     << (cond?"a conditional ":"a ") << ndim << "-dimensional p.d.f" << endl ;
    return 0 ;    
  }

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