41 Double_t RooCBShape::ApproxErf(Double_t arg)
const
43 static const double erflim = 5.0;
49 return RooMath::erf(arg);
54 RooCBShape::RooCBShape(
const char *name,
const char *title,
55 RooAbsReal& _m, RooAbsReal& _m0, RooAbsReal& _sigma,
56 RooAbsReal& _alpha, RooAbsReal& _n) :
57 RooAbsPdf(name, title),
58 m(
"m",
"Dependent", this, _m),
59 m0(
"m0",
"M0", this, _m0),
60 sigma(
"sigma",
"Sigma", this, _sigma),
61 alpha(
"alpha",
"Alpha", this, _alpha),
62 n(
"n",
"Order", this, _n)
68 RooCBShape::RooCBShape(
const RooCBShape& other,
const char* name) :
69 RooAbsPdf(other, name), m(
"m", this, other.m), m0(
"m0", this, other.m0),
70 sigma(
"sigma", this, other.sigma), alpha(
"alpha", this, other.alpha),
77 Double_t RooCBShape::evaluate()
const {
78 Double_t t = (m-m0)/sigma;
79 if (alpha < 0) t = -t;
81 Double_t absAlpha = fabs((Double_t)alpha);
87 Double_t a = TMath::Power(n/absAlpha,n)*exp(-0.5*absAlpha*absAlpha);
88 Double_t b= n/absAlpha - absAlpha;
90 return a/TMath::Power(b - t, n);
99 template<
class Tm,
class Tm0,
class Tsigma,
class Talpha,
class Tn>
100 void compute(
size_t batchSize,
101 double * __restrict output,
102 Tm M, Tm0 M0, Tsigma S, Talpha A, Tn N)
104 for (
size_t i=0; i<batchSize; i++) {
105 const double t = (M[i]-M0[i]) / S[i];
106 if ((A[i]>0 && t>=-A[i]) || (A[i]<0 && -t>=A[i])) {
107 output[i] = -0.5*t*t;
109 output[i] = N[i] / (N[i] -A[i]*A[i] -A[i]*t);
110 output[i] = _rf_fast_log(output[i]);
112 output[i] -= 0.5*A[i]*A[i];
116 for (
size_t i=0; i<batchSize; i++) {
117 output[i] = _rf_fast_exp(output[i]);
122 RooSpan<double> RooCBShape::evaluateBatch(std::size_t begin, std::size_t batchSize)
const {
123 using namespace BatchHelpers;
125 EvaluateInfo info = getInfo( {&m, &m0, &sigma, &alpha, &n}, begin, batchSize );
126 if (info.nBatches == 0) {
129 auto output = _batchData.makeWritableBatchUnInit(begin, batchSize);
130 auto mData = m.getValBatch(begin, info.size);
132 if (info.nBatches==1 && !mData.empty()) {
133 compute(info.size, output.data(), mData.data(),
134 BracketAdapter<double> (m0),
135 BracketAdapter<double> (sigma),
136 BracketAdapter<double> (alpha),
137 BracketAdapter<double> (n));
140 compute(info.size, output.data(),
141 BracketAdapterWithMask (m,m.getValBatch(begin,info.size)),
142 BracketAdapterWithMask (m0,m0.getValBatch(begin,info.size)),
143 BracketAdapterWithMask (sigma,sigma.getValBatch(begin,info.size)),
144 BracketAdapterWithMask (alpha,alpha.getValBatch(begin,info.size)),
145 BracketAdapterWithMask (n,n.getValBatch(begin,info.size)));
152 Int_t RooCBShape::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars,
const char* )
const
154 if( matchArgs(allVars,analVars,m) )
162 Double_t RooCBShape::analyticalIntegral(Int_t code,
const char* rangeName)
const
164 static const double sqrtPiOver2 = 1.2533141373;
165 static const double sqrt2 = 1.4142135624;
171 if( fabs(n-1.0) < 1.0e-05 )
174 double sig = fabs((Double_t)sigma);
176 double tmin = (m.min(rangeName)-m0)/sig;
177 double tmax = (m.max(rangeName)-m0)/sig;
185 double absAlpha = fabs((Double_t)alpha);
187 if( tmin >= -absAlpha ) {
188 result += sig*sqrtPiOver2*( ApproxErf(tmax/sqrt2)
189 - ApproxErf(tmin/sqrt2) );
191 else if( tmax <= -absAlpha ) {
192 double a = TMath::Power(n/absAlpha,n)*exp(-0.5*absAlpha*absAlpha);
193 double b = n/absAlpha - absAlpha;
196 result += a*sig*( log(b-tmin) - log(b-tmax) );
199 result += a*sig/(1.0-n)*( 1.0/(TMath::Power(b-tmin,n-1.0))
200 - 1.0/(TMath::Power(b-tmax,n-1.0)) );
204 double a = TMath::Power(n/absAlpha,n)*exp(-0.5*absAlpha*absAlpha);
205 double b = n/absAlpha - absAlpha;
209 term1 = a*sig*( log(b-tmin) - log(n/absAlpha));
212 term1 = a*sig/(1.0-n)*( 1.0/(TMath::Power(b-tmin,n-1.0))
213 - 1.0/(TMath::Power(n/absAlpha,n-1.0)) );
216 double term2 = sig*sqrtPiOver2*( ApproxErf(tmax/sqrt2)
217 - ApproxErf(-absAlpha/sqrt2) );
220 result += term1 + term2;
223 return result != 0. ? result : 1.E-300;
229 Int_t RooCBShape::getMaxVal(
const RooArgSet& vars)
const
233 if (matchArgs(vars,dummy,m)) {
241 Double_t RooCBShape::maxVal(Int_t code)
const