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;
246 }
else if (code == 4 || code == 6) {
255 mod =
x * (high - nominal);
256 }
else if (
x <= -boundary) {
257 mod =
x * (nominal - low);
260 double t =
x / boundary;
261 double eps_plus = high - nominal;
262 double eps_minus = nominal - low;
263 double S = 0.5 * (eps_plus + eps_minus);
264 double A = 0.0625 * (eps_plus - eps_minus);
266 mod =
x * (S + t * A * (15 + t * t * (-10 + t * t * 3)));
275 }
else if (code == 5) {
279 mod = std::pow(high / nominal, +paramVal);
280 }
else if (
x <= -boundary) {
281 mod = std::pow(low / nominal, -paramVal);
284 double x0 = boundary;
290 double powUp = std::pow(high, x0);
291 double powDown = std::pow(low, x0);
292 double logHi = std::log(high);
293 double logLo = std::log(low);
294 double powUpLog = high <= 0.0 ? 0.0 : powUp * logHi;
295 double powDownLog = low <= 0.0 ? 0.0 : -powDown * logLo;
296 double powUpLog2 = high <= 0.0 ? 0.0 : powUpLog * logHi;
297 double powDownLog2 = low <= 0.0 ? 0.0 : -powDownLog * logLo;
299 double S0 = 0.5 * (powUp + powDown);
300 double A0 = 0.5 * (powUp - powDown);
301 double S1 = 0.5 * (powUpLog + powDownLog);
302 double A1 = 0.5 * (powUpLog - powDownLog);
303 double S2 = 0.5 * (powUpLog2 + powDownLog2);
304 double A2 = 0.5 * (powUpLog2 - powDownLog2);
308 double a = 1. / (8 * x0) * (15 * A0 - 7 * x0 *
S1 + x0 * x0 * A2);
309 double b = 1. / (8 * x0 * x0) * (-24 + 24 *
S0 - 9 * x0 * A1 + x0 * x0 * S2);
310 double c = 1. / (4 * std::pow(x0, 3)) * (-5 * A0 + 5 * x0 *
S1 - x0 * x0 * A2);
311 double d = 1. / (4 * std::pow(x0, 4)) * (12 - 12 *
S0 + 7 * x0 * A1 - x0 * x0 * S2);
312 double e = 1. / (8 * std::pow(x0, 5)) * (+3 * A0 - 3 * x0 *
S1 + x0 * x0 * A2);
313 double f = 1. / (8 * std::pow(x0, 6)) * (-8 + 8 *
S0 - 5 * x0 * A1 + x0 * x0 * S2);
319 return res * (mod - 1.0);
325inline double flexibleInterp(
unsigned int code,
double const *params,
unsigned int n,
double const *low,
326 double const *high,
double boundary,
double nominal,
int doCutoff)
328 double total = nominal;
329 for (std::size_t i = 0; i <
n; ++i) {
333 return doCutoff && total <= 0 ? TMath::Limits<double>::Min() :
total;
358inline double nll(
double pdf,
double weight,
int binnedL,
int doBinOffset)
364 if (std::abs(pdf) < 1
e-10 && std::abs(weight) < 1
e-10) {
368 return pdf - weight - weight * (std::log(pdf) - std::log(weight));
372 return -weight * std::log(pdf);
380 for (
unsigned int i = 1; i <
n; ++i) {
389 double t = (
m - m0) /
sigma;
393 double absAlpha = std::abs((
double)alpha);
395 if (t >= -absAlpha) {
396 return std::exp(-0.5 * t * t);
398 double a = std::pow(
n / absAlpha,
n) * std::exp(-0.5 * absAlpha * absAlpha);
399 double b =
n / absAlpha - absAlpha;
401 return a / std::pow(
b - t,
n);
432 double scaledMin = 0.;
433 double scaledMax = 0.;
434 scaledMin = (xMin - mean) / xscale;
435 scaledMax = (xMax - mean) / xscale;
447 double prd = scaledMin * scaledMax;
449 cond = 2.0 - (ecmin + ecmax);
450 }
else if (scaledMax <= 0.0) {
451 cond = ecmax - ecmin;
453 cond = ecmin - ecmax;
455 return resultScale * cond;
463 const double resultScale = 0.5 * std::sqrt(
TMath::TwoPi());
466 return resultScale * (sigmaL * (
TMath::Erf((xMax - mean) / xscaleL) -
TMath::Erf((xMin - mean) / xscaleL)));
467 }
else if (xMin > mean) {
468 return resultScale * (sigmaR * (
TMath::Erf((xMax - mean) / xscaleR) -
TMath::Erf((xMin - mean) / xscaleR)));
477 if (constant == 0.0) {
481 return (std::exp(constant * xMax) - std::exp(constant * xMin)) / constant;
485template <
bool pdfMode = false>
486inline double polynomialIntegral(
double const *coeffs,
int nCoeffs,
int lowestOrder,
double xMin,
double xMax)
488 int denom = lowestOrder + nCoeffs;
489 double min = coeffs[nCoeffs - 1] /
double(denom);
490 double max = coeffs[nCoeffs - 1] /
double(denom);
492 for (
int i = nCoeffs - 2; i >= 0; i--) {
494 min = (coeffs[i] /
double(denom)) + xMin * min;
495 max = (coeffs[i] /
double(denom)) + xMax * max;
498 max = max * std::pow(xMax, 1 + lowestOrder);
499 min = min * std::pow(xMin, 1 + lowestOrder);
501 return max - min + (pdfMode && lowestOrder > 0.0 ? xMax - xMin : 0.0);
507#if defined(FP_FAST_FMA)
508 return std::fma(
x,
y, z);
511#if defined(__clang__)
512#pragma STDC FP_CONTRACT ON
518inline double chebychevIntegral(
double const *coeffs,
unsigned int nCoeffs,
double xMin,
double xMax,
double xMinFull,
521 const double halfrange = .5 * (xMax - xMin);
522 const double mid = .5 * (xMax + xMin);
525 const double b = (xMaxFull - mid) / halfrange;
526 const double a = (xMinFull - mid) / halfrange;
533 const unsigned int iend = nCoeffs;
537 const double c = coeffs[0];
542 double btwox = 2 *
b;
546 double atwox = 2 *
a;
549 double newval = atwox * acurr - alast;
553 newval = btwox * bcurr - blast;
557 for (
unsigned int i = 1; iend != i; ++i) {
559 const double c = coeffs[i];
560 const double term2 = (blast - alast) / nminus1;
562 newval = atwox * acurr - alast;
566 newval = btwox * bcurr - blast;
571 const double term1 = (bcurr - acurr) / (nminus1 + 1.);
572 const double intTn = 0.5 * (term1 - term2);
580 return halfrange *
sum;
585poissonIntegral(
int code,
double mu,
double x,
double integrandMin,
double integrandMax,
unsigned int protectNegative)
587 if (protectNegative && mu < 0.0) {
588 return std::exp(-2.0 * mu);
594 integrandMin = std::max(0., integrandMin);
596 if (integrandMax < 0. || integrandMax < integrandMin) {
599 const double delta = 100.0 * std::sqrt(mu);
603 if (integrandMin < std::max(mu - delta, 0.0) && integrandMax > mu + delta) {
608 const unsigned int ixMin = integrandMin;
609 const unsigned int ixMax = std::min(integrandMax + 1, (
double)std::numeric_limits<unsigned int>::max());
627 const double ix = 1 +
x;
634 const double root2 = std::sqrt(2.);
636 double ln_k = std::abs(std::log(k));
638 0.5 * (
TMath::Erf(std::log(xMax / m0) / (root2 * ln_k)) -
TMath::Erf(std::log(xMin / m0) / (root2 * ln_k)));
645 const double root2 = std::sqrt(2.);
647 double ln_k = std::abs(
sigma);
649 0.5 * (
TMath::Erf((std::log(xMax) - mu) / (root2 * ln_k)) -
TMath::Erf((std::log(xMin) - mu) / (root2 * ln_k)));
656 const double sqrtPiOver2 = 1.2533141373;
657 const double sqrt2 = 1.4142135624;
662 if (std::abs(
n - 1.0) < 1.0e-05)
665 double sig = std::abs(
sigma);
667 double tmin = (mMin - m0) / sig;
668 double tmax = (mMax - m0) / sig;
676 double absAlpha = std::abs(alpha);
678 if (tmin >= -absAlpha) {
680 }
else if (tmax <= -absAlpha) {
681 double a = std::pow(
n / absAlpha,
n) * std::exp(-0.5 * absAlpha * absAlpha);
682 double b =
n / absAlpha - absAlpha;
685 result +=
a * sig * (std::log(
b - tmin) - std::log(
b - tmax));
687 result +=
a * sig / (1.0 -
n) * (1.0 / (std::pow(
b - tmin,
n - 1.0)) - 1.0 / (std::pow(
b - tmax,
n - 1.0)));
690 double a = std::pow(
n / absAlpha,
n) * std::exp(-0.5 * absAlpha * absAlpha);
691 double b =
n / absAlpha - absAlpha;
695 term1 =
a * sig * (std::log(
b - tmin) - std::log(
n / absAlpha));
697 term1 =
a * sig / (1.0 -
n) * (1.0 / (std::pow(
b - tmin,
n - 1.0)) - 1.0 / (std::pow(
n / absAlpha,
n - 1.0)));
700 double term2 = sig * sqrtPiOver2 * (
approxErf(tmax / sqrt2) -
approxErf(-absAlpha / sqrt2));
715 int degree = nCoefs - 1;
718 for (
int i = 0; i <= degree; ++i) {
723 for (
int j = i; j <= degree; ++j) {
725 double oneOverJPlusOne = 1. / (j + 1.);
726 double powDiff = std::pow(xhiScaled, j + 1.) - std::pow(xloScaled, j + 1.);
727 temp += std::pow(-1., j - i) * binCoefs * powDiff * oneOverJPlusOne;
741 for (
int i = 0; i <
n; ++i) {
742 for (
int j = 0; j <
n; ++j) {
743 result += (
x[i] - mu[i]) * covI[i *
n + j] * (
x[j] - mu[j]);
746 return std::exp(-0.5 *
result);
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 inc_gamma_c(double a, double x)
Calculates the normalized (regularized) upper incomplete gamma function (upper integral)
double inc_gamma(double a, double x)
Calculates the normalized (regularized) lower incomplete gamma function (lower integral)
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 multiVarGaussian(int n, const double *x, const double *mu, const double *covI)
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)