// @(#)root/mathmore:$Id$
// Author: L. Moneta June 2009

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


// Header file for class MinimTransformFunction

#ifndef ROOT_Math_MinimTransformFunction
#define ROOT_Math_MinimTransformFunction


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

#ifndef ROOT_Math_MinimTransformVariable
#include "Math/MinimTransformVariable.h"
#endif


#include <vector>
#include <map>

namespace ROOT {

   namespace Math {



/**
   MinimTransformFunction class to perform a transformations on the
   variables to deal with fixed or limited variables (support both double and single bounds)
   The class manages the passed function pointer

   @ingroup MultiMin
*/
class MinimTransformFunction : public IMultiGradFunction {

public:

   typedef  ROOT::Math::IMultiGradFunction BaseGradFunc;
   typedef  ROOT::Math::IMultiGradFunction::BaseFunc BaseFunc;


   /**
     Constructor from a IMultiGradFunction interface (which is managed by the class)
     vector specifying the variable types (free, bounded or fixed, defined in enum EMinimVariableTypes )
     variable values (used for the fixed ones) and a map with the bounds (for the bounded variables)

   */
   MinimTransformFunction ( const IMultiGradFunction * f, const std::vector<ROOT::Math::EMinimVariableType> & types, const std::vector<double> & values,
                            const std::map<unsigned int, std::pair<double, double> > & bounds);


   /**
      Destructor (delete function pointer)
   */
   ~MinimTransformFunction ()  {
      if (fFunc) delete fFunc;
   }


   // method inherited from IFunction interface

   unsigned int NDim() const { return fIndex.size(); }

   unsigned int NTot() const { return fFunc->NDim(); }

   /// clone:  not supported (since auto_ptr used in the fVariables)
   IMultiGenFunction * Clone() const {
      return 0;
   }


   /// transform from internal to external
   /// result is cached also inside the class
   const double * Transformation( const double * x) const {
      Transformation(x, &fX[0]);
      return &fX.front();
  }


   /// transform from internal to external
   void Transformation( const double * xint, double * xext) const;

   /// inverse transformation (external -> internal)
   void  InvTransformation(const double * xext,  double * xint) const;

   /// inverse transformation for steps (external -> internal) at external point x
   void  InvStepTransformation(const double * x, const double * sext,  double * sint) const;

   ///transform gradient vector (external -> internal) at internal point x
   void GradientTransformation(const double * x, const double *gExt, double * gInt) const;

   ///transform covariance matrix (internal -> external) at internal point x
   /// use row storages for matrices  m(i,j) = rep[ i * dim + j]
   void MatrixTransformation(const double * x, const double *covInt, double * covExt) const;

   // return original function
   const IMultiGradFunction *OriginalFunction() const { return fFunc; }


private:

   /// function evaluation
   virtual double DoEval(const double * x) const {
#ifndef DO_THREADSAFE
      return (*fFunc)(Transformation(x));
#else
      std::vector<double> xext(fVariables.size() );
      Transformation(x, &xext[0]);
      return (*fFunc)(&xext[0]);
#endif
   }

   /// calculate derivatives
   virtual double DoDerivative (const double * x, unsigned int icoord  ) const {
      const MinimTransformVariable & var = fVariables[ fIndex[icoord] ];
      double dExtdInt = (var.IsLimited() ) ? var.DerivativeIntToExt( x[icoord] ) : 1.0;
      double deriv =  fFunc->Derivative( Transformation(x) , fIndex[icoord] );
      //std::cout << "Derivative icoord (ext)" << fIndex[icoord] << "   dtrafo " << dExtdInt << "  " << deriv << std::endl;
      return deriv * dExtdInt;
   }

   // copy constructor for this class (disable by having it private)
   MinimTransformFunction( const MinimTransformFunction & ) :
      BaseFunc(), BaseGradFunc()
   {}

   // assignment operator for this class (disable by having it private)
   MinimTransformFunction & operator= ( const MinimTransformFunction & ) {
      return *this;
   }



private:

   mutable std::vector<double>  fX;              // internal cached of external values
   std::vector<MinimTransformVariable> fVariables;    // vector of variable settings and tranformation function
   std::vector<unsigned int>      fIndex;        // vector with external indices for internal variables
   const IMultiGradFunction * fFunc;             // user function

};

   } // end namespace Math

} // end namespace ROOT


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