#include "TUnuranContDist.h"
#include "Math/RichardsonDerivator.h"
#include "Math/WrappedTF1.h"
#include "Math/Integrator.h"
#include "TF1.h"
#include <cassert>
#include <cmath>
ClassImp(TUnuranContDist)
TUnuranContDist::TUnuranContDist (const ROOT::Math::IGenFunction & pdf, const ROOT::Math::IGenFunction * deriv, bool isLogPdf, bool copyFunc ) :
fPdf(&pdf),
fDPdf(deriv),
fCdf(0),
fXmin(1.),
fXmax(-1.),
fMode(0),
fArea(0),
fIsLogPdf(isLogPdf),
fHasDomain(0),
fHasMode(0),
fHasArea(0),
fOwnFunc(copyFunc)
{
if (fOwnFunc) {
fPdf = fPdf->Clone();
if (fDPdf) fDPdf->Clone();
}
}
TUnuranContDist::TUnuranContDist (TF1 * pdf, TF1 * deriv, bool isLogPdf ) :
fPdf( (pdf) ? new ROOT::Math::WrappedTF1 ( *pdf) : 0 ),
fDPdf( (deriv) ? new ROOT::Math::WrappedTF1 ( *deriv) : 0 ),
fCdf(0),
fXmin(1.),
fXmax(-1.),
fMode(0),
fArea(0),
fIsLogPdf(isLogPdf),
fHasDomain(0),
fHasMode(0),
fHasArea(0),
fOwnFunc(true)
{
}
TUnuranContDist::TUnuranContDist(const TUnuranContDist & rhs) :
TUnuranBaseDist(),
fPdf(0),
fDPdf(0),
fCdf(0)
{
operator=(rhs);
}
TUnuranContDist & TUnuranContDist::operator = (const TUnuranContDist &rhs)
{
if (this == &rhs) return *this;
fXmin = rhs.fXmin;
fXmax = rhs.fXmax;
fMode = rhs.fMode;
fArea = rhs.fArea;
fIsLogPdf = rhs.fIsLogPdf;
fHasDomain = rhs.fHasDomain;
fHasMode = rhs.fHasMode;
fHasArea = rhs.fHasArea;
fOwnFunc = rhs.fOwnFunc;
if (!fOwnFunc) {
fPdf = rhs.fPdf;
fDPdf = rhs.fDPdf;
fCdf = rhs.fCdf;
}
else {
if (fPdf) delete fPdf;
if (fDPdf) delete fDPdf;
if (fCdf) delete fCdf;
fPdf = (rhs.fPdf) ? rhs.fPdf->Clone() : 0;
fDPdf = (rhs.fDPdf) ? rhs.fDPdf->Clone() : 0;
fCdf = (rhs.fCdf) ? rhs.fCdf->Clone() : 0;
}
return *this;
}
TUnuranContDist::~TUnuranContDist() {
if (fOwnFunc) {
if (fPdf) delete fPdf;
if (fDPdf) delete fDPdf;
if (fCdf) delete fCdf;
}
}
void TUnuranContDist::SetCdf(const ROOT::Math::IGenFunction & cdf) {
fCdf = (fOwnFunc) ? cdf.Clone() : &cdf;
}
void TUnuranContDist::SetCdf(TF1 * cdf) {
if (!fOwnFunc) {
assert (fPdf != 0);
fPdf = fPdf->Clone();
if (fDPdf) fDPdf->Clone();
}
else
if (fOwnFunc && fCdf) delete fCdf;
fCdf = (cdf) ? new ROOT::Math::WrappedTF1 ( *cdf) : 0;
fOwnFunc = true;
}
double TUnuranContDist::Pdf ( double x) const {
assert(fPdf != 0);
return (*fPdf)(x);
}
double TUnuranContDist::DPdf( double x) const {
if (fDPdf != 0) {
return (*fDPdf)(x);
}
ROOT::Math::RichardsonDerivator rd;
static double gEps = 0.001;
double h = ( std::abs(x) > 0 ) ? gEps * std::abs(x) : gEps;
assert (fPdf != 0);
return rd.Derivative1( *fPdf, x, h);
}
double TUnuranContDist::Cdf(double x) const {
if (fCdf != 0) {
return (*fCdf)(x);
}
ROOT::Math::Integrator ig;
if (fXmin > fXmax) return ig.Integral( *fPdf );
else
return ig.Integral( *fPdf, fXmin, fXmax );
}