// @(#)root/mathcore:$Id$
// Authors: M. Slawinska   08/2007

/**********************************************************************
 *                                                                    *
 * Copyright (c) 2007 , LCG ROOT MathLib Team                         *
 *                                                                    *
 *                                                                    *
 **********************************************************************/

// Header source file for class IntegratorMultiDim


#ifndef ROOT_Math_IntegratorMultiDim
#define ROOT_Math_IntegratorMultiDim


#ifndef ROOT_Math_IFunctionfwd
#include "Math/IFunctionfwd.h"
#endif

#ifndef ROOT_Math_IntegrationTypes
#include "Math/AllIntegrationTypes.h"
#endif

#ifndef ROOT_Math_IntegratorOptions
#include "Math/IntegratorOptions.h"
#endif

#ifndef ROOT_Math_VirtualIntegrator
#include "Math/VirtualIntegrator.h"
#endif

#ifndef __CINT__

#ifndef ROOT_Math_WrappedFunction
#include "Math/WrappedFunction.h"
#endif

#endif

#include <memory>

namespace ROOT {
namespace Math {

//___________________________________________________________________________________________
/**
   User class for performing multidimensional integration

   By default uses adaptive multi-dimensional integration using the algorithm from Genz Mallik
   implemented in the class ROOT::Math::AdaptiveIntegratorMultiDim otherwise it can uses via the
   plug-in manager the MC integration class (ROOT::Math::GSLMCIntegration) from MathMore.

   @ingroup Integration


 */

class IntegratorMultiDim {

public:

   typedef IntegrationMultiDim::Type Type;   // for the enumerations defining the types


    /** Generic constructor of multi dimensional Integrator. By default uses the Adaptive integration method

       @param type   integration type (adaptive, MC methods, etc..)
       @param absTol desired absolute Error
       @param relTol desired relative Error
       @param size maximum number of sub-intervals

       In case no parameter  values are passed the default ones used in IntegratorMultiDimOptions are used
    */
   explicit
   IntegratorMultiDim(IntegrationMultiDim::Type type = IntegrationMultiDim::kDEFAULT, double absTol = 0, double relTol = 0, unsigned int ncall = 0) :
      fIntegrator(0), fFunc(0)
   {
       fIntegrator = CreateIntegrator(type, absTol, relTol, ncall);
   }

    /** Generic Constructor of multi dimensional Integrator passing a function. By default uses the adaptive integration method

       @param f      integration function (multi-dim interface)
       @param type   integration type (adaptive, MC methods, etc..)
       @param absTol desired absolute Error
       @param relTol desired relative Error
       @param ncall  number of function calls (apply only to MC integratioon methods)
    */
   explicit
   IntegratorMultiDim(const IMultiGenFunction &f, IntegrationMultiDim::Type type = IntegrationMultiDim::kDEFAULT, double absTol = 0, double relTol = 0, unsigned int ncall = 0) :
      fIntegrator(0), fFunc(0)
   {
      fIntegrator = CreateIntegrator(type, absTol, relTol, ncall);
      SetFunction(f);
   }

   // remove template constructor since is ambigous

    /** Template Constructor of multi dimensional Integrator passing a generic function. By default uses the adaptive integration method

       @param f      integration function (generic function implementin operator()(const double *)
       @param dim    function dimension
       @param type   integration type (adaptive, MC methods, etc..)
       @param absTol desired absolute Error
       @param relTol desired relative Error
       @param ncall  number of function calls (apply only to MC integratioon methods)
    */
// this is ambigous
//    template<class Function>
//    IntegratorMultiDim(Function & f, unsigned int dim, IntegrationMultiDim::Type type = IntegrationMultiDim::kADAPTIVE, double absTol = 1.E-9, double relTol = 1E-6, unsigned int ncall = 100000) {
//       fIntegrator = CreateIntegrator(type, absTol, relTol, ncall);
//       SetFunction(f, dim);
//    }

   /// destructor
   virtual ~IntegratorMultiDim() {
      if (fIntegrator) delete fIntegrator;
   }


   // disable copy constructur and assignment operator

private:
   IntegratorMultiDim(const IntegratorMultiDim &) : fIntegrator(0), fFunc(0) {}
   IntegratorMultiDim & operator=(const IntegratorMultiDim &) { return *this; }

public:


   /**
      evaluate the integral with the previously given function between xmin[] and xmax[]
   */
   double Integral(const double* xmin, const double * xmax) {
      return fIntegrator == 0 ? 0 : fIntegrator->Integral(xmin,xmax);
   }

   /// evaluate the integral passing a new function
   double Integral(const IMultiGenFunction &f, const double* xmin, const double * xmax) {
      SetFunction(f);
      return Integral(xmin,xmax);
   }

   /// evaluate the integral passing a new generic function
   template<class Function>
   double Integral(Function & f , unsigned int dim, const double* xmin, const double * xmax) {
      SetFunction<Function>(f,dim);
      return Integral(xmin, xmax);
   }


   /**
       set integration function using a generic function implementing the operator()(double *x)
       The dimension of the function is in this case required
   */
   template <class Function>
   void SetFunction(Function & f, unsigned int dim) {
      fFunc = std::auto_ptr<IMultiGenFunction>(new  WrappedMultiFunction<Function &> (f, dim) );
      fIntegrator->SetFunction(*fFunc);
   }

   // set the function without cloning it
   void SetFunction(const IMultiGenFunction &f) {
      if (fIntegrator)  fIntegrator->SetFunction(f);
   }

   /// return result of last integration
   double Result() const { return fIntegrator == 0 ? 0 : fIntegrator->Result(); }

   /// return integration error
   double Error() const { return fIntegrator == 0 ? 0 : fIntegrator->Error(); }

   ///  return the Error Status of the last Integral calculation
   int Status() const { return fIntegrator == 0 ? -1 : fIntegrator->Status(); }

   // return number of function evaluations in calculating the integral
   //unsigned int NEval() const { return fNEval; }

   /// set the relative tolerance
   void SetRelTolerance(double relTol) { if (fIntegrator) fIntegrator->SetRelTolerance(relTol); }

   /// set absolute tolerance
   void SetAbsTolerance(double absTol)  { if (fIntegrator) fIntegrator->SetAbsTolerance(absTol); }

   /// set the options
   void SetOptions(const ROOT::Math::IntegratorMultiDimOptions & opt) { if (fIntegrator) fIntegrator->SetOptions(opt); }

   /// retrieve the options
   ROOT::Math::IntegratorMultiDimOptions Options() const { return (fIntegrator) ? fIntegrator->Options() : IntegratorMultiDimOptions(); }

   /// return a pointer to integrator object
   VirtualIntegratorMultiDim * GetIntegrator() { return fIntegrator; }

   /// return name of integrator
   std::string Name() const { return (fIntegrator) ? Options().Integrator() : std::string(""); }

   /// static function to get the enumeration from a string
   static IntegrationMultiDim::Type GetType(const char * name);

   /// static function to get a string from the enumeration
   static std::string GetName(IntegrationMultiDim::Type);

protected:

   VirtualIntegratorMultiDim * CreateIntegrator(IntegrationMultiDim::Type type , double absTol, double relTol, unsigned int ncall);

 private:

   VirtualIntegratorMultiDim * fIntegrator;     // pointer to multi-dimensional integrator base class
   std::auto_ptr<IMultiGenFunction> fFunc;       // pointer to owned function


};

}//namespace Math
}//namespace ROOT

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