/******************************************************************************* * Project: BaBar detector at the SLAC PEP-II B-factory * Package: EvtGenBase * File: $Id: EvtPdfSum.hh,v 1.3 2009-03-16 16:40:16 robbep 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 c,const EvtPdf& pdf) { assert(c >= 0.); _c.push_back(c); _term.push_back(pdf.clone()); } void addOwnedTerm(double c, EvtPdf* pdf) { _c.push_back(c); _term.push_back(pdf); } size_t 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 }; template EvtPdfSum::EvtPdfSum(const EvtPdfSum& other) : EvtPdf(other) { for(size_t i = 0; i < other.nTerms(); i++) { _c.push_back(other._c[i]); _term.push_back(other._term[i]->clone()); } } template EvtPdfSum::~EvtPdfSum() { for(size_t i = 0; i < _c.size(); i++) { delete _term[i]; } } template double EvtPdfSum::pdf(const T& p) const { double ret = 0.; for(size_t 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 { EvtValError itg(0.0,0.0); for(size_t i=0;igetItg(); } return itg; } template EvtValError EvtPdfSum::compute_integral(int N) const { EvtValError itg(0.0,0.0); for(size_t 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(!this->_itg.valueKnown()) this->_itg = compute_integral(); double max = this->_itg.value(); double rnd = EvtRandom::Flat(0,max); double sum = 0.; size_t 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