// @(#)root/mathcore:$Id$
// Authors: L. Moneta    11/2006

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

// Header file for function interfaces
//
// Generic Interfaces for one or  multi-dimensional functions
//
// Created by: Lorenzo Moneta  : Wed Nov 13 2006
//
//
#ifndef ROOT_Math_IFunction
#define ROOT_Math_IFunction

/**
@defgroup CppFunctions Function Classes and Interfaces

 Interfaces (abstract classes) and Base classes used in MathCore and MathMore numerical methods
 for describing function classes. They define function and gradient evaluation and as well the
 functionality for dealing with parameters in the case of parametric functions which are used for
 fitting and data modeling.
 Included are also adapter classes, such as  functors, to wrap generic callable C++ objects
 in the desired interface.
*/

//typedefs and tags definitions
#ifndef ROOT_Math_IFunctionfwd
#include "Math/IFunctionfwd.h"
#endif


namespace ROOT {
namespace Math {

/**
   @defgroup GenFunc Interfaces for generic function evaluation
   @ingroup CppFunctions
*/

//___________________________________________________________________________________
   /**
       Documentation for the abstract class IBaseFunctionMultiDim.
       Interface (abstract class) for generic functions objects of multi-dimension
       Provides a method to evaluate the function given a vector of coordinate values,
       by implementing operator() (const double *).
       In addition it defines the interface for copying functions via the pure virtual method Clone()
       and the interface for getting the function dimension via the NDim() method.
       Derived classes must implement the pure private virtual method DoEval(const double *) for the
       function evaluation in addition to NDim() and Clone().

       @ingroup  GenFunc
   */

   class IBaseFunctionMultiDim {

   public:

      typedef  IBaseFunctionMultiDim BaseFunc;


      IBaseFunctionMultiDim() {}

      /**
         virtual destructor
       */
      virtual ~IBaseFunctionMultiDim() {}

      /**
          Clone a function.
          Each derived class must implement their version of the Clone method
      */
      virtual IBaseFunctionMultiDim * Clone() const = 0;

      /**
         Retrieve the dimension of the function
       */
      virtual unsigned int NDim() const = 0;

      /**
          Evaluate the function at a point x[].
          Use the pure virtual private method DoEval which must be implemented by the sub-classes
      */
      double operator() (const double* x) const {
         return DoEval(x);
      }

#ifdef LATER
      /**
         Template method to eveluate the function using the begin of an iterator
         User is responsible to provide correct size for the iterator
      */
      template <class Iterator>
      double operator() (const Iterator it ) const {
         return DoEval( &(*it) );
      }
#endif


   private:


      /**
         Implementation of the evaluation function. Must be implemented by derived classes
      */
      virtual double DoEval(const double * x) const = 0;


  };


//___________________________________________________________________________________
   /**
       Interface (abstract class) for generic functions objects of one-dimension
       Provides a method to evaluate the function given a value (simple double)
       by implementing operator() (const double ).
       In addition it defines the interface for copying functions via the pure virtual method Clone().
       Derived classes must implement the pure virtual private method DoEval(double ) for the
       function evaluation in addition to  Clone().
       An interface for evaluating the function passing a vector (like for multidim functions) is also
       provided

       @ingroup  GenFunc
   */
   class IBaseFunctionOneDim {

   public:

      typedef  IBaseFunctionOneDim BaseFunc;

      IBaseFunctionOneDim() {}

      /**
         virtual destructor
       */
      virtual ~IBaseFunctionOneDim() {}

      /**
          Clone a function.
          Each derived class will implement their version of the provate DoClone method
      */
      virtual IBaseFunctionOneDim * Clone() const = 0;

      /**
          Evaluate the function at a point x
          Use the  a pure virtual private method DoEval which must be implemented by sub-classes
      */
      double operator() (double x) const {
         return DoEval(x);
      }

      /**
          Evaluate the function at a point x[].
          Compatible method with multi-dimensional functions
      */
      double operator() (const double * x) const {
         return DoEval(*x);
      }



   private:

      // use private virtual inheritance

      /// implementation of the evaluation function. Must be implemented by derived classes
      virtual double DoEval(double x) const = 0;

   };


//-------- GRAD  functions---------------------------

//___________________________________________________________________________________
   /**
      Gradient interface (abstract class) defining the signature for calculating the gradient of a
      multi-dimensional function.
      Three methods are provided:
      - Gradient(const double *x, double * grad) evaluate the full gradient vector at the vector value x
      - Derivative(const double * x, int icoord) evaluate the partial derivative for the icoord coordinate
      - FdF(const double *x, double &f, double * g) evaluate at the same time gradient and function/

      Concrete classes should derive from ROOT::Math::IGradientFunctionMultiDim and not from this class.

      @ingroup  GenFunc
    */

   class IGradientMultiDim {

      public:

      /// virual destructor
      virtual ~IGradientMultiDim() {}

      /**
          Evaluate all the vector of function derivatives (gradient)  at a point x.
          Derived classes must re-implement if it is more efficient than evaluting one at a time
      */
      virtual void  Gradient(const double *x, double * grad) const = 0;

      /**
         Return the partial derivative with respect to the passed coordinate
      */
      double Derivative(const double * x, unsigned int icoord = 0) const  {
         return DoDerivative(x, icoord);
      }


      /**
          Optimized method to evaluate at the same time the function value and derivative at a point x.
          Often both value and derivatives are needed and it is often more efficient to compute them at the same time.
          Derived class should implement this method if performances play an important role and if it is faster to
          evaluate value and derivative at the same time

      */
      virtual void FdF (const double * x, double & f, double * df) const  = 0;


   private:


      /**
         function to evaluate the derivative with respect each coordinate. To be implemented by the derived class
      */
      virtual  double  DoDerivative(const double * x, unsigned int icoord ) const = 0;

   };

//___________________________________________________________________________________
   /**
      Specialized Gradient interface(abstract class)  for one dimensional functions
      It provides a method to evaluate the derivative of the function, Derivative and a
      method to evaluate at the same time the function and the derivative FdF

      Concrete classes should derive from ROOT::Math::IGradientFunctionOneDim and not from this class.

      @ingroup  GenFunc
    */
   class IGradientOneDim {

   public:

      /// virtual destructor
      virtual ~IGradientOneDim() {}

      /**
         Return the derivative of the function at a point x
         Use the private method DoDerivative
      */
      double Derivative(double x ) const  {
         return DoDerivative(x );
      }


      /**
          Optimized method to evaluate at the same time the function value and derivative at a point x.
          Often both value and derivatives are needed and it is often more efficient to compute them at the same time.
          Derived class should implement this method if performances play an important role and if it is faster to
          evaluate value and derivative at the same time

      */
      virtual void FdF (double x, double & f, double & df) const = 0;


      /**
         Compatibility method with multi-dimensional interface for partial derivative
       */
      double Derivative(const double * x) const  {
         return DoDerivative( *x);
      }

      /**
         Compatibility method with multi-dimensional interface for Gradient
       */
      void Gradient(const double * x, double *g) const  {
         g[0] = DoDerivative( *x);
      }

      /**
         Compatibility method with multi-dimensional interface for Gradient and function evaluation
       */
      void FdF(const double * x, double & f, double * df) const  {
         FdF(*x, f, *df);
      }



   private:


      /**
         function to evaluate the derivative with respect each coordinate. To be implemented by the derived class
      */
      virtual  double  DoDerivative(double x ) const = 0;

   };

//___________________________________________________________________________________
/**
   Interface (abstract class) for multi-dimensional functions providing a gradient calculation.
   It implements both the ROOT::Math::IBaseFunctionMultiDim and
   ROOT::Math::IGradientMultiDim interfaces.
   The method ROOT::Math::IFunction::Gradient calculates the full gradient vector,
   ROOT::Math::IFunction::Derivative calculates the partial derivative for each coordinate and
   ROOT::Math::Fdf calculates the gradient and the function value at the same time.
   The pure private virtual method DoDerivative() must be implemented by the derived classes, while
   Gradient and FdF are by default implemented using DoDerivative, butthey  can be overloaded by the
   derived classes to improve the efficiency in the derivative calculation.

   @ingroup  GenFunc
*/


   class IGradientFunctionMultiDim :
      virtual public IBaseFunctionMultiDim ,
      public IGradientMultiDim {


   public:

      typedef IBaseFunctionMultiDim BaseFunc;
      typedef IGradientMultiDim BaseGrad;


      /**
          Virtual Destructor (no operations)
      */
      virtual ~IGradientFunctionMultiDim () {}

      /**
          Evaluate all the vector of function derivatives (gradient)  at a point x.
          Derived classes must re-implement it if more efficient than evaluting one at a time
      */
      virtual void  Gradient(const double *x, double * grad) const {
         unsigned int ndim = NDim();
         for (unsigned int icoord  = 0; icoord < ndim; ++icoord)
            grad[icoord] = BaseGrad::Derivative(x,icoord);
      }

      using  BaseFunc::NDim;


      /**
          Optimized method to evaluate at the same time the function value and derivative at a point x.
          Often both value and derivatives are needed and it is often more efficient to compute them at the same time.
          Derived class should implement this method if performances play an important role and if it is faster to
          evaluate value and derivative at the same time

      */
      virtual void FdF (const double * x, double & f, double * df) const {
         f = BaseFunc::operator()(x);
         Gradient(x,df);
      }


   };


//___________________________________________________________________________________
/**
   Interface (abstract class) for one-dimensional functions providing a gradient calculation.
   It implements both the ROOT::Math::IBaseFunctionOneDim and
   ROOT::Math::IGradientOneDim interfaces.
   The method  ROOT::Math::IFunction::Derivative calculates the derivative  and
   ROOT::Math::Fdf calculates the derivative and the function values at the same time.
   The pure private virtual method DoDerivative() must be implemented by the derived classes, while
   FdF is by default implemented using DoDerivative, but it can be overloaded by the
   derived classes to improve the efficiency in the derivative calculation.


   @ingroup  GenFunc
*/
   //template <>
   class IGradientFunctionOneDim :
      virtual public IBaseFunctionOneDim ,
      public IGradientOneDim {


   public:

      typedef IBaseFunctionOneDim BaseFunc;
      typedef IGradientOneDim BaseGrad;


      /**
          Virtual Destructor (no operations)
      */
      virtual ~IGradientFunctionOneDim () {}


      /**
          Optimized method to evaluate at the same time the function value and derivative at a point x.
           Often both value and derivatives are needed and it is often more efficient to compute them at the same time.
          Derived class should implement this method if performances play an important role and if it is faster to
          evaluate value and derivative at the same time

      */
      virtual void FdF (double x, double & f, double & df) const {
         f = operator()(x);
         df = Derivative(x);
      }



   };



} // namespace Math
} // namespace ROOT

#endif /* ROOT_Math_IGenFunction */
 IFunction.h:1
 IFunction.h:2
 IFunction.h:3
 IFunction.h:4
 IFunction.h:5
 IFunction.h:6
 IFunction.h:7
 IFunction.h:8
 IFunction.h:9
 IFunction.h:10
 IFunction.h:11
 IFunction.h:12
 IFunction.h:13
 IFunction.h:14
 IFunction.h:15
 IFunction.h:16
 IFunction.h:17
 IFunction.h:18
 IFunction.h:19
 IFunction.h:20
 IFunction.h:21
 IFunction.h:22
 IFunction.h:23
 IFunction.h:24
 IFunction.h:25
 IFunction.h:26
 IFunction.h:27
 IFunction.h:28
 IFunction.h:29
 IFunction.h:30
 IFunction.h:31
 IFunction.h:32
 IFunction.h:33
 IFunction.h:34
 IFunction.h:35
 IFunction.h:36
 IFunction.h:37
 IFunction.h:38
 IFunction.h:39
 IFunction.h:40
 IFunction.h:41
 IFunction.h:42
 IFunction.h:43
 IFunction.h:44
 IFunction.h:45
 IFunction.h:46
 IFunction.h:47
 IFunction.h:48
 IFunction.h:49
 IFunction.h:50
 IFunction.h:51
 IFunction.h:52
 IFunction.h:53
 IFunction.h:54
 IFunction.h:55
 IFunction.h:56
 IFunction.h:57
 IFunction.h:58
 IFunction.h:59
 IFunction.h:60
 IFunction.h:61
 IFunction.h:62
 IFunction.h:63
 IFunction.h:64
 IFunction.h:65
 IFunction.h:66
 IFunction.h:67
 IFunction.h:68
 IFunction.h:69
 IFunction.h:70
 IFunction.h:71
 IFunction.h:72
 IFunction.h:73
 IFunction.h:74
 IFunction.h:75
 IFunction.h:76
 IFunction.h:77
 IFunction.h:78
 IFunction.h:79
 IFunction.h:80
 IFunction.h:81
 IFunction.h:82
 IFunction.h:83
 IFunction.h:84
 IFunction.h:85
 IFunction.h:86
 IFunction.h:87
 IFunction.h:88
 IFunction.h:89
 IFunction.h:90
 IFunction.h:91
 IFunction.h:92
 IFunction.h:93
 IFunction.h:94
 IFunction.h:95
 IFunction.h:96
 IFunction.h:97
 IFunction.h:98
 IFunction.h:99
 IFunction.h:100
 IFunction.h:101
 IFunction.h:102
 IFunction.h:103
 IFunction.h:104
 IFunction.h:105
 IFunction.h:106
 IFunction.h:107
 IFunction.h:108
 IFunction.h:109
 IFunction.h:110
 IFunction.h:111
 IFunction.h:112
 IFunction.h:113
 IFunction.h:114
 IFunction.h:115
 IFunction.h:116
 IFunction.h:117
 IFunction.h:118
 IFunction.h:119
 IFunction.h:120
 IFunction.h:121
 IFunction.h:122
 IFunction.h:123
 IFunction.h:124
 IFunction.h:125
 IFunction.h:126
 IFunction.h:127
 IFunction.h:128
 IFunction.h:129
 IFunction.h:130
 IFunction.h:131
 IFunction.h:132
 IFunction.h:133
 IFunction.h:134
 IFunction.h:135
 IFunction.h:136
 IFunction.h:137
 IFunction.h:138
 IFunction.h:139
 IFunction.h:140
 IFunction.h:141
 IFunction.h:142
 IFunction.h:143
 IFunction.h:144
 IFunction.h:145
 IFunction.h:146
 IFunction.h:147
 IFunction.h:148
 IFunction.h:149
 IFunction.h:150
 IFunction.h:151
 IFunction.h:152
 IFunction.h:153
 IFunction.h:154
 IFunction.h:155
 IFunction.h:156
 IFunction.h:157
 IFunction.h:158
 IFunction.h:159
 IFunction.h:160
 IFunction.h:161
 IFunction.h:162
 IFunction.h:163
 IFunction.h:164
 IFunction.h:165
 IFunction.h:166
 IFunction.h:167
 IFunction.h:168
 IFunction.h:169
 IFunction.h:170
 IFunction.h:171
 IFunction.h:172
 IFunction.h:173
 IFunction.h:174
 IFunction.h:175
 IFunction.h:176
 IFunction.h:177
 IFunction.h:178
 IFunction.h:179
 IFunction.h:180
 IFunction.h:181
 IFunction.h:182
 IFunction.h:183
 IFunction.h:184
 IFunction.h:185
 IFunction.h:186
 IFunction.h:187
 IFunction.h:188
 IFunction.h:189
 IFunction.h:190
 IFunction.h:191
 IFunction.h:192
 IFunction.h:193
 IFunction.h:194
 IFunction.h:195
 IFunction.h:196
 IFunction.h:197
 IFunction.h:198
 IFunction.h:199
 IFunction.h:200
 IFunction.h:201
 IFunction.h:202
 IFunction.h:203
 IFunction.h:204
 IFunction.h:205
 IFunction.h:206
 IFunction.h:207
 IFunction.h:208
 IFunction.h:209
 IFunction.h:210
 IFunction.h:211
 IFunction.h:212
 IFunction.h:213
 IFunction.h:214
 IFunction.h:215
 IFunction.h:216
 IFunction.h:217
 IFunction.h:218
 IFunction.h:219
 IFunction.h:220
 IFunction.h:221
 IFunction.h:222
 IFunction.h:223
 IFunction.h:224
 IFunction.h:225
 IFunction.h:226
 IFunction.h:227
 IFunction.h:228
 IFunction.h:229
 IFunction.h:230
 IFunction.h:231
 IFunction.h:232
 IFunction.h:233
 IFunction.h:234
 IFunction.h:235
 IFunction.h:236
 IFunction.h:237
 IFunction.h:238
 IFunction.h:239
 IFunction.h:240
 IFunction.h:241
 IFunction.h:242
 IFunction.h:243
 IFunction.h:244
 IFunction.h:245
 IFunction.h:246
 IFunction.h:247
 IFunction.h:248
 IFunction.h:249
 IFunction.h:250
 IFunction.h:251
 IFunction.h:252
 IFunction.h:253
 IFunction.h:254
 IFunction.h:255
 IFunction.h:256
 IFunction.h:257
 IFunction.h:258
 IFunction.h:259
 IFunction.h:260
 IFunction.h:261
 IFunction.h:262
 IFunction.h:263
 IFunction.h:264
 IFunction.h:265
 IFunction.h:266
 IFunction.h:267
 IFunction.h:268
 IFunction.h:269
 IFunction.h:270
 IFunction.h:271
 IFunction.h:272
 IFunction.h:273
 IFunction.h:274
 IFunction.h:275
 IFunction.h:276
 IFunction.h:277
 IFunction.h:278
 IFunction.h:279
 IFunction.h:280
 IFunction.h:281
 IFunction.h:282
 IFunction.h:283
 IFunction.h:284
 IFunction.h:285
 IFunction.h:286
 IFunction.h:287
 IFunction.h:288
 IFunction.h:289
 IFunction.h:290
 IFunction.h:291
 IFunction.h:292
 IFunction.h:293
 IFunction.h:294
 IFunction.h:295
 IFunction.h:296
 IFunction.h:297
 IFunction.h:298
 IFunction.h:299
 IFunction.h:300
 IFunction.h:301
 IFunction.h:302
 IFunction.h:303
 IFunction.h:304
 IFunction.h:305
 IFunction.h:306
 IFunction.h:307
 IFunction.h:308
 IFunction.h:309
 IFunction.h:310
 IFunction.h:311
 IFunction.h:312
 IFunction.h:313
 IFunction.h:314
 IFunction.h:315
 IFunction.h:316
 IFunction.h:317
 IFunction.h:318
 IFunction.h:319
 IFunction.h:320
 IFunction.h:321
 IFunction.h:322
 IFunction.h:323
 IFunction.h:324
 IFunction.h:325
 IFunction.h:326
 IFunction.h:327
 IFunction.h:328
 IFunction.h:329
 IFunction.h:330
 IFunction.h:331
 IFunction.h:332
 IFunction.h:333
 IFunction.h:334
 IFunction.h:335
 IFunction.h:336
 IFunction.h:337
 IFunction.h:338
 IFunction.h:339
 IFunction.h:340
 IFunction.h:341
 IFunction.h:342
 IFunction.h:343
 IFunction.h:344
 IFunction.h:345
 IFunction.h:346
 IFunction.h:347
 IFunction.h:348
 IFunction.h:349
 IFunction.h:350
 IFunction.h:351
 IFunction.h:352
 IFunction.h:353
 IFunction.h:354
 IFunction.h:355
 IFunction.h:356
 IFunction.h:357
 IFunction.h:358
 IFunction.h:359
 IFunction.h:360
 IFunction.h:361
 IFunction.h:362
 IFunction.h:363
 IFunction.h:364
 IFunction.h:365
 IFunction.h:366
 IFunction.h:367
 IFunction.h:368
 IFunction.h:369
 IFunction.h:370
 IFunction.h:371
 IFunction.h:372
 IFunction.h:373
 IFunction.h:374
 IFunction.h:375
 IFunction.h:376
 IFunction.h:377
 IFunction.h:378
 IFunction.h:379
 IFunction.h:380
 IFunction.h:381
 IFunction.h:382
 IFunction.h:383
 IFunction.h:384
 IFunction.h:385
 IFunction.h:386
 IFunction.h:387
 IFunction.h:388
 IFunction.h:389
 IFunction.h:390
 IFunction.h:391
 IFunction.h:392
 IFunction.h:393
 IFunction.h:394
 IFunction.h:395
 IFunction.h:396
 IFunction.h:397
 IFunction.h:398
 IFunction.h:399
 IFunction.h:400
 IFunction.h:401
 IFunction.h:402
 IFunction.h:403
 IFunction.h:404
 IFunction.h:405
 IFunction.h:406
 IFunction.h:407
 IFunction.h:408
 IFunction.h:409
 IFunction.h:410
 IFunction.h:411
 IFunction.h:412
 IFunction.h:413
 IFunction.h:414
 IFunction.h:415
 IFunction.h:416
 IFunction.h:417