59enum BasisType { none = 0, expBasis = 1, sinBasis = 2, cosBasis = 3, sinhBasis = 4, coshBasis = 5 };
61enum BasisSign { Both = 0, Plus = +1, Minus = -1 };
86 bool nlo,
Type type) :
88 _mean(
"mean",
"Mean of Gaussian component", this, meanIn),
89 sigma(
"sigma",
"Width", this, sigmaIn),
90 rlife(
"rlife",
"Life time", this, rlifeIn),
91 _meanSF(
"meanSF",
"Scale factor for mean", this, meanSF),
92 ssf(
"ssf",
"Sigma Scale Factor", this, sigmaSF),
93 rsf(
"rsf",
"RLife Scale Factor", this, rlifeSF),
114 bool nlo,
Type type) :
117 sigma(
"sigma",
"Width",this,_sigma),
118 rlife(
"rlife",
"Life time",this,_rlife),
140 bool nlo,
Type type) :
143 sigma(
"sigma",
"Width",this,_sigma),
144 rlife(
"rlife",
"Life time",this,_rlife),
146 ssf(
"ssf",
"Sigma Scale Factor",this,_rsSF),
147 rsf(
"rsf",
"RLife Scale Factor",this,_rsSF),
170 bool nlo,
Type type) :
173 sigma(
"sigma",
"Width",this,_sigma),
174 rlife(
"rlife",
"Life time",this,_rlife),
176 ssf(
"ssf",
"Sigma Scale Factor",this,_sigmaSF),
177 rsf(
"rsf",
"RLife Scale Factor",this,_rlifeSF),
193 ssf(
"ssf",this,other.
ssf),
194 rsf(
"rsf",this,other.
rsf),
206 std::string str =
name;
209 str.erase(remove(str.begin(),str.end(),
' '),str.end());
211 if (str ==
"exp(-@0/@1)")
return expBasisPlus ;
212 if (str ==
"exp(@0/@1)")
return expBasisMinus ;
213 if (str ==
"exp(-abs(@0)/@1)")
return expBasisSum ;
214 if (str ==
"exp(-@0/@1)*sin(@0*@2)")
return sinBasisPlus ;
215 if (str ==
"exp(@0/@1)*sin(@0*@2)")
return sinBasisMinus ;
216 if (str ==
"exp(-abs(@0)/@1)*sin(@0*@2)")
return sinBasisSum ;
217 if (str ==
"exp(-@0/@1)*cos(@0*@2)")
return cosBasisPlus ;
218 if (str ==
"exp(@0/@1)*cos(@0*@2)")
return cosBasisMinus ;
219 if (str ==
"exp(-abs(@0)/@1)*cos(@0*@2)")
return cosBasisSum ;
220 if (str ==
"exp(-@0/@1)*sinh(@0*@2/2)")
return sinhBasisPlus;
221 if (str ==
"exp(@0/@1)*sinh(@0*@2/2)")
return sinhBasisMinus;
222 if (str ==
"exp(-abs(@0)/@1)*sinh(@0*@2/2)")
return sinhBasisSum;
223 if (str ==
"exp(-@0/@1)*cosh(@0*@2/2)")
return coshBasisPlus;
224 if (str ==
"exp(@0/@1)*cosh(@0*@2/2)")
return coshBasisMinus;
225 if (str ==
"exp(-abs(@0)/@1)*cosh(@0*@2/2)")
return coshBasisSum;
234double logErfC(
double xx)
244 (-z * z - 1.26551223 +
250 t * (-1.13520398 + t * (1.48851587 + t * (-0.82215223 + t * 0.17087277)))))))));
255 exp(-z * z - 1.26551223 +
260 t * (0.27886807 + t * (-1.13520398 +
261 t * (1.48851587 + t * (-0.82215223 + t * 0.17087277))))))))));
274 static double rootpi=
sqrt(
atan2(0.,-1.));
275 std::complex<double> z(swt*
c,u+
c);
276 std::complex<double> zc(u+
c,-swt*
c);
277 std::complex<double> zsq= z*
z;
278 std::complex<double>
v= -zsq - u*u;
280 return std::exp(
v)*(-std::exp(zsq)/(zc*rootpi) + 1.)*2.;
285std::complex<double>
evalCerf(
double swt,
double u,
double c)
287 std::complex<double> z(swt*
c,u+
c);
294inline double evalCerfRe(
double u,
double c) {
295 double expArg = u*2*
c+
c*
c ;
299 return exp(expArg+logErfC(u+
c));
311 static double root2(sqrt(2.)) ;
314 BasisSign basisSign = (BasisSign)(
_basisCode - 10*(basisType-1) - 2 ) ;
316 double fsign =
_flip?-1:1 ;
323 if (basisType == coshBasis &&
_basisCode!=noBasis ) {
325 if (dGamma==0) basisType = expBasis;
329 if (basisType==none || ((basisType==expBasis || basisType==cosBasis) && tau==0.)) {
330 if (
verboseEval()>2) std::cout <<
"RooGExpModel::evaluate(" <<
GetName() <<
") 1st form" << std::endl ;
332 double expArg = sig*sig/(2*rtau*rtau) + fsign*(
x -
_mean*
_meanSF)/rtau ;
340 result = 1/(2*rtau) * exp(expArg + logErfC(sig/(root2*rtau) + fsign*(
x -
_mean*
_meanSF)/(root2*sig))) ;
353 if (
_basisCode!=0 && basisSign==Both) result *= 2 ;
360 if (
verboseEval()>2) std::cout <<
"RooGExpModel::evaluate(" <<
GetName() <<
") 2nd form" << std::endl ;
364 double omega = (basisType!=expBasis)?(
static_cast<RooAbsReal*
>(
basis().getParameter(2)))->getVal():0. ;
367 if (basisType==expBasis || (basisType==cosBasis && omega==0.)) {
368 if (
verboseEval()>2) std::cout <<
"RooGExpModel::evaluate(" <<
GetName() <<
") 3d form tau=" << tau << std::endl ;
370 if (basisSign!=Minus) result +=
calcDecayConv(+1,tau,sig,rtau,fsign) ;
371 if (basisSign!=Plus) result +=
calcDecayConv(-1,tau,sig,rtau,fsign) ;
377 double wt = omega *tau ;
378 if (basisType==sinBasis) {
379 if (
verboseEval()>2) std::cout <<
"RooGExpModel::evaluate(" <<
GetName() <<
") 4th form omega = "
380 << omega <<
", tau = " << tau << std::endl ;
382 if (wt==0.)
return result ;
383 if (basisSign!=Minus) result += -1*
calcSinConv(+1,sig,tau,omega,rtau,fsign).imag() ;
384 if (basisSign!=Plus) result += -1*
calcSinConv(-1,sig,tau,omega,rtau,fsign).imag() ;
390 if (basisType==cosBasis) {
392 <<
") 5th form omega = " << omega <<
", tau = " << tau << std::endl ;
394 if (basisSign!=Minus) result +=
calcSinConv(+1,sig,tau,omega,rtau,fsign).real() ;
395 if (basisSign!=Plus) result +=
calcSinConv(-1,sig,tau,omega,rtau,fsign).real() ;
402 if (basisType==sinhBasis) {
406 <<
") 6th form = " << dgamma <<
", tau = " << tau << std::endl;
411 double tau1 = 1/(1/tau-dgamma/2) ;
412 double tau2 = 1/(1/tau+dgamma/2) ;
422 if (basisType==coshBasis) {
426 <<
") 7th form = " << dgamma <<
", tau = " << tau << std::endl;
431 double tau1 = 1/(1/tau-dgamma/2) ;
432 double tau2 = 1/(1/tau+dgamma/2) ;
449 static double root2(sqrt(2.)) ;
453 double c1= sig/(root2*tau);
454 double u1=
s1/(2*
c1);
456 double c2= sig/(root2*rtau);
457 double u2= fsign*s2/(2*
c2) ;
460 std::complex<double> eins(1,0);
461 std::complex<double> k(1/tau,sign*omega);
464 return (
evalCerf(-sign*omega*tau,u1,
c1)+std::complex<double>(evalCerfRe(u2,
c2),0)*fsign*sign) / (eins + k*fsign*sign*rtau) ;
475 static double root2(sqrt(2.)) ;
479 double c1= sig/(root2*tau);
480 double u1=
s1/(2*
c1);
482 double c2= sig/(root2*rtau);
483 double u2= fsign*s2/(2*
c2) ;
488 return (evalCerfRe(u1,
c1)+evalCerfRe(u2,
c2)*fsign*sign) / (eins + k*fsign*sign*rtau) ;
498 static double root2(sqrt(2.)) ;
499 static double root2pi(sqrt(2*atan2(0.,-1.))) ;
500 static double rootpi(sqrt(atan2(0.,-1.)));
512 if ((sign<0)&&(std::abs(tau-rtau)<tau/260)) {
514 double MeanTau=0.5*(tau+rtau);
515 if (std::abs(xp/MeanTau)>300) {
519 cFly=1./(MeanTau*MeanTau*root2pi) *
520 exp(-(-xp/MeanTau-sig*sig/(2*MeanTau*MeanTau)))
521 *(sig*exp(-1/(2*sig*sig)*std::pow((sig*sig/MeanTau+xp),2))
522 -(sig*sig/MeanTau+xp)*(rootpi/root2)*
RooMath::erfc(sig/(root2*MeanTau)+xp/(root2*sig)));
525 double epsilon=0.5*(tau-rtau);
526 double a=sig/(root2*MeanTau)+xp/(root2*sig);
527 cFly += 1./(MeanTau*MeanTau)
528 *exp(-(-xp/MeanTau-sig*sig/(2*MeanTau*MeanTau)))
529 *0.5/MeanTau*epsilon*epsilon*
530 (exp(-
a*
a)*(sig/MeanTau*root2/rootpi
531 -(4*
a*sig*sig)/(2*rootpi*MeanTau*MeanTau)
532 +(-4/rootpi+8*
a*
a/rootpi)/6
533 *std::pow(sig/(root2*MeanTau),3)
534 +2/rootpi*(sig*sig/(MeanTau*MeanTau)+xp/MeanTau)*
535 (sig/(root2*MeanTau)-
a*(sig*sig)/(2*MeanTau*MeanTau))
536 +2/rootpi*((3*sig*sig)/(2*MeanTau*MeanTau)+xp/MeanTau+
537 0.5*std::pow(sig*sig/(MeanTau*MeanTau)+xp/MeanTau,2))*sig/(root2*MeanTau))
538 -(2*sig*sig/(MeanTau*MeanTau)+xp/MeanTau+(sig*sig/(MeanTau*MeanTau)+xp/MeanTau)*
539 (3*sig*sig/(2*MeanTau*MeanTau)+xp/MeanTau)
540 +std::pow(sig*sig/(MeanTau*MeanTau)+xp/MeanTau,3)/6)*
RooMath::erfc(
a));
545 double expArg1 = sig*sig/(2*tau*tau)-sign*xp/tau ;
546 double expArg2 = sig*sig/(2*rtau*rtau)+xp/rtau ;
551 term1 = exp(expArg1) *
RooMath::erfc(sig/(root2*tau)-sign*xp/(root2*sig)) ;
553 term1 = exp(expArg1+logErfC(sig/(root2*tau)-sign*xp/(root2*sig))) ;
556 term2 = exp(expArg2) *
RooMath::erfc(sig/(root2*rtau)+xp/(root2*sig)) ;
558 term2 = exp(expArg2+logErfC(sig/(root2*rtau)+xp/(root2*sig))) ;
561 cFly=(term1+sign*term2)/(2*(tau+sign*rtau));
579double RooGExpModel::calcCoshConv(double sign, double tau, double dgamma, double sig, double rtau, double fsign) const
583 static double root2(sqrt(2.)) ;
584 static double root2pi(sqrt(2*atan2(0.,-1.))) ;
585 static double rootpi(sqrt(atan2(0.,-1.)));
586 double tau1 = 1/(1/tau-dgamma/2);
587 double tau2 = 1/(1/tau+dgamma/2);
595 xp *= fsign ; // modified FMV,08/13/03
596 sign *= fsign ; // modified FMV,08/13/03
598 cFly=tau1*(exp(sig*sig/(2*tau1*tau1)-sign*xp/tau1)
599 *RooMath::erfc(sig/(root2*tau1)-sign*xp/(root2*sig))
600 +sign*exp(sig*sig/(2*rtau*rtau)+xp/rtau)
601 *RooMath::erfc(sig/(root2*rtau)+xp/(root2*sig)))/(2*(tau1+sign*rtau))
602 +tau2*(exp(sig*sig/(2*tau2*tau2)-sign*xp/tau2)
603 *RooMath::erfc(sig/(root2*tau2)-sign*xp/(root2*sig))
604 +sign*exp(sig*sig/(2*rtau*rtau)+xp/rtau)
605 *RooMath::erfc(sig/(root2*rtau)+xp/(root2*sig)))/(2*(tau2+sign*rtau));
614double RooGExpModel::calcSinhConv(double sign, double sign1, double sign2, double tau, double dgamma, double sig, double rtau, double fsign) const
616 static double root2(sqrt(2.)) ;
617 static double root2pi(sqrt(2*atan2(0.,-1.))) ;
618 static double rootpi(sqrt(atan2(0.,-1.)));
619 double tau1 = 1/(1/tau-dgamma/2);
620 double tau2 = 1/(1/tau+dgamma/2);
629 xp *= fsign ; // modified FMV,08/13/03
630 sign1 *= fsign ; // modified FMV,08/13/03
631 sign2 *= fsign ; // modified FMV,08/13/03
633 cFly=sign1*tau1*(exp(sig*sig/(2*tau1*tau1)-sign*xp/tau1)
634 *RooMath::erfc(sig/(root2*tau1)-sign*xp/(root2*sig))
635 +sign*exp(sig*sig/(2*rtau*rtau)+xp/rtau)
636 *RooMath::erfc(sig/(root2*rtau)+xp/(root2*sig)))/(2*(tau1+sign*rtau))
637 +sign2*tau2*(exp(sig*sig/(2*tau2*tau2)-sign*xp/tau2)
638 *RooMath::erfc(sig/(root2*tau2)-sign*xp/(root2*sig))
639 +sign*exp(sig*sig/(2*rtau*rtau)+xp/rtau)
640 *RooMath::erfc(sig/(root2*rtau)+xp/(root2*sig)))/(2*(tau2+sign*rtau));
691 static double root2 = sqrt(2.) ;
698 ssfInt = (
ssf.max(rangeName)-
ssf.min(rangeName)) ;
702 BasisSign basisSign = (BasisSign)(
_basisCode - 10*(basisType-1) - 2 ) ;
707 if (basisType == coshBasis &&
_basisCode!=noBasis ) {
709 if (dGamma==0) basisType = expBasis;
711 double fsign =
_flip?-1:1 ;
716 if (basisType==none || ((basisType==expBasis || basisType==cosBasis) && tau==0.)) {
717 if (
verboseEval()>0) std::cout <<
"RooGExpModel::analyticalIntegral(" <<
GetName() <<
") 1st form" << std::endl ;
723 double c = sig/(root2*rtau) ;
724 double umin = xpmin/(2*
c) ;
725 double umax = xpmax/(2*
c) ;
730 result = 0.5*
evalCerfInt(-fsign,rtau,fsign*umin,fsign*umax,
c)/rtau ;
733 if (
_basisCode!=0 && basisSign==Both) result *= 2 ;
735 return result*ssfInt ;
738 double omega = (basisType!=expBasis) ?(
static_cast<RooAbsReal*
>(
basis().getParameter(2)))->getVal() : 0 ;
743 if (
verboseEval()>0) std::cout <<
"RooGExpModel::analyticalIntegral(" <<
GetName() <<
") 2nd form" << std::endl ;
748 if (basisType==expBasis || (basisType==cosBasis && omega==0.)) {
753 if (basisSign!=Minus) result +=
calcSinConvNorm(+1,tau,sig,rtau,fsign,rangeName);
754 if (basisSign!=Plus) result +=
calcSinConvNorm(-1,tau,sig,rtau,fsign,rangeName);
756 return result*ssfInt ;
760 double wt = omega * tau ;
761 if (basisType==sinBasis) {
762 if (
verboseEval()>0) std::cout <<
"RooGExpModel::analyticalIntegral(" <<
GetName() <<
") 4th form omega = "
763 << omega <<
", tau = " << tau << std::endl ;
766 if (wt==0)
return result ;
770 if (basisSign!=Minus) result += -1*
calcSinConvNorm(+1,tau,omega,sig,rtau,fsign,rangeName).imag();
771 if (basisSign!=Plus) result += -1*
calcSinConvNorm(-1,tau,omega,sig,rtau,fsign,rangeName).imag();
773 return result*ssfInt ;
777 if (basisType==cosBasis) {
779 <<
") 5th form omega = " << omega <<
", tau = " << tau << std::endl ;
785 if (basisSign!=Minus) result +=
calcSinConvNorm(+1,tau,omega,sig,rtau,fsign,rangeName).real();
786 if (basisSign!=Plus) result +=
calcSinConvNorm(-1,tau,omega,sig,rtau,fsign,rangeName).real();
788 return result*ssfInt ;
791 double dgamma = ((basisType==coshBasis)||(basisType==sinhBasis))?(
static_cast<RooAbsReal*
>(
basis().getParameter(2)))->getVal():0 ;
794 if (basisType==sinhBasis) {
796 <<
") 6th form dgamma = " << dgamma <<
", tau = " << tau << std::endl ;
797 double tau1 = 1/(1/tau-dgamma/2);
798 double tau2 = 1/(1/tau+dgamma/2);
804 if (basisSign!=Minus) result += 0.5*(
calcSinConvNorm(+1,tau1,sig,rtau,fsign,rangeName)-
806 if (basisSign!=Plus) result += 0.5*(
calcSinConvNorm(-1,tau2,sig,rtau,fsign,rangeName)-
813 if (basisType==coshBasis) {
815 <<
") 6th form dgamma = " << dgamma <<
", tau = " << tau << std::endl ;
817 double tau1 = 1/(1/tau-dgamma/2);
818 double tau2 = 1/(1/tau+dgamma/2);
823 if (basisSign!=Minus) result += 0.5*(
calcSinConvNorm(+1,tau1,sig,rtau,fsign,rangeName)+
825 if (basisSign!=Plus) result += 0.5*(
calcSinConvNorm(-1,tau1,sig,rtau,fsign,rangeName)+
844 double sig,
double rtau,
double fsign,
const char* rangeName)
const
846 static double root2(sqrt(2.)) ;
850 double c1= sig/(root2*tau);
851 double umin1= smin1/(2*
c1);
852 double umax1= smax1/(2*
c1);
855 double c2= sig/(root2*rtau);
856 double umin2= smin2/(2*
c2) ;
857 double umax2= smax2/(2*
c2) ;
859 std::complex<double> eins(1,0);
860 std::complex<double> k(1/tau,sign*omega);
861 std::complex<double> term1 =
evalCerfInt(sign,-sign*omega*tau, tau, -sign*umin1, -sign*umax1,
c1);
863 std::complex<double> term2 = std::complex<double>(
evalCerfInt(-fsign, rtau, fsign*umin2, fsign*umax2,
c2)*fsign*sign,0);
864 return (term1+term2)/(eins + k*fsign*sign*rtau) ;
873 static double root2(sqrt(2.)) ;
877 double c1= sig/(root2*tau);
878 double umin1= smin1/(2*
c1);
879 double umax1= smax1/(2*
c1);
882 double c2= sig/(root2*rtau);
883 double umin2= smin2/(2*
c2) ;
884 double umax2= smax2/(2*
c2) ;
888 double term1 =
evalCerfInt(sign, tau, -sign*umin1, -sign*umax1,
c1);
889 double term2 =
evalCerfInt(-fsign, rtau, fsign*umin2, fsign*umax2,
c2)*fsign*sign;
892 if (std::abs(tau-rtau)<1
e-10 && std::abs(term1+term2)<1
e-10) {
893 std::cout <<
"epsilon method" << std::endl ;
894 static double epsilon = 1
e-4 ;
895 return calcSinConvNorm(sign,tau+epsilon,sig,rtau-epsilon,fsign,rangeName) ;
897 return (term1+term2)/(eins + k*fsign*sign*rtau) ;
905 std::complex<double> diff;
907 diff = std::complex<double>(2,0) ;
911 return std::complex<double>(tau/(1.+wt*wt),0)*std::complex<double>(1,wt)*diff;
923 if ((umin<-8 && umax>8)||(umax<-8 && umin>8)) {
937 if (
matchArgs(directVars,generateVars,
x))
return 1 ;
951 xgen = xgau + (
rlife*
rsf)*log(xexp);
953 xgen = xgau - (
rlife *
rsf) * log(xexp);
STD::complex< double > evalCerf(double swt, double u, double c)
STD::complex< double > evalCerfApprox(double _x, double u, double c)
use the approximation: erf(z) = exp(-z*z)/(STD::sqrt(pi)*z) to explicitly cancel the divergent exp(y*...
int Int_t
Signed integer 4 bytes (int).
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
static int verboseEval()
Return global level of verbosity for p.d.f. evaluations.
Abstract base class for objects that represent a real value that may appear on the left hand side of ...
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
bool matchArgs(const RooArgSet &allDeps, RooArgSet &analDeps, const RooArgProxy &a, const Proxies &... proxies) const
RooArgSet is a container object that can hold multiple RooAbsArg objects.
std::complex< double > evalCerfInt(double sign, double wt, double tau, double umin, double umax, double c) const
std::complex< double > calcSinConv(double sign, double sig, double tau, double omega, double rtau, double fsign) const
double calcDecayConv(double sign, double tau, double sig, double rtau, double fsign) const
double evaluate() const override
Evaluate this PDF / function / constant. Needs to be overridden by all derived classes.
void generateEvent(Int_t code) override
Interface for generation of an event using the algorithm corresponding to the specified code.
Int_t getGenerator(const RooArgSet &directVars, RooArgSet &generateVars, bool staticInitOK=true) const override
Load generatedVars with the subset of directVars that we can generate events for, and return a code t...
std::complex< double > calcSinConvNorm(double sign, double tau, double omega, double sig, double rtau, double fsign, const char *rangeName) const
old code (asymptotic normalization only) std::complex<double> z(1/tau,sign*omega); return z*2/(omega*...
double analyticalIntegral(Int_t code, const char *rangeName=nullptr) const override
Implements the actual analytical integral(s) advertised by getAnalyticalIntegral.
Int_t getAnalyticalIntegral(RooArgSet &allVars, RooArgSet &analVars, const char *rangeName=nullptr) const override
Interface function getAnalyticalIntergral advertises the analytical integrals that are supported.
Int_t basisCode(const char *name) const override
static std::complex< double > erfc(const std::complex< double > z)
complex erfc function
static std::complex< double > erf(const std::complex< double > z)
complex erf function
static std::complex< double > faddeeva_fast(std::complex< double > z)
evaluate Faddeeva function for complex argument (fast version)
static double uniform(TRandom *generator=randomGenerator())
Return a number uniformly distributed from (0,1).
static TRandom * randomGenerator()
Return a pointer to a singleton random-number generator implementation.
Provides static functions to create and keep track of RooRealVar constants.
Int_t _basisCode
Identifier code for selected basis function.
RooAbsRealLValue & convVar() const
Return the convolution variable of the resolution model.
RooResolutionModel()=default
const RooFormulaVar & basis() const
RooTemplateProxy< RooAbsRealLValue > x
Dependent/convolution variable.
const char * GetName() const override
Returns name of object.
virtual Double_t Gaus(Double_t mean=0, Double_t sigma=1)
Samples a random number from the standard Normal (Gaussian) Distribution with the given mean and sigm...
RVec< PromoteType< T > > log(const RVec< T > &v)
RVec< PromoteTypes< T0, T1 > > atan2(const T0 &x, const RVec< T1 > &v)
RVec< PromoteType< T > > exp(const RVec< T > &v)
VecExpr< UnaryOp< Sqrt< T >, VecExpr< A, T, D >, T >, T, D > sqrt(const VecExpr< A, T, D > &rhs)