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

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

// Header source file for class AdaptiveIntegratorMultiDim


#ifndef ROOT_Math_AdaptiveIntegratorMultiDim
#define ROOT_Math_AdaptiveIntegratorMultiDim

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

#include "Math/VirtualIntegrator.h"

namespace ROOT {
namespace Math {


//__________________________________________________________________________________________
/**
   class for adaptive quadrature integration in multi-dimensions using rectangular regions.
   Algorithm from  A.C. Genz, A.A. Malik, An adaptive algorithm for numerical integration over
   an N-dimensional rectangular region, J. Comput. Appl. Math. 6 (1980) 295-302.

   Converted/adapted by R.Brun to C++ from Fortran CERNLIB routine RADMUL (D120)
   The new code features many changes compared to the Fortran version.

   Control  parameters are:

       minpts: Minimum number of function evaluations requested. Must not exceed maxpts.
               if minpts < 1 minpts is set to 2^n +2*n*(n+1) +1 where n is the function dimension
      maxpts: Maximum number of function evaluations to be allowed.
              maxpts >= 2^n +2*n*(n+1) +1
              if maxpts<minpts, maxpts is set to 10*minpts
      epstol, epsrel   : Specified relative and  absolute accuracy.

      The integral will stop if the relative error is less than relative tolerance OR the
      absolute error is less than the absolute tolerance

   The class computes in addition to the integral of the function is the desired interval:

       an estimation of the relative accuracy of the result.
       number of function evaluations performed.
       status code  :
          0 Normal exit.  . At least minpts and at most maxpts calls to the function were performed.
          1 maxpts is too small for the specified accuracy eps.
            The result and relerr contain the values obtainable for the
            specified value of maxpts.
          3 n<2 or n>15

   Method:

      An integration rule of degree seven is used together with a certain
      strategy of subdivision.
      For a more detailed description of the method see References.

   Notes:

     1.Multi-dimensional integration is time-consuming. For each rectangular
       subregion, the routine requires function evaluations.
       Careful programming of the integrand might result in substantial saving
       of time.
     2.Numerical integration usually works best for smooth functions.
       Some analysis or suitable transformations of the integral prior to
       numerical work may contribute to numerical efficiency.

   References:

     1.A.C. Genz and A.A. Malik, Remarks on algorithm 006:
       An adaptive algorithm for numerical integration over
       an N-dimensional rectangular region, J. Comput. Appl. Math. 6 (1980) 295-302.
     2.A. van Doren and L. de Ridder, An adaptive algorithm for numerical
       integration over an n-dimensional cube, J.Comput. Appl. Math. 2 (1976) 207-217.


   @ingroup Integration


*/

class AdaptiveIntegratorMultiDim : public VirtualIntegratorMultiDim {

public:

   /**
      construct given optionally tolerance (absolute and relative), maximum number of function evaluation (maxpts)  and
      size of the working array.
      The size of working array represents the number of sub-division used for calculating the integral.
      Higher the dimension, larger sizes are required for getting the same accuracy.
      The size must be larger than  >= (2N + 3) * (1 + MAXPTS/(2**N + 2N(N + 1) + 1))/2). For smaller value passed, the
      minimum allowed will be used
   */
   explicit
   AdaptiveIntegratorMultiDim(double absTol = 1.E-9, double relTol = 1E-9, unsigned int maxpts = 100000, unsigned int size = 0);

   /**
      Construct with a reference to the integrand function and given optionally
      tolerance (absolute and relative), maximum number of function evaluation (maxpts)  and
      size of the working array.
   */
   explicit
   AdaptiveIntegratorMultiDim(const IMultiGenFunction &f, double absTol = 1.E-9, double relTol = 1E-9,  unsigned int maxcall = 100000, unsigned int size = 0);

   /**
      destructor (no operations)
    */
   virtual ~AdaptiveIntegratorMultiDim() {}


   /**
      evaluate the integral with the previously given function between xmin[] and xmax[]
   */
   double Integral(const double* xmin, const double * xmax) {
      return DoIntegral(xmin,xmax, false);
   }


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

   /// set the integration function (must implement multi-dim function interface: IBaseFunctionMultiDim)
   void SetFunction(const IMultiGenFunction &f);

   /// return result of integration
   double Result() const { return fResult; }

   /// return integration error
   double Error() const { return fError; }

   /// return relative error
   double RelError() const { return fRelError; }

   /// return status of integration
   int Status() const { return fStatus; }

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

   /// set relative tolerance
   void SetRelTolerance(double relTol);

   /// set absolute tolerance
   void SetAbsTolerance(double absTol);

   ///set workspace size
   void SetSize(unsigned int size) { fSize = size; }

   ///set min points
   void SetMinPts(unsigned int n) { fMinPts = n; }

   ///set max points
   void SetMaxPts(unsigned int n) { fMaxPts = n; }

   /// set the options
   void SetOptions(const ROOT::Math::IntegratorMultiDimOptions & opt);

   ///  get the option used for the integration
   ROOT::Math::IntegratorMultiDimOptions Options() const;

protected:

   // internal function to compute the integral (if absVal is true compute abs value of function integral
   double DoIntegral(const double* xmin, const double * xmax, bool absVal = false);

 private:

   unsigned int fDim;     // dimentionality of integrand
   unsigned int fMinPts;    // minimum number of function evaluation requested
   unsigned int fMaxPts;    // maximum number of function evaluation requested
   unsigned int fSize;    // max size of working array (explode with dimension)
   double fAbsTol;        // absolute tolerance
   double fRelTol;        // relative tolerance

   double fResult;        // last integration result
   double fError;         // integration error
   double fRelError;      // Relative error
   int    fNEval;        // number of function evaluation
   int fStatus;   // status of algorithm (error if not zero)

   const IMultiGenFunction* fFun;   // pointer to integrand function

};

}//namespace Math
}//namespace ROOT

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