// @(#)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 TUnuranContDist #include "TUnuranContDist.h" #include "Math/RichardsonDerivator.h" #include "Math/WrappedTF1.h" #include "Math/Integrator.h" #include "TF1.h" #include #include 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) { // Constructor from generic function interfaces // manage the functions and clone them if flag copyFunc is true 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) { // Constructor from a TF1 objects // function pointers are managed by class } TUnuranContDist::TUnuranContDist(const TUnuranContDist & rhs) : TUnuranBaseDist(), fPdf(0), fDPdf(0), fCdf(0) { // Implementation of copy constructor operator=(rhs); } TUnuranContDist & TUnuranContDist::operator = (const TUnuranContDist &rhs) { // Implementation of assignment operator. if (this == &rhs) return *this; // time saving self-test 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() { // destructor implementation if (fOwnFunc) { if (fPdf) delete fPdf; if (fDPdf) delete fDPdf; if (fCdf) delete fCdf; } } void TUnuranContDist::SetCdf(const ROOT::Math::IGenFunction & cdf) { // set cdf distribution using a generic function interface fCdf = (fOwnFunc) ? cdf.Clone() : &cdf; } void TUnuranContDist::SetCdf(TF1 * cdf) { // set cumulative distribution function from a TF1 if (!fOwnFunc) { // need to manage all functions now 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 { // evaluate the pdf of the distribution assert(fPdf != 0); //fX[0] = x; return (*fPdf)(x); } double TUnuranContDist::DPdf( double x) const { // evaluate the derivative of the pdf // if derivative function is not given is evaluated numerically if (fDPdf != 0) { //fX[0] = x; return (*fDPdf)(x); } // do numerical derivation using numerical derivation 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 { // evaluate the integral (cdf) on the domain if (fCdf != 0) { // fX[0] = x; return (*fCdf)(x); } // do numerical integration ROOT::Math::Integrator ig; if (fXmin > fXmax) return ig.Integral( *fPdf ); else return ig.Integral( *fPdf, fXmin, fXmax ); }