/*****************************************************************************
 * 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
// RooAdaptiveIntegratorND implements an adaptive one-dimensional 
// numerical integration algorithm.
// END_HTML
//


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

#include "TClass.h"
#include "RooAdaptiveIntegratorND.h"
#include "RooArgSet.h"
#include "RooRealVar.h"
#include "RooNumber.h"
#include "RooMsgService.h"
#include "RooNumIntFactory.h"
#include "RooMultiGenFunction.h"
#include "Math/AdaptiveIntegratorMultiDim.h"

#include <assert.h>
#include <iomanip>



using namespace std;

ClassImp(RooAdaptiveIntegratorND)
;

// Register this class with RooNumIntConfig

//_____________________________________________________________________________
void RooAdaptiveIntegratorND::registerIntegrator(RooNumIntFactory& fact)
{
  // Register RooAdaptiveIntegratorND, its parameters, dependencies and capabilities with RooNumIntFactory

  RooRealVar maxEval2D("maxEval2D","Max number of function evaluations for 2-dim integrals",100000) ;
  RooRealVar maxEval3D("maxEval3D","Max number of function evaluations for 3-dim integrals",1000000) ;
  RooRealVar maxEvalND("maxEvalND","Max number of function evaluations for >3-dim integrals",10000000) ;
  RooRealVar maxWarn("maxWarn","Max number of warnings on precision not reached that is printed",5) ;

  fact.storeProtoIntegrator(new RooAdaptiveIntegratorND(),RooArgSet(maxEval2D,maxEval3D,maxEvalND,maxWarn)) ;
}
 


//_____________________________________________________________________________
RooAdaptiveIntegratorND::RooAdaptiveIntegratorND()
{
  // Default ctor
  _xmin = 0 ;
  _xmax = 0 ;
  _epsRel = 1e-7 ;
  _epsAbs = 1e-7 ;
  _nmax = 10000 ;
  _func = 0 ;
  _integrator = 0 ;
  _nError = 0 ;
  _nWarn = 0 ;
  _useIntegrandLimits = kTRUE ;
  _intName = "(none)" ;
}



//_____________________________________________________________________________
RooAdaptiveIntegratorND::RooAdaptiveIntegratorND(const RooAbsFunc& function, const RooNumIntConfig& config) :
  RooAbsIntegrator(function)
{
  // Constructor of integral on given function binding and with given configuration. The
  // integration limits are taken from the definition in the function binding
  //_func = function.


  _func = new RooMultiGenFunction(function) ;  
  _nWarn = static_cast<Int_t>(config.getConfigSection("RooAdaptiveIntegratorND").getRealValue("maxWarn")) ;
  switch (_func->NDim()) {
  case 1: throw string(Form("RooAdaptiveIntegratorND::ctor ERROR dimension of function must be at least 2")) ;
  case 2: _nmax = static_cast<Int_t>(config.getConfigSection("RooAdaptiveIntegratorND").getRealValue("maxEval2D")) ; break ; 
  case 3: _nmax = static_cast<Int_t>(config.getConfigSection("RooAdaptiveIntegratorND").getRealValue("maxEval3D")) ; break ;
  default: _nmax = static_cast<Int_t>(config.getConfigSection("RooAdaptiveIntegratorND").getRealValue("maxEvalND")) ; break ;
  }
  _integrator = new ROOT::Math::AdaptiveIntegratorMultiDim(config.epsAbs(),config.epsRel(),_nmax) ;
  _integrator->SetFunction(*_func) ;
  _useIntegrandLimits=kTRUE ;

  _xmin = 0 ;
  _xmax = 0 ;
  _nError = 0 ;
  _nWarn = 0 ;
  _epsRel = 1e-7 ;
  _epsAbs = 1e-7 ;
  checkLimits() ;
  _intName = function.getName() ;
} 



//_____________________________________________________________________________
RooAbsIntegrator* RooAdaptiveIntegratorND::clone(const RooAbsFunc& function, const RooNumIntConfig& config) const
{
  // Virtual constructor with given function and configuration. Needed by RooNumIntFactory

  RooAbsIntegrator* ret = new RooAdaptiveIntegratorND(function,config) ;
  
  return ret ;
}




//_____________________________________________________________________________
RooAdaptiveIntegratorND::~RooAdaptiveIntegratorND()
{
  // Destructor
  delete[] _xmin ;
  delete[] _xmax ;
  delete _integrator ;
  delete _func ;
  if (_nError>_nWarn) {
    coutW(NumIntegration) << "RooAdaptiveIntegratorND::dtor(" << _intName 
			  << ") WARNING: Number of suppressed warningings about integral evaluations where target precision was not reached is " << _nError-_nWarn << endl ;
  }

}



//_____________________________________________________________________________
Bool_t RooAdaptiveIntegratorND::checkLimits() const 
{
  // Check that our integration range is finite and otherwise return kFALSE.
  // Update the limits from the integrand if requested.
  
  if (!_xmin) {
    _xmin = new Double_t[_func->NDim()] ;
    _xmax = new Double_t[_func->NDim()] ;
  }
  
  if (_useIntegrandLimits) {
    for (UInt_t i=0 ; i<_func->NDim() ; i++) {
      _xmin[i]= integrand()->getMinLimit(i);
      _xmax[i]= integrand()->getMaxLimit(i);
    }
  }

  return kTRUE ;
}


//_____________________________________________________________________________
Bool_t RooAdaptiveIntegratorND::setLimits(Double_t *xmin, Double_t *xmax) 
{
  // Change our integration limits. Return kTRUE if the new limits are
  // ok, or otherwise kFALSE. Always returns kFALSE and does nothing
  // if this object was constructed to always use our integrand's limits.

  if(_useIntegrandLimits) {
    oocoutE((TObject*)0,Integration) << "RooAdaptiveIntegratorND::setLimits: cannot override integrand's limits" << endl;
    return kFALSE;
  }
  for (UInt_t i=0 ; i<_func->NDim() ; i++) {
    _xmin[i]= xmin[i];
    _xmax[i]= xmax[i];
  }

  return checkLimits();
}




//_____________________________________________________________________________
Double_t RooAdaptiveIntegratorND::integral(const Double_t* /*yvec*/) 
{
  // Evaluate integral at given function binding parameter values
  Double_t ret = _integrator->Integral(_xmin,_xmax) ;  
  if (_integrator->Status()==1) {
    _nError++ ;
    if (_nError<=_nWarn) {
      coutW(NumIntegration) << "RooAdaptiveIntegratorND::integral(" << integrand()->getName() << ") WARNING: target rel. precision not reached due to nEval limit of "
			    << _nmax << ", estimated rel. precision is " << Form("%3.1e",_integrator->RelError()) << endl ;
    } 
    if (_nError==_nWarn) {
      coutW(NumIntegration) << "RooAdaptiveIntegratorND::integral(" << integrand()->getName() 
			    << ") Further warnings on target precision are suppressed conform specification in integrator specification" << endl ;
    }    
  }  
  return ret ;
}

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