// @(#)root/mathcore:$Id$
// Author: L. Moneta Tue Nov 14 14:20:07 2006

/**********************************************************************
 *                                                                    *
 * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
 *                                                                    *
 *                                                                    *
 **********************************************************************/

// Header file for class IParamFunction

#ifndef ROOT_Math_IParamFunction
#define ROOT_Math_IParamFunction

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

#ifndef ROOT_Math_IParamFunctionfwd
#include "Math/IParamFunctionfwd.h"
#endif

#ifndef ROOT_Math_Util
#include "Math/Util.h"
#endif


#include <cassert> 

/**
   @defgroup ParamFunc Interfaces for parametric functions 
   @ingroup CppFunctions
*/


namespace ROOT { 

namespace Math { 


//___________________________________________________________________
/** 
    Documentation for the abstract class IBaseParam.
    It defines the interface for dealing with the function parameters
    This is used only for internal convinience, to avoid redefining the Parameter API  
    for the one and the multi-dim functions. 
    Concrete class should derive from ROOT::Math::IParamFunction and not from this class.  
    
    @ingroup  ParamFunc
*/ 

class IBaseParam  {

public: 


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


   /**
      Access the parameter values
   */
   virtual const double * Parameters() const = 0;

   /**
      Set the parameter values
      @param p vector of doubles containing the parameter values. 

      to be defined:  can user change number of params ? At the moment no. 

   */
   virtual void SetParameters(const double * p ) = 0;

    
   /**
      Return the number of Parameters
   */
   virtual unsigned int NPar() const = 0; 

   /**
      Return the name of the i-th parameter (starting from zero)
      Overwrite if want to avoid the default name ("Par_0, Par_1, ...") 
    */
   virtual std::string ParameterName(unsigned int i) const { 
      assert(i < NPar() ); 
      return "Par_" + Util::ToString(i);
   }


};

//___________________________________________________________________
/** 
   IParamFunction interface (abstract class) describing multi-dimensional parameteric functions
   It is a derived class from ROOT::Math::IBaseFunctionMultiDim and 
   ROOT::Math::IBaseParam

   Provides the interface for evaluating a function passing a coordinate vector and a parameter vector.  

   @ingroup  ParamFunc
*/ 

class IParametricFunctionMultiDim : 
         virtual public IBaseFunctionMultiDim , 
         public IBaseParam {

public: 

   typedef IBaseFunctionMultiDim  BaseFunc; 



   /**
      Evaluate function at a point x and for given parameters p.
      This method does not change the internal status of the function (internal parameter values). 
      If for some reason one prefers caching the parameter values, SetParameters(p) and then operator()(x) should be 
      called.
      Use the pure virtual function DoEvalPar to implement it
   */
   double operator() (const double * x, const double *  p ) const { 
      return DoEvalPar(x, p); 
   }

   using BaseFunc::operator();


private: 

   /**
      Implementation of the evaluation function using the x values and the parameters. 
      Must be implemented by derived classes
   */
   virtual double DoEvalPar(const double * x, const double * p) const = 0; 

   /**
      Implement the ROOT::Math::IBaseFunctionMultiDim interface DoEval(x) using the cached parameter values
   */
   virtual double DoEval(const double *x) const { 
      return DoEvalPar( x, Parameters() );  
   }

}; 

//___________________________________________________________________
/** 
   Specialized IParamFunction interface (abstract class) for one-dimensional parametric functions
   It is a derived class from ROOT::Math::IBaseFunctionOneDim and 
   ROOT::Math::IBaseParam

   @ingroup  ParamFunc
*/ 

class IParametricFunctionOneDim : 
         virtual public IBaseFunctionOneDim, 
         public IBaseParam { 


public: 

   typedef IBaseFunctionOneDim   BaseFunc; 


   using BaseFunc::operator();

   /**
      Evaluate function at a point x and for given parameters p.
      This method does not change the internal status of the function (internal parameter values). 
      If for some reason one prefers caching the parameter values, SetParameters(p) and then operator()(x) should be 
      called.
      Use the pure virtual function DoEvalPar to implement it
   */
   double operator() ( double x, const double *  p ) const { 
      return DoEvalPar(x, p); 
   }


   /**
      multidim-like interface
   */
   double operator() (const double * x, const double *  p ) const
   { 
      return DoEvalPar(*x, p); 
   }

private:

   /**
      Implementation of the evaluation function using the x value and the parameters. 
      Must be implemented by derived classes
   */
   virtual double DoEvalPar(double x, const double * p) const = 0; 

   /**
      Implement the ROOT::Math::IBaseFunctionOneDim interface DoEval(x) using the cached parameter values
   */
   virtual double DoEval(double x) const { 
      return DoEvalPar( x, Parameters() );  
   }

}; 



//_______________________________________________________________________________
/** 
   Interface (abstract class) for parametric gradient multi-dimensional functions providing 
   in addition to function evaluation with respect to the coordinates 
   also the gradient with respect to the parameters, via the method ParameterGradient. 

   It is a derived class from ROOT::Math::IParametricFunctionMultiDim.

   The pure private virtual method DoParameterGradient must be implemented by the derived classes 
   in addition to those inherited by the base abstract classes. 

   @ingroup  ParamFunc
*/ 

class IParametricGradFunctionMultiDim : 
         public IParametricFunctionMultiDim 
//         ,public IGradientFunctionMultiDim   
{

public: 

   typedef IParametricFunctionMultiDim                BaseParamFunc; 
   typedef IGradientFunctionMultiDim                  BaseGradFunc; 
   typedef IParametricFunctionMultiDim::BaseFunc  BaseFunc; 


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



   using BaseParamFunc::operator();

   /**
      Evaluate the all the derivatives (gradient vector) of the function with respect to the parameters at a point x.
      It is optional to be implemented by the derived classes for better efficiency
   */
   virtual void ParameterGradient(const double * x , const double * p, double * grad ) const { 
      unsigned int npar = NPar(); 
      for (unsigned int ipar  = 0; ipar < npar; ++ipar) 
         grad[ipar] = DoParameterDerivative(x,p,ipar); 
   } 

   /**
      Evaluate the partial derivative w.r.t a parameter ipar from values and parameters
    */
   double ParameterDerivative(const double * x, const double * p, unsigned int ipar = 0) const { 
      return DoParameterDerivative(x, p, ipar); 
   }  

   /**
      Evaluate all derivatives using cached parameter values
   */
   void ParameterGradient(const double * x , double * grad ) const { 
      return ParameterGradient(x, Parameters(), grad); 
   }
   /**
      Evaluate partial derivative using cached parameter values
   */
   double ParameterDerivative(const double * x, unsigned int ipar = 0) const { 
      return DoParameterDerivative(x, Parameters() , ipar); 
   }

private: 



   /**
      Evaluate the partial derivative w.r.t a parameter ipar , to be implemented by the derived classes
    */
   virtual double DoParameterDerivative(const double * x, const double * p, unsigned int ipar) const = 0;  


};

//_______________________________________________________________________________
/** 
   Interface (abstract class) for parametric one-dimensional gradient functions providing 
   in addition to function evaluation with respect the coordinates 
   also the gradient with respect to the parameters, via the method ParameterGradient. 

   It is a derived class from ROOT::Math::IParametricFunctionOneDim.
   
   The pure private virtual method DoParameterGradient must be implemented by the derived classes 
   in addition to those inherited by the base abstract classes. 

   @ingroup  ParamFunc
*/ 

class IParametricGradFunctionOneDim : 
         public IParametricFunctionOneDim
//         ,public IGradientFunctionOneDim
{

public: 

   typedef IParametricFunctionOneDim            BaseParamFunc; 
   typedef IGradientFunctionOneDim              BaseGradFunc; 
   typedef IParametricFunctionOneDim::BaseFunc  BaseFunc; 


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


   using BaseParamFunc::operator();

   /**
      Evaluate the derivatives of the function with respect to the parameters at a point x.
      It is optional to be implemented by the derived classes for better efficiency if needed
   */
   virtual void ParameterGradient(double x , const double * p, double * grad ) const { 
      unsigned int npar = NPar(); 
      for (unsigned int ipar  = 0; ipar < npar; ++ipar) 
         grad[ipar] = DoParameterDerivative(x, p, ipar); 
   } 

   /**
      Evaluate all derivatives using cached parameter values
   */
   void ParameterGradient(double  x , double * grad ) const { 
      return ParameterGradient( x, Parameters(), grad); 
   }

   /**
      Compatibility interface with multi-dimensional functions 
   */
   void ParameterGradient(const double * x , const double * p, double * grad ) const { 
      ParameterGradient(*x, p, grad); 
   } 

   /**
      Evaluate all derivatives using cached parameter values (multi-dim like interface)
   */
   void ParameterGradient(const double * x , double * grad ) const { 
      return ParameterGradient( *x, Parameters(), grad); 
   }


   /**
      Partial derivative with respect a parameter
    */
   double ParameterDerivative(double x, const double * p, unsigned int ipar = 0) const { 
      return DoParameterDerivative(x, p, ipar); 
   }

   /**
      Evaluate partial derivative using cached parameter values
   */
   double ParameterDerivative(double x, unsigned int ipar = 0) const { 
      return DoParameterDerivative(x, Parameters() , ipar); 
   }

   /**
      Partial derivative with respect a parameter
      Compatibility interface with multi-dimensional functions 
   */
   double ParameterDerivative(const double * x, const double * p, unsigned int ipar = 0) const { 
      return DoParameterDerivative(*x, p, ipar); 
   }


   /**
      Evaluate partial derivative using cached parameter values (multi-dim like interface)
   */
   double ParameterDerivative(const double * x, unsigned int ipar = 0) const { 
      return DoParameterDerivative( *x, Parameters() , ipar); 
   }



private: 


   /**
      Evaluate the gradient, to be implemented by the derived classes
    */
   virtual double DoParameterDerivative(double x, const double * p, unsigned int ipar ) const = 0;  


};




   } // end namespace Math

} // end namespace ROOT



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