14#ifndef RooFit_Detail_MathFuncs_h
15#define RooFit_Detail_MathFuncs_h
33 if (
n < 0 || k < 0 ||
n < k)
38 int k1 = std::min(k,
n - k);
41 for (
double i = k1; i > 1.; --i) {
51 int degree = nCoefs - 1;
56 }
else if (degree == 0) {
58 }
else if (degree == 1) {
61 double a1 = coefs[1] - a0;
62 return a1 * xScaled + a0;
64 }
else if (degree == 2) {
67 double a1 = 2 * (coefs[1] - a0);
68 double a2 = coefs[2] - a1 - a0;
69 return (a2 * xScaled + a1) * xScaled + a0;
73 double s = 1. - xScaled;
75 double result = coefs[0] * s;
76 for (
int i = 1; i < degree; i++) {
80 result += t * coefs[degree];
88 const double arg =
x - mean;
89 const double sig =
sigma;
90 return std::exp(-0.5 * arg * arg / (sig * sig));
93inline double product(
double const *factors, std::size_t nFactors)
96 for (std::size_t i = 0; i < nFactors; ++i) {
103inline double ratio(
double numerator,
double denominator)
105 return numerator / denominator;
108inline double bifurGauss(
double x,
double mean,
double sigmaL,
double sigmaR)
117inline double efficiency(
double effFuncVal,
int catIndex,
int sigCatIndex)
120 effFuncVal = std::clamp(effFuncVal, 0.0, 1.0);
122 if (catIndex == sigCatIndex)
125 return 1 - effFuncVal;
129template <
bool pdfMode = false>
130inline double polynomial(
double const *coeffs,
int nCoeffs,
int lowestOrder,
double x)
132 double retVal = coeffs[nCoeffs - 1];
133 for (
int i = nCoeffs - 2; i >= 0; i--)
134 retVal = coeffs[i] +
x * retVal;
135 retVal = retVal * std::pow(
x, lowestOrder);
136 return retVal + (pdfMode && lowestOrder > 0 ? 1.0 : 0.0);
139inline double chebychev(
double *coeffs,
unsigned int nCoeffs,
double x_in,
double xMin,
double xMax)
142 const double xPrime = (x_in - 0.5 * (xMax + xMin)) / (0.5 * (xMax - xMin));
147 double curr = xPrime;
148 double twox = 2 * xPrime;
150 double newval = twox * curr - last;
153 for (
unsigned int i = 0; nCoeffs != i; ++i) {
154 sum += last * coeffs[i];
155 newval = twox * curr - last;
166 for (
unsigned int i = 0; i < compSize; i++) {
167 sum -= std::log(comp[i]);
174 double binWidth = (high - low) / numBins;
175 return val >= high ? numBins - 1 : std::abs((val - low) / binWidth);
178inline double interpolate1d(
double low,
double high,
double val,
unsigned int numBins,
double const* vals)
180 double binWidth = (high - low) / numBins;
181 int idx = val >= high ? numBins - 1 : std::abs((val - low) / binWidth);
184 double central = low + (idx + 0.5) * binWidth;
185 if (val > low + 0.5 * binWidth && val < high - 0.5 * binWidth) {
188 slope = vals[idx] - vals[idx - 1];
190 slope = vals[idx + 1] - vals[idx];
192 return vals[idx] + slope * (val - central) / binWidth;
205 }
else if (
x == 0.0) {
206 return std::exp(-par);
209 return std::exp(out);
214 double paramVal,
double res)
219 return paramVal * (high - nominal);
221 return paramVal * (nominal - low);
223 }
else if (code == 1) {
226 return res * (std::pow(high / nominal, +paramVal) - 1);
228 return res * (std::pow(low / nominal, -paramVal) - 1);
230 }
else if (code == 2) {
232 double a = 0.5 * (high + low) - nominal;
233 double b = 0.5 * (high - low);
236 return (2 *
a +
b) * (paramVal - 1) + high - nominal;
237 }
else if (paramVal < -1) {
238 return -1 * (2 *
a -
b) * (paramVal + 1) + low - nominal;
240 return a * std::pow(paramVal, 2) +
b * paramVal +
c;
242 }
else if (code == 3) {
244 double a = 0.5 * (high + low) - nominal;
245 double b = 0.5 * (high - low);
248 return (2 *
a +
b) * (paramVal - 1) + high - nominal;
249 }
else if (paramVal < -1) {
250 return -1 * (2 *
a -
b) * (paramVal + 1) + low - nominal;
252 return a * std::pow(paramVal, 2) +
b * paramVal +
c;
254 }
else if (code == 4) {
257 return x * (high - nominal);
258 }
else if (
x <= -boundary) {
259 return x * (nominal - low);
263 double t =
x / boundary;
264 double eps_plus = high - nominal;
265 double eps_minus = nominal - low;
266 double S = 0.5 * (eps_plus + eps_minus);
267 double A = 0.0625 * (eps_plus - eps_minus);
269 return x * (S + t * A * (15 + t * t * (-10 + t * t * 3)));
270 }
else if (code == 5) {
274 mod = std::pow(high / nominal, +paramVal);
275 }
else if (
x <= -boundary) {
276 mod = std::pow(low / nominal, -paramVal);
279 double x0 = boundary;
285 double powUp = std::pow(high, x0);
286 double powDown = std::pow(low, x0);
287 double logHi = std::log(high);
288 double logLo = std::log(low);
289 double powUpLog = high <= 0.0 ? 0.0 : powUp * logHi;
290 double powDownLog = low <= 0.0 ? 0.0 : -powDown * logLo;
291 double powUpLog2 = high <= 0.0 ? 0.0 : powUpLog * logHi;
292 double powDownLog2 = low <= 0.0 ? 0.0 : -powDownLog * logLo;
294 double S0 = 0.5 * (powUp + powDown);
295 double A0 = 0.5 * (powUp - powDown);
296 double S1 = 0.5 * (powUpLog + powDownLog);
297 double A1 = 0.5 * (powUpLog - powDownLog);
298 double S2 = 0.5 * (powUpLog2 + powDownLog2);
299 double A2 = 0.5 * (powUpLog2 - powDownLog2);
303 double a = 1. / (8 * x0) * (15 * A0 - 7 * x0 *
S1 + x0 * x0 * A2);
304 double b = 1. / (8 * x0 * x0) * (-24 + 24 *
S0 - 9 * x0 * A1 + x0 * x0 * S2);
305 double c = 1. / (4 * std::pow(x0, 3)) * (-5 * A0 + 5 * x0 *
S1 - x0 * x0 * A2);
306 double d = 1. / (4 * std::pow(x0, 4)) * (12 - 12 *
S0 + 7 * x0 * A1 - x0 * x0 * S2);
307 double e = 1. / (8 * std::pow(x0, 5)) * (+3 * A0 - 3 * x0 *
S1 + x0 * x0 * A2);
308 double f = 1. / (8 * std::pow(x0, 6)) * (-8 + 8 *
S0 - 5 * x0 * A1 + x0 * x0 * S2);
314 return res * (mod - 1.0);
320inline double flexibleInterp(
unsigned int code,
double const *params,
unsigned int n,
double const *low,
321 double const *high,
double boundary,
double nominal,
int doCutoff)
323 double total = nominal;
324 for (std::size_t i = 0; i <
n; ++i) {
328 return doCutoff && total <= 0 ? TMath::Limits<double>::Min() :
total;
353inline double nll(
double pdf,
double weight,
int binnedL,
int doBinOffset)
359 if (std::abs(pdf) < 1
e-10 && std::abs(weight) < 1
e-10) {
363 return pdf - weight - weight * (std::log(pdf) - std::log(weight));
367 return -weight * std::log(pdf);
375 for (
unsigned int i = 1; i <
n; ++i) {
384 double t = (
m - m0) /
sigma;
388 double absAlpha = std::abs((
double)alpha);
390 if (t >= -absAlpha) {
391 return std::exp(-0.5 * t * t);
393 double a = std::pow(
n / absAlpha,
n) * std::exp(-0.5 * absAlpha * absAlpha);
394 double b =
n / absAlpha - absAlpha;
396 return a / std::pow(
b - t,
n);
427 double scaledMin = 0.;
428 double scaledMax = 0.;
429 scaledMin = (xMin - mean) / xscale;
430 scaledMax = (xMax - mean) / xscale;
442 double prd = scaledMin * scaledMax;
444 cond = 2.0 - (ecmin + ecmax);
445 }
else if (scaledMax <= 0.0) {
446 cond = ecmax - ecmin;
448 cond = ecmin - ecmax;
450 return resultScale * cond;
458 const double resultScale = 0.5 * std::sqrt(
TMath::TwoPi());
461 return resultScale * (sigmaL * (
TMath::Erf((xMax - mean) / xscaleL) -
TMath::Erf((xMin - mean) / xscaleL)));
462 }
else if (xMin > mean) {
463 return resultScale * (sigmaR * (
TMath::Erf((xMax - mean) / xscaleR) -
TMath::Erf((xMin - mean) / xscaleR)));
472 if (constant == 0.0) {
476 return (std::exp(constant * xMax) - std::exp(constant * xMin)) / constant;
480template <
bool pdfMode = false>
481inline double polynomialIntegral(
double const *coeffs,
int nCoeffs,
int lowestOrder,
double xMin,
double xMax)
483 int denom = lowestOrder + nCoeffs;
484 double min = coeffs[nCoeffs - 1] /
double(denom);
485 double max = coeffs[nCoeffs - 1] /
double(denom);
487 for (
int i = nCoeffs - 2; i >= 0; i--) {
489 min = (coeffs[i] /
double(denom)) + xMin * min;
490 max = (coeffs[i] /
double(denom)) + xMax * max;
493 max = max * std::pow(xMax, 1 + lowestOrder);
494 min = min * std::pow(xMin, 1 + lowestOrder);
496 return max - min + (pdfMode && lowestOrder > 0.0 ? xMax - xMin : 0.0);
502#if defined(FP_FAST_FMA)
503 return std::fma(
x,
y, z);
506#if defined(__clang__)
507#pragma STDC FP_CONTRACT ON
513inline double chebychevIntegral(
double const *coeffs,
unsigned int nCoeffs,
double xMin,
double xMax,
double xMinFull,
516 const double halfrange = .5 * (xMax - xMin);
517 const double mid = .5 * (xMax + xMin);
520 const double b = (xMaxFull - mid) / halfrange;
521 const double a = (xMinFull - mid) / halfrange;
528 const unsigned int iend = nCoeffs;
532 const double c = coeffs[0];
537 double btwox = 2 *
b;
541 double atwox = 2 *
a;
544 double newval = atwox * acurr - alast;
548 newval = btwox * bcurr - blast;
552 for (
unsigned int i = 1; iend != i; ++i) {
554 const double c = coeffs[i];
555 const double term2 = (blast - alast) / nminus1;
557 newval = atwox * acurr - alast;
561 newval = btwox * bcurr - blast;
566 const double term1 = (bcurr - acurr) / (nminus1 + 1.);
567 const double intTn = 0.5 * (term1 - term2);
575 return halfrange *
sum;
580poissonIntegral(
int code,
double mu,
double x,
double integrandMin,
double integrandMax,
unsigned int protectNegative)
582 if (protectNegative && mu < 0.0) {
583 return std::exp(-2.0 * mu);
589 integrandMin = std::max(0., integrandMin);
591 if (integrandMax < 0. || integrandMax < integrandMin) {
594 const double delta = 100.0 * std::sqrt(mu);
598 if (integrandMin < std::max(mu - delta, 0.0) && integrandMax > mu + delta) {
603 const unsigned int ixMin = integrandMin;
604 const unsigned int ixMax = std::min(integrandMax + 1, (
double)std::numeric_limits<unsigned int>::max());
622 const double ix = 1 +
x;
629 const double root2 = std::sqrt(2.);
631 double ln_k = std::abs(std::log(k));
633 0.5 * (
TMath::Erf(std::log(xMax / m0) / (root2 * ln_k)) -
TMath::Erf(std::log(xMin / m0) / (root2 * ln_k)));
640 const double root2 = std::sqrt(2.);
642 double ln_k = std::abs(
sigma);
644 0.5 * (
TMath::Erf((std::log(xMax) - mu) / (root2 * ln_k)) -
TMath::Erf((std::log(xMin) - mu) / (root2 * ln_k)));
651 const double sqrtPiOver2 = 1.2533141373;
652 const double sqrt2 = 1.4142135624;
657 if (std::abs(
n - 1.0) < 1.0e-05)
660 double sig = std::abs(
sigma);
662 double tmin = (mMin - m0) / sig;
663 double tmax = (mMax - m0) / sig;
671 double absAlpha = std::abs(alpha);
673 if (tmin >= -absAlpha) {
675 }
else if (tmax <= -absAlpha) {
676 double a = std::pow(
n / absAlpha,
n) * std::exp(-0.5 * absAlpha * absAlpha);
677 double b =
n / absAlpha - absAlpha;
680 result +=
a * sig * (std::log(
b - tmin) - std::log(
b - tmax));
682 result +=
a * sig / (1.0 -
n) * (1.0 / (std::pow(
b - tmin,
n - 1.0)) - 1.0 / (std::pow(
b - tmax,
n - 1.0)));
685 double a = std::pow(
n / absAlpha,
n) * std::exp(-0.5 * absAlpha * absAlpha);
686 double b =
n / absAlpha - absAlpha;
690 term1 =
a * sig * (std::log(
b - tmin) - std::log(
n / absAlpha));
692 term1 =
a * sig / (1.0 -
n) * (1.0 / (std::pow(
b - tmin,
n - 1.0)) - 1.0 / (std::pow(
n / absAlpha,
n - 1.0)));
695 double term2 = sig * sqrtPiOver2 * (
approxErf(tmax / sqrt2) -
approxErf(-absAlpha / sqrt2));
710 int degree = nCoefs - 1;
713 for (
int i = 0; i <= degree; ++i) {
718 for (
int j = i; j <= degree; ++j) {
720 double oneOverJPlusOne = 1. / (j + 1.);
721 double powDiff = std::pow(xhiScaled, j + 1.) - std::pow(xloScaled, j + 1.);
722 temp += std::pow(-1., j - i) * binCoefs * powDiff * oneOverJPlusOne;
static unsigned int total
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
double lognormal_pdf(double x, double m, double s, double x0=0)
Probability density function of the lognormal distribution.
double landau_pdf(double x, double xi=1, double x0=0)
Probability density function of the Landau distribution:
double gamma_cdf_c(double x, double alpha, double theta, double x0=0)
Complement of the cumulative distribution function of the gamma distribution (upper tail).
double gamma_cdf(double x, double alpha, double theta, double x0=0)
Cumulative distribution function of the gamma distribution (lower tail).
double logNormalIntegral(double xMin, double xMax, double m0, double k)
double gaussianIntegral(double xMin, double xMax, double mean, double sigma)
Function to calculate the integral of an un-normalized RooGaussian over x.
double chebychevIntegral(double const *coeffs, unsigned int nCoeffs, double xMin, double xMax, double xMinFull, double xMaxFull)
double bifurGaussIntegral(double xMin, double xMax, double mean, double sigmaL, double sigmaR)
double cbShape(double m, double m0, double sigma, double alpha, double n)
double polynomial(double const *coeffs, int nCoeffs, int lowestOrder, double x)
In pdfMode, a coefficient for the constant term of 1.0 is implied if lowestOrder > 0.
double recursiveFraction(double *a, unsigned int n)
double constraintSum(double const *comp, unsigned int compSize)
double cbShapeIntegral(double mMin, double mMax, double m0, double sigma, double alpha, double n)
double fast_fma(double x, double y, double z) noexcept
use fast FMA if available, fall back to normal arithmetic if not
double logNormalIntegralStandard(double xMin, double xMax, double mu, double sigma)
double landau(double x, double mu, double sigma)
double gaussian(double x, double mean, double sigma)
Function to evaluate an un-normalized RooGaussian.
double product(double const *factors, std::size_t nFactors)
double chebychev(double *coeffs, unsigned int nCoeffs, double x_in, double xMin, double xMax)
double poisson(double x, double par)
double binomial(int n, int k)
Calculates the binomial coefficient n over k.
unsigned int getUniformBinning(double low, double high, double val, unsigned int numBins)
double flexibleInterpSingle(unsigned int code, double low, double high, double boundary, double nominal, double paramVal, double res)
double interpolate1d(double low, double high, double val, unsigned int numBins, double const *vals)
double logNormalStandard(double x, double sigma, double mu)
double bifurGauss(double x, double mean, double sigmaL, double sigmaR)
double ratio(double numerator, double denominator)
double polynomialIntegral(double const *coeffs, int nCoeffs, int lowestOrder, double xMin, double xMax)
In pdfMode, a coefficient for the constant term of 1.0 is implied if lowestOrder > 0.
double bernsteinIntegral(double xlo, double xhi, double xmin, double xmax, double *coefs, int nCoefs)
double approxErf(double arg)
double effProd(double eff, double pdf)
double poissonIntegral(int code, double mu, double x, double integrandMin, double integrandMax, unsigned int protectNegative)
double logNormal(double x, double k, double m0)
double nll(double pdf, double weight, int binnedL, int doBinOffset)
double bernstein(double x, double xmin, double xmax, double *coefs, int nCoefs)
The caller needs to make sure that there is at least one coefficient.
double efficiency(double effFuncVal, int catIndex, int sigCatIndex)
double flexibleInterp(unsigned int code, double const *params, unsigned int n, double const *low, double const *high, double boundary, double nominal, int doCutoff)
double exponentialIntegral(double xMin, double xMax, double constant)
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Double_t Erf(Double_t x)
Computation of the error function erf(x).
Double_t QuietNaN()
Returns a quiet NaN as defined by IEEE 754.
constexpr Double_t Sqrt2()
Double_t Erfc(Double_t x)
Computes the complementary error function erfc(x).
Double_t LnGamma(Double_t z)
Computation of ln[gamma(z)] for all z.
Double_t SignalingNaN()
Returns a signaling NaN as defined by IEEE 754](http://en.wikipedia.org/wiki/NaN#Signaling_NaN).
constexpr Double_t TwoPi()
static uint64_t sum(uint64_t i)