// @(#)root/unuran:$Id$
// Authors: L. Moneta, J. Leydold Wed Feb 28 2007

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

// Header file for class TUnuranMultiContDist

#ifndef ROOT_Math_TUnuranMultiContDist
#define ROOT_Math_TUnuranMultiContDist

#ifndef ROOT_Math_TUnuranBaseDist
#include "TUnuranBaseDist.h"
#endif

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



#include <vector>

class TF1;


//___________________________________________________________________________________________
/**
   TUnuranMultiContDist class describing multi dimensional continuous distributions.
   It is used by TUnuran to generate a set of random numbers according to this distribution via
   TUnuran::Sample(double *).
   The class can be constructed from a multi-dimensional function (TF1 pointer, which can be actually also a
   TF2 or a TF3).
   It provides a method to set the domain of the distribution ( SetDomain ) which will correspond to the range
   of the generated random numbers. By default the domain is [(-inf,-inf,...)(+inf,+inf,...)], indipendently of the
   range set in the TF1 class used to construct the distribution.

   The derivatives of the pdf which are used by some UNURAN methods are estimated numerically in the
   Derivative() method. Some extra information (like distribution mode) can be set using SetMode.
   Some methods require instead of the pdf the log of the pdf.
   This can also be controlled by setting a flag when constructing this class.

*/
/////////////////////////////////////////////////////////////
class TUnuranMultiContDist : public TUnuranBaseDist {

public:


   /**
      Constructor from a TF1 object representing the Probability density function.
      The derivatives of the Pdf are estimated, when required by the UNURAN algorithm,
      using numerical derivation.
      If a value of dim 0 is passed , the dimension of the function is taken from TF1::GetNdim().
      This works only for 2D and 3D (for TF2 and TF3 objects).
   */
   TUnuranMultiContDist (TF1 * func = 0, unsigned int dim = 0, bool isLogPdf = false);


   /**
      Constructor as before but from a generic function object interface for multi-dim functions
   */
   TUnuranMultiContDist (const ROOT::Math::IMultiGenFunction & pdf, bool isLogPdf = false);

   /**
      Destructor
   */
   virtual ~TUnuranMultiContDist ();


   /**
      Copy constructor
   */
   TUnuranMultiContDist(const TUnuranMultiContDist &);

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

   /**
      Clone (required by base class)
    */
   virtual TUnuranMultiContDist * Clone() const { return new TUnuranMultiContDist(*this); }


   /**
      get number of dimension of the distribution
   */
   unsigned int NDim() const {
      return fPdf->NDim();
   }

   /**
      set the domain of the distribution giving an array of minimum and maximum values
      By default otherwise the domain is undefined, i.e. is [-inf,+inf]
      To remove the domain do a SetDomain(0,0).
      There is no possibility to have a domain defined in only one coordinate. Use instead inf or DOUBLE_MAX to
      specify un infinite domain in that coordinate
   */
   void SetDomain(const double *xmin, const double *xmax)  {
      if (xmin == 0 || xmax == 0) return;
      fXmin = std::vector<double>(xmin,xmin+NDim());
      fXmax = std::vector<double>(xmax,xmax+NDim());
   }

   /**
      set the mode of the distribution (coordinates of the distribution maximum values)
   */
   void SetMode(const double * x) {
      fMode = std::vector<double>(x,x+NDim());
   }

   /**
      get the distribution lower domain values. Return a null pointer if domain is not defined
   */
   const double * GetLowerDomain() const {
      if (fXmin.size() == 0 || (  fXmin.size() != fXmax.size() )  ) return 0;
      return &fXmin[0];
   }
   /**
      get the distribution upper domain values. Return a null pointer if domain is not defined
   */
   const double * GetUpperDomain() const {
      if (fXmax.size() == 0 || (  fXmin.size() != fXmax.size() )  ) return 0;
      return &fXmax[0];
   }


   /**
      get the mode (vector of coordinate positions of the maxima of the distribution)
      If a mode has not defined return a NULL pointer
   */
   const double * GetMode( ) const {
      if (fMode.size() == 0  ) return 0;
      return &fMode.front();
   }


   /**
      flag to control if given function represent the log of a pdf
   */
   bool IsLogPdf() const {  return fIsLogPdf; }

   /**
      evaluate the probability density function, used by UnuRan
   */
   double Pdf ( const double * x) const;

   /**
       evaluate the gradient vector of  the Pdf. Used by UnuRan
   */
   void Gradient( const double * x, double * grad) const;

   /**
      evaluate the partial derivative for the given coordinate. Used by UnuRan
   */
   double Derivative( const double * x, int icoord) const;



private:

   const ROOT::Math::IMultiGenFunction  * fPdf;    //pointer to the pdf

   std::vector<double> fXmin;      //vector with lower x values of the domain
   std::vector<double> fXmax;      //vector with upper x values of the domain
   std::vector<double> fMode;      //vector representing the x coordinates of the maximum of the pdf

   bool fIsLogPdf;                 //flag to control if function pointer represent log of pdf
   bool  fOwnFunc;                // flag to indicate if class manages the function pointers


   ClassDef(TUnuranMultiContDist,1)  //Wrapper class for multi dimensional continuous distribution


};



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