// @(#)root/mathcore:$Id$
// Author: L. Moneta Mon Nov 13 15:58:13 2006

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

// Header file for Functor classes.
// design is inspired by the Loki Functor

#ifndef ROOT_Math_ParamFunctor
#define ROOT_Math_ParamFunctor

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

// #ifndef Root_Math_StaticCheck
// #include "Math/StaticCheck.h"
// #endif

//#ifndef __CINT__
//#include <memory>

#include <vector>
#include <iostream>

namespace ROOT {

namespace Math {


/** class defining the signature for multi-dim parametric functions

   @ingroup  ParamFunctor_int
 */

class ParamFunctionBase {
  public:
   virtual ~ParamFunctionBase() {}
//   virtual double operator() (const double * x, const double *p) const = 0;
   virtual double operator() (double * x, double *p) = 0;
   virtual ParamFunctionBase * Clone() const = 0;
};



/**
   ParamFunctor Handler class is responsible for wrapping any other functor and pointer to
   free C functions.
   It can be created from any function implementing the correct signature
   corresponding to the requested type

   @ingroup  ParamFunctor_int

*/
#ifndef __CINT__

template<class ParentFunctor, class Func >
class ParamFunctorHandler : public ParentFunctor::Impl {

   typedef typename ParentFunctor::Impl Base;

public:

   // constructor
   ParamFunctorHandler(const Func & fun) : fFunc(fun) {}


   virtual ~ParamFunctorHandler() {}


   // for 1D functions
   inline double operator() (double x, double *p)  {
      return fFunc(x,p);
   }
//    inline double operator() (double x, const double *p) const {
//       return fFunc(x,p);
//    }
   // for multi-dimensional functions
//    inline double operator() (const double * x, const double *p) const {
//       return fFunc(x,p);
//    }
   inline double operator() (double * x, double *p)  {
      return FuncEvaluator<Func>::Eval(fFunc,x,p);
   }

   // clone (use same pointer)
   ParamFunctorHandler  * Clone() const {
      return new ParamFunctorHandler(fFunc);
   }


private :

   Func fFunc;

   // structure to distinguish pointer types
   template <typename F> struct FuncEvaluator {
      inline static double Eval( F & f, double *x, double * p) {
         return f(x,p);
      }
   };
   template <typename F> struct FuncEvaluator<F*> {
      inline static double Eval( F * f, double *x, double * p) {
         return (*f)(x,p);
      }
   };
   template <typename F> struct FuncEvaluator<F* const> {
      inline static double Eval( const F * f, double *x, double * p) {
         return (*f)(x,p);
      }
   };
   // need maybe also volatile ?
};


#if defined(__MAKECINT__) || defined(G__DICTIONARY)
// needed since CINT initialize it with TRootIOCtor
//class TRootIOCtor;
template<class ParentFunctor>
class ParamFunctorHandler<ParentFunctor,TRootIOCtor *> : public ParentFunctor::Impl
{
public:

   ParamFunctorHandler(TRootIOCtor  *) {}

   double operator() (double *, double * )  { return 0; }
   // clone (use same pointer)
   ParamFunctorHandler  * Clone() const {
      return 0;
   }

};
#endif


/**
   ParamFunctor Handler to Wrap pointers to member functions

   @ingroup  ParamFunctor_int
*/
template <class ParentFunctor, typename PointerToObj,
          typename PointerToMemFn>
class ParamMemFunHandler : public ParentFunctor::Impl
{
   typedef typename ParentFunctor::Impl Base;


public:

   /// constructor from a pointer to the class and a pointer to the function
   ParamMemFunHandler(const PointerToObj& pObj, PointerToMemFn pMemFn)
      : fObj(pObj), fMemFn(pMemFn)
   {}

   virtual ~ParamMemFunHandler() {}

//    inline double operator() (double x, const double * p) const {
//       return ((*fObj).*fMemFn)(x,p);
//    }

   inline double operator() (double x, double * p)  {
      return ((*fObj).*fMemFn)(x,p);
   }

//    inline double operator() (const double * x, const double * p) const {
//       return ((*fObj).*fMemFn)(x,p);
//    }

   inline double operator() (double * x, double * p)  {
      return ((*fObj).*fMemFn)(x,p);
   }

   // clone (use same pointer)
   ParamMemFunHandler  * Clone() const {
      return new ParamMemFunHandler(fObj, fMemFn);
   }


private :
   ParamMemFunHandler(const ParamMemFunHandler&); // Not implemented
   ParamMemFunHandler& operator=(const ParamMemFunHandler&); // Not implemented

   PointerToObj fObj;
   PointerToMemFn fMemFn;

};

#endif



/**
   Param Functor class for Multidimensional functions.
   It is used to wrap in a very simple and convenient way
   any other C++ callable object (implemention double operator( const double *, const double * ) )
   or a member function with the correct signature,
   like Foo::EvalPar(const double *, const double *)

   @ingroup  ParamFunc

 */


class ParamFunctor   {


public:

   typedef  ParamFunctionBase Impl;


   /**
      Default constructor
   */
   ParamFunctor ()  : fImpl(0) {}


   /**
       construct from a pointer to member function (multi-dim type)
    */
   template <class PtrObj, typename MemFn>
   ParamFunctor(const PtrObj& p, MemFn memFn)
      : fImpl(new ParamMemFunHandler<ParamFunctor, PtrObj, MemFn>(p, memFn))
   {}



   /**
      construct from another generic Functor of multi-dimension
    */
   template <typename Func>
   explicit ParamFunctor( const Func & f) :
      fImpl(new ParamFunctorHandler<ParamFunctor,Func>(f) )
   {}



   // specialization used in TF1
   typedef double (* FreeFunc ) (double * , double *);
   ParamFunctor(FreeFunc f) :
      fImpl(new ParamFunctorHandler<ParamFunctor,FreeFunc>(f) )
   {
   }


   /**
      Destructor (no operations)
   */
   virtual ~ParamFunctor ()  {
      if (fImpl) delete fImpl;
   }

   /**
      Copy constructor
   */
   ParamFunctor(const ParamFunctor & rhs) :
      fImpl(0)
   {
//       if (rhs.fImpl.get() != 0)
//          fImpl = std::auto_ptr<Impl>( (rhs.fImpl)->Clone() );
      if (rhs.fImpl != 0)  fImpl = rhs.fImpl->Clone();
   }

   /**
      Assignment operator
   */
   ParamFunctor & operator = (const ParamFunctor & rhs)  {
//      ParamFunctor copy(rhs);
      // swap auto_ptr by hand
//       Impl * p = fImpl.release();
//       fImpl.reset(copy.fImpl.release());
//       copy.fImpl.reset(p);

      if(this != &rhs) {
         if (fImpl) delete fImpl;
         fImpl = 0;
         if (rhs.fImpl != 0)
            fImpl = rhs.fImpl->Clone();
      }
      return *this;
   }

   void * GetImpl() { return (void *) fImpl; }


   double operator() (double * x, double * p)  {
      return (*fImpl)(x,p);
   }



   bool Empty() const { return fImpl == 0; }


   void SetFunction(Impl * f) {
      fImpl = f;
   }

private :


   //std::auto_ptr<Impl> fImpl;
   Impl * fImpl;


};



   } // end namespace Math

} // end namespace ROOT


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