// @(#)root/mathcore:$Id$
// Authors: David Gonzalez Maline    01/2008

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

// Header file for GaussIntegrator
//
// Created by: David Gonzalez Maline  : Wed Jan 16 2008
//

#ifndef ROOT_Math_GaussIntegrator
#define ROOT_Math_GaussIntegrator

#ifndef ROOT_Math_IFunction
#include "Math/IFunction.h"
#endif

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


namespace ROOT {
namespace Math {


//___________________________________________________________________________________________
/**
   User class for performing function integration.

   It will use the Gauss Method for function integration in a given interval.
   This class is implemented from TF1::Integral().

   @ingroup Integration

 */

class GaussIntegrator: public VirtualIntegratorOneDim {


public:

   /** Destructor */
   virtual ~GaussIntegrator();

   /** Default Constructor. */
   GaussIntegrator(double absTol = 0, double relTol = 0);


   /** Static function: set the fgAbsValue flag.
       By default TF1::Integral uses the original function value to compute the integral
       However, TF1::Moment, CentralMoment require to compute the integral
       using the absolute value of the function.
   */
   void AbsValue(bool flag);


   // Implementing VirtualIntegrator Interface

   /** Set the desired relative Error. */
   virtual void SetRelTolerance (double eps) { fEpsRel = eps; }

   /** This method is not implemented. */
   virtual void SetAbsTolerance (double eps) { fEpsAbs = eps; }

   /** Returns the result of the last Integral calculation. */
   double Result () const;

   /** Return the estimate of the absolute Error of the last Integral calculation. */
   double Error () const;

   /** return the status of the last integration - 0 in case of success */
   int Status () const;

   // Implementing VirtualIntegratorOneDim Interface

   /**
     Returns Integral of function between a and b.
     Based on original CERNLIB routine DGAUSS by Sigfried Kolbig
     converted to C++ by Rene Brun

     This function computes, to an attempted specified accuracy, the value
     of the integral.

    Method:
       For any interval [a,b] we define g8(a,b) and g16(a,b) to be the 8-point
       and 16-point Gaussian quadrature approximations to
   Begin_Latex
      I = #int^{b}_{a} f(x)dx
   End_Latex
      and define
   Begin_Latex
      r(a,b) = #frac{#||{g_{16}(a,b)-g_{8}(a,b)}}{1+#||{g_{16}(a,b)}}
   End_Latex
      Then,
   Begin_Latex
      G = #sum_{i=1}^{k}g_{16}(x_{i-1},x_{i})
   End_Latex
      where, starting with x0 = A and finishing with xk = B,
      the subdivision points xi(i=1,2,...) are given by
   Begin_Latex
      x_{i} = x_{i-1} + #lambda(B-x_{i-1})
   End_Latex
   Begin_Latex
      #lambda
   End_Latex
      is equal to the first member of the
      sequence 1,1/2,1/4,... for which r(xi-1, xi) < EPS.
      If, at any stage in the process of subdivision, the ratio
  Begin_Latex
      q = #||{#frac{x_{i}-x_{i-1}}{B-A}}
  End_Latex
      is so small that 1+0.005q is indistinguishable from 1 to
      machine accuracy, an error exit occurs with the function value
      set equal to zero.

   Accuracy:
      The user provides absolute and relative error bounds (epsrel and epsabs) and the
      algorithm will stop when the estimated error is less than the epsabs OR is less
      than |I| * epsrel.
      Unless there is severe cancellation of positive and negative values of
      f(x) over the interval [A,B], the relative error may be considered as
      specifying a bound on the <I>relative</I> error of I in the case
      |I|&gt;1, and a bound on the absolute error in the case |I|&lt;1. More
      precisely, if k is the number of sub-intervals contributing to the
      approximation (see Method), and if
      Begin_Latex
      I_{abs} = #int^{B}_{A} #||{f(x)}dx
      End_Latex
      then the relation
   Begin_Latex
    #frac{#||{G-I}}{I_{abs}+k} < EPS
   End_Latex
      will nearly always be true, provided the routine terminates without
      printing an error message. For functions f having no singularities in
      the closed interval [A,B] the accuracy will usually be much higher than
      this.

    Error handling:
      The requested accuracy cannot be obtained (see Method).
      The function value is set equal to zero.

    Note 1:
      Values of the function f(x) at the interval end-points A and B are not
      required. The subprogram may therefore be used when these values are
      undefined
   */
   double Integral (double a, double b);

   /** Returns Integral of function on an infinite interval.
      This function computes, to an attempted specified accuracy, the value of the integral:
   Begin_Latex
      I = #int^{#infinity}_{-#infinity} f(x)dx
   End_Latex
      Usage:
        In any arithmetic expression, this function has the approximate value
        of the integral I.

      The integral is mapped onto [0,1] using a transformation then integral computation is surrogated to DoIntegral.
   */
   double Integral ();

   /** Returns Integral of function on an upper semi-infinite interval.
      This function computes, to an attempted specified accuracy, the value of the integral:
   Begin_Latex
      I = #int^{#infinity}_{A} f(x)dx
   End_Latex
      Usage:
        In any arithmetic expression, this function has the approximate value
        of the integral I.
        - A: lower end-point of integration interval.

      The integral is mapped onto [0,1] using a transformation then integral computation is surrogated to DoIntegral.
   */
   double IntegralUp (double a);

   /** Returns Integral of function on a lower semi-infinite interval.
       This function computes, to an attempted specified accuracy, the value of the integral:
   Begin_Latex
      I = #int^{B}_{#infinity} f(x)dx
   End_Latex
      Usage:
         In any arithmetic expression, this function has the approximate value
         of the integral I.
         - B: upper end-point of integration interval.

      The integral is mapped onto [0,1] using a transformation then integral computation is surrogated to DoIntegral.
   */
   double IntegralLow (double b);


   /** Set integration function (flag control if function must be copied inside).
       \@param f Function to be used in the calculations.
   */
   void SetFunction (const IGenFunction &);

   /** This method is not implemented. */
   double Integral (const std::vector< double > &pts);

   /** This method is not implemented. */
   double IntegralCauchy (double a, double b, double c);

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

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

private:

   /**
      Integration surrugate method. Return integral of passed function in  interval [a,b]
      Derived class (like GaussLegendreIntegrator)  can re-implement this method to modify to use
      an improved algorithm
   */
   virtual double DoIntegral (double a, double b, const IGenFunction* func);

protected:

   static bool fgAbsValue;          // AbsValue used for the calculation of the integral
   double fEpsRel;                  // Relative error.
   double fEpsAbs;                  // Absolute error.
   bool fUsedOnce;                  // Bool value to check if the function was at least called once.
   double fLastResult;              // Result from the last stimation.
   double fLastError;               // Error from the last stimation.
   const IGenFunction* fFunction;   // Pointer to function used.

};

/**
   Auxillary inner class for mapping infinite and semi-infinite integrals
*/
class IntegrandTransform : public IGenFunction {
public:
   enum ESemiInfinitySign {kMinus = -1, kPlus = +1};
   IntegrandTransform(const IGenFunction* integrand);
   IntegrandTransform(const double boundary, ESemiInfinitySign sign, const IGenFunction* integrand);
   double operator()(double x) const;
   double DoEval(double x) const;
   IGenFunction* Clone() const;
private:
   ESemiInfinitySign fSign;
   const IGenFunction* fIntegrand;
   double fBoundary;
   bool fInfiniteInterval;
   double DoEval(double x, double boundary, int sign) const;
};



} // end namespace Math

} // end namespace ROOT

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