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

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

// Implementation file for class TUnuranMultiContDist

#include "TUnuranMultiContDist.h"
#include "Math/WrappedMultiTF1.h"

#include "TF1.h"
#include <cassert>


TUnuranMultiContDist::TUnuranMultiContDist (const ROOT::Math::IMultiGenFunction & pdf, bool isLogPdf) :
   fPdf(&pdf),
   fIsLogPdf(isLogPdf),
   fOwnFunc(false)
{
   //Constructor from generic function interfaces
}


TUnuranMultiContDist::TUnuranMultiContDist (TF1 * func, unsigned int dim, bool isLogPdf) :
   fPdf(0),
   fIsLogPdf(isLogPdf),
   fOwnFunc(false)
{
   //Constructor from a TF1 objects
   if (func) {
      fPdf = new ROOT::Math::WrappedMultiTF1( *func, dim);
      fOwnFunc = true;
   }
}



TUnuranMultiContDist::TUnuranMultiContDist(const TUnuranMultiContDist & rhs) :
   TUnuranBaseDist(),
   fPdf(0)
{
   // Implementation of copy ctor using assignment operator
   operator=(rhs);
}

TUnuranMultiContDist & TUnuranMultiContDist::operator = (const TUnuranMultiContDist &rhs)
{
   // Implementation of assignment operator (copy only the function pointer not the function itself)
   if (this == &rhs) return *this;  // time saving self-test
   fXmin = rhs.fXmin;
   fXmax = rhs.fXmax;
   fMode = rhs.fMode;
   fIsLogPdf  = rhs.fIsLogPdf;
   fOwnFunc   = rhs.fOwnFunc;
   if (!fOwnFunc)
      fPdf   = rhs.fPdf;
   else {
       if (fPdf) delete fPdf;
       fPdf  = (rhs.fPdf)  ? rhs.fPdf->Clone()  : 0;
   }
   return *this;
}

TUnuranMultiContDist::~TUnuranMultiContDist() {
   // destructor implementation
   if (fOwnFunc && fPdf) delete fPdf;
}


double TUnuranMultiContDist::Pdf ( const double * x) const {
   // evaluate the distribution
   assert(fPdf != 0);
   return (*fPdf)(x);
}


void TUnuranMultiContDist::Gradient( const double * x, double * grad) const {
   // do numerical derivation and return gradient in vector grad
   // grad must point to a vector of at least ndim size
   unsigned int ndim = NDim();
   for (unsigned int i = 0; i < ndim; ++i)
      grad[i] = Derivative(x,i);

   return;
}

double TUnuranMultiContDist::Derivative( const double * x, int coord) const {
    // do numerical derivation of gradient using 5 point rule
   // use 5 point rule

   //double eps = 0.001;
   //const double kC1 = 8*std::numeric_limits<double>::epsilon();
   assert(fPdf != 0);

   double h = 0.001;

   std::vector<double> xx(NDim() );

   xx[coord] = x[coord]+h;     double f1 = (*fPdf)(&xx.front());
   xx[coord] = x[coord]-h;     double f2 = (*fPdf)(&xx.front());

   xx[coord] = x[coord]+h/2;   double g1 = (*fPdf)(&xx.front());
   xx[coord] = x[coord]-h/2;   double g2 = (*fPdf)(&xx.front());

   //compute the central differences
   double h2    = 1/(2.*h);
   double d0    = f1 - f2;
   double d2    = 2*(g1 - g2);
   //double error  = kC1*h2*fx;  //compute the error
   double deriv = h2*(4*d2 - d0)/3.;
   return deriv;
}



 TUnuranMultiContDist.cxx:1
 TUnuranMultiContDist.cxx:2
 TUnuranMultiContDist.cxx:3
 TUnuranMultiContDist.cxx:4
 TUnuranMultiContDist.cxx:5
 TUnuranMultiContDist.cxx:6
 TUnuranMultiContDist.cxx:7
 TUnuranMultiContDist.cxx:8
 TUnuranMultiContDist.cxx:9
 TUnuranMultiContDist.cxx:10
 TUnuranMultiContDist.cxx:11
 TUnuranMultiContDist.cxx:12
 TUnuranMultiContDist.cxx:13
 TUnuranMultiContDist.cxx:14
 TUnuranMultiContDist.cxx:15
 TUnuranMultiContDist.cxx:16
 TUnuranMultiContDist.cxx:17
 TUnuranMultiContDist.cxx:18
 TUnuranMultiContDist.cxx:19
 TUnuranMultiContDist.cxx:20
 TUnuranMultiContDist.cxx:21
 TUnuranMultiContDist.cxx:22
 TUnuranMultiContDist.cxx:23
 TUnuranMultiContDist.cxx:24
 TUnuranMultiContDist.cxx:25
 TUnuranMultiContDist.cxx:26
 TUnuranMultiContDist.cxx:27
 TUnuranMultiContDist.cxx:28
 TUnuranMultiContDist.cxx:29
 TUnuranMultiContDist.cxx:30
 TUnuranMultiContDist.cxx:31
 TUnuranMultiContDist.cxx:32
 TUnuranMultiContDist.cxx:33
 TUnuranMultiContDist.cxx:34
 TUnuranMultiContDist.cxx:35
 TUnuranMultiContDist.cxx:36
 TUnuranMultiContDist.cxx:37
 TUnuranMultiContDist.cxx:38
 TUnuranMultiContDist.cxx:39
 TUnuranMultiContDist.cxx:40
 TUnuranMultiContDist.cxx:41
 TUnuranMultiContDist.cxx:42
 TUnuranMultiContDist.cxx:43
 TUnuranMultiContDist.cxx:44
 TUnuranMultiContDist.cxx:45
 TUnuranMultiContDist.cxx:46
 TUnuranMultiContDist.cxx:47
 TUnuranMultiContDist.cxx:48
 TUnuranMultiContDist.cxx:49
 TUnuranMultiContDist.cxx:50
 TUnuranMultiContDist.cxx:51
 TUnuranMultiContDist.cxx:52
 TUnuranMultiContDist.cxx:53
 TUnuranMultiContDist.cxx:54
 TUnuranMultiContDist.cxx:55
 TUnuranMultiContDist.cxx:56
 TUnuranMultiContDist.cxx:57
 TUnuranMultiContDist.cxx:58
 TUnuranMultiContDist.cxx:59
 TUnuranMultiContDist.cxx:60
 TUnuranMultiContDist.cxx:61
 TUnuranMultiContDist.cxx:62
 TUnuranMultiContDist.cxx:63
 TUnuranMultiContDist.cxx:64
 TUnuranMultiContDist.cxx:65
 TUnuranMultiContDist.cxx:66
 TUnuranMultiContDist.cxx:67
 TUnuranMultiContDist.cxx:68
 TUnuranMultiContDist.cxx:69
 TUnuranMultiContDist.cxx:70
 TUnuranMultiContDist.cxx:71
 TUnuranMultiContDist.cxx:72
 TUnuranMultiContDist.cxx:73
 TUnuranMultiContDist.cxx:74
 TUnuranMultiContDist.cxx:75
 TUnuranMultiContDist.cxx:76
 TUnuranMultiContDist.cxx:77
 TUnuranMultiContDist.cxx:78
 TUnuranMultiContDist.cxx:79
 TUnuranMultiContDist.cxx:80
 TUnuranMultiContDist.cxx:81
 TUnuranMultiContDist.cxx:82
 TUnuranMultiContDist.cxx:83
 TUnuranMultiContDist.cxx:84
 TUnuranMultiContDist.cxx:85
 TUnuranMultiContDist.cxx:86
 TUnuranMultiContDist.cxx:87
 TUnuranMultiContDist.cxx:88
 TUnuranMultiContDist.cxx:89
 TUnuranMultiContDist.cxx:90
 TUnuranMultiContDist.cxx:91
 TUnuranMultiContDist.cxx:92
 TUnuranMultiContDist.cxx:93
 TUnuranMultiContDist.cxx:94
 TUnuranMultiContDist.cxx:95
 TUnuranMultiContDist.cxx:96
 TUnuranMultiContDist.cxx:97
 TUnuranMultiContDist.cxx:98
 TUnuranMultiContDist.cxx:99
 TUnuranMultiContDist.cxx:100
 TUnuranMultiContDist.cxx:101
 TUnuranMultiContDist.cxx:102
 TUnuranMultiContDist.cxx:103
 TUnuranMultiContDist.cxx:104
 TUnuranMultiContDist.cxx:105
 TUnuranMultiContDist.cxx:106
 TUnuranMultiContDist.cxx:107
 TUnuranMultiContDist.cxx:108
 TUnuranMultiContDist.cxx:109
 TUnuranMultiContDist.cxx:110
 TUnuranMultiContDist.cxx:111
 TUnuranMultiContDist.cxx:112
 TUnuranMultiContDist.cxx:113
 TUnuranMultiContDist.cxx:114
 TUnuranMultiContDist.cxx:115
 TUnuranMultiContDist.cxx:116
 TUnuranMultiContDist.cxx:117
 TUnuranMultiContDist.cxx:118
 TUnuranMultiContDist.cxx:119
 TUnuranMultiContDist.cxx:120