/******************************************************************************* * Project: BaBar detector at the SLAC PEP-II B-factory * Package: EvtGenBase * File: $Id: EvtPdfSum.hh,v 1.7 2003/06/20 17:20:10 dvoretsk Exp $ * Author: Alexei Dvoretskii, dvoretsk@slac.stanford.edu, 2001-2002 * * Copyright (C) 2002 Caltech *******************************************************************************/ // Sum of PDF functions. #ifndef EVT_PDF_SUM_HH #define EVT_PDF_SUM_HH #include #include using std::vector; #include "EvtGenBase/EvtPdf.hh" template class EvtPdfSum : public EvtPdf { public: EvtPdfSum() {} EvtPdfSum(const EvtPdfSum& other); virtual ~EvtPdfSum(); virtual EvtPdf* clone() const { return new EvtPdfSum(*this); } // Manipulate terms and coefficients void addTerm(double fc,const EvtPdf& fpdf) { assert(fc >= 0.); _c.push_back(fc); _term.push_back(fpdf.clone()); } void addOwnedTerm(double fc, EvtPdf* fpdf) { _c.push_back(fc); _term.push_back(fpdf); } int nTerms() const { return _term.size(); } // number of terms inline double c(int i) const { return _c[i]; } inline EvtPdf* getPdf(int i) const { return _term[i]; } // Integrals virtual EvtValError compute_integral() const; virtual EvtValError compute_integral(int N) const; virtual T randomPoint(); protected: virtual double pdf(const T& p) const; vector _c; // coefficients vector*> _term; // pointers to pdfs mutable EvtValError _itg; // propagated from EvtPdf, corrected by S.Spataro. It needs to be checked }; template EvtPdfSum::EvtPdfSum(const EvtPdfSum& other) : EvtPdf(other) { int i; for(i = 0; i < other.nTerms(); i++) { _c.push_back(other._c[i]); _term.push_back(other._term[i]->clone()); } } template EvtPdfSum::~EvtPdfSum() { int i; for(i = 0; i < _c.size(); i++) delete _term[i]; } template double EvtPdfSum::pdf(const T& p) const { double ret = 0.; unsigned i; for(i=0; i < _c.size(); i++) ret += _c[i] * _term[i]->evaluate(p); return ret; } /* * Compute the sum integral by summing all term integrals. */ template EvtValError EvtPdfSum::compute_integral() const { int i; EvtValError itg(0.0,0.0); for(i=0;igetItg(); return itg; } template EvtValError EvtPdfSum::compute_integral(int N) const { int i; EvtValError itg(0.0,0.0); for(i=0;igetItg(N); return itg; } /* * Sample points randomly according to the sum of PDFs. First throw a random number uniformly * between zero and the value of the sum integral. Using this random number select one * of the PDFs. The generate a random point according to that PDF. */ template T EvtPdfSum::randomPoint() { if(!_itg.valueKnown()) _itg = compute_integral(); double max = _itg.value(); double rnd = EvtRandom::Flat(0,max); double sum = 0.; int i; for(i = 0; i < nTerms(); i++) { double itg = _term[i]->getItg().value(); sum += _c[i] * itg; if(sum > rnd) break; } return _term[i]->randomPoint(); } #endif