// @(#)root/mathmore:$Id$
// Author: L. Moneta Wed Sep  6 09:52:26 2006

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

// Header file for class WrappedTFunction

#ifndef ROOT_Math_WrappedMultiTF1
#define ROOT_Math_WrappedMultiTF1


#ifndef ROOT_Math_IParamFunction
#include "Math/IParamFunction.h"
#endif

#ifndef ROOT_TF1
#include "TF1.h"
#endif

namespace ROOT {

   namespace Math {


/**
   Class to Wrap a ROOT Function class (like TF1)  in a IParamMultiFunction interface
   of multi-dimensions to be used in the ROOT::Math numerical algorithm
   This wrapper class does not own the TF1 pointer, so it assumes it exists during the wrapper lifetime.
   The class copy the TF1 pointer only when it owns it 

   The class from ROOT version 6.03 does not contain anymore a copy of the parameters. The parameters are 
   stored in the TF1 class.    

   @ingroup CppFunctions
*/

//LM note: are there any issues when cloning the class for the parameters that are not copied anymore ??      

class WrappedMultiTF1 : public ROOT::Math::IParamMultiGradFunction {

public:

   typedef  ROOT::Math::IParamMultiGradFunction        BaseParamFunc;
   typedef  ROOT::Math::IParamMultiFunction::BaseFunc  BaseFunc;


   /**
      constructor from a function pointer to a TF1
      If dim = 0 dimension is taken from TF1::GetNdim().
      IN case of multi-dimensional function created using directly TF1 object the dimension
      returned by TF1::GetNdim is always 1. The user must then pass the correct value of dim
   */
   WrappedMultiTF1 (TF1 & f, unsigned int dim = 0 );

   /**
      Destructor (no operations). Function pointer is not owned
   */
   virtual ~WrappedMultiTF1 () { if (fOwnFunc && fFunc) delete fFunc; }

   /**
      Copy constructor
   */
   WrappedMultiTF1(const WrappedMultiTF1 & rhs);

   /**
      Assignment operator
   */
   WrappedMultiTF1 & operator = (const WrappedMultiTF1 & rhs);


   /** @name interface inherited from IFunction */

   /**
       Clone the wrapper but not the original function
   */
   IMultiGenFunction * Clone() const {
      return new WrappedMultiTF1(*this);
   }

   /// function dimension
   unsigned int NDim() const {
      return fDim;
   }


   /** @name interface inherited from IParamFunction */

   /// get the parameter values (return values from TF1)
   const double * Parameters() const {
  //return  (fParams.size() > 0) ? &fParams.front() : 0;
      return  fFunc->GetParameters();
   }

   /// set parameter values (only the cached one in this class,leave unchanges those of TF1)
   void SetParameters(const double * p) { 
      //std::copy(p,p+fParams.size(),fParams.begin());
      fFunc->SetParameters(p); 
   } 

   /// return number of parameters
   unsigned int NPar() const {
      // return fParams.size();
      return fFunc->GetNpar(); 
   }

   /// return parameter name (from TF1)
   std::string ParameterName(unsigned int i) const {
      return std::string(fFunc->GetParName(i));
   }


   /// evaluate the derivative of the function with respect to the parameters
   void  ParameterGradient(const double * x, const double * par, double * grad ) const;

   /// precision value used for calculating the derivative step-size
   /// h = eps * |x|. The default is 0.001, give a smaller in case function changes rapidly
   static void SetDerivPrecision(double eps);

   /// get precision value used for calculating the derivative step-size
   static double GetDerivPrecision();

   /// method to retrieve the internal function pointer
   const TF1 * GetFunction() const { return fFunc; }

   /// method to set a new function pointer and copy it inside. 
   /// By calling this method the class manages now the passed TF1 pointer
   void SetAndCopyFunction(const TF1 * f = 0);
   
   

private:

   /// evaluate function passing coordinates x and vector of parameters
   double DoEvalPar (const double * x, const double * p ) const {
      if (fFunc->GetMethodCall() )  fFunc->InitArgs(x,p);  // needed for interpreted functions
      return fFunc->EvalPar(x,p);
   }

   /// evaluate function using the cached parameter values (of TF1)
   /// re-implement for better efficiency
   double DoEval (const double* x) const { 
      // no need to call InitArg for interpreted functions (done in ctor)

      //const double * p = (fParams.size() > 0) ? &fParams.front() : 0;
      return fFunc->EvalPar(x, 0 ); 
   }


   /// evaluate the partial derivative with respect to the parameter
   double DoParameterDerivative(const double * x, const double * p, unsigned int ipar) const;


   bool fLinear;                 // flag for linear functions
   bool fPolynomial;             // flag for polynomial functions
   bool fOwnFunc;                 // flag to indicate we own the TF1 function pointer
   TF1 * fFunc;                   // pointer to ROOT function
   unsigned int fDim;             // cached value of dimension
   //std::vector<double> fParams;   // cached vector with parameter values

   static double fgEps;          // epsilon used in derivative calculation h ~ eps |p|
};

   } // end namespace Fit

} // end namespace ROOT


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