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) {
249 return x * (high - nominal);
250 }
else if (
x <= -boundary) {
251 return x * (nominal - low);
255 double t =
x / boundary;
256 double eps_plus = high - nominal;
257 double eps_minus = nominal - low;
258 double S = 0.5 * (eps_plus + eps_minus);
259 double A = 0.0625 * (eps_plus - eps_minus);
261 return x * (S + t * A * (15 + t * t * (-10 + t * t * 3)));
262 }
else if (code == 5) {
266 mod = std::pow(high / nominal, +paramVal);
267 }
else if (
x <= -boundary) {
268 mod = std::pow(low / nominal, -paramVal);
271 double x0 = boundary;
277 double powUp = std::pow(high, x0);
278 double powDown = std::pow(low, x0);
279 double logHi = std::log(high);
280 double logLo = std::log(low);
281 double powUpLog = high <= 0.0 ? 0.0 : powUp * logHi;
282 double powDownLog = low <= 0.0 ? 0.0 : -powDown * logLo;
283 double powUpLog2 = high <= 0.0 ? 0.0 : powUpLog * logHi;
284 double powDownLog2 = low <= 0.0 ? 0.0 : -powDownLog * logLo;
286 double S0 = 0.5 * (powUp + powDown);
287 double A0 = 0.5 * (powUp - powDown);
288 double S1 = 0.5 * (powUpLog + powDownLog);
289 double A1 = 0.5 * (powUpLog - powDownLog);
290 double S2 = 0.5 * (powUpLog2 + powDownLog2);
291 double A2 = 0.5 * (powUpLog2 - powDownLog2);
295 double a = 1. / (8 * x0) * (15 * A0 - 7 * x0 *
S1 + x0 * x0 * A2);
296 double b = 1. / (8 * x0 * x0) * (-24 + 24 *
S0 - 9 * x0 * A1 + x0 * x0 * S2);
297 double c = 1. / (4 * std::pow(x0, 3)) * (-5 * A0 + 5 * x0 *
S1 - x0 * x0 * A2);
298 double d = 1. / (4 * std::pow(x0, 4)) * (12 - 12 *
S0 + 7 * x0 * A1 - x0 * x0 * S2);
299 double e = 1. / (8 * std::pow(x0, 5)) * (+3 * A0 - 3 * x0 *
S1 + x0 * x0 * A2);
300 double f = 1. / (8 * std::pow(x0, 6)) * (-8 + 8 *
S0 - 5 * x0 * A1 + x0 * x0 * S2);
306 return res * (mod - 1.0);
312inline double flexibleInterp(
unsigned int code,
double const *params,
unsigned int n,
double const *low,
313 double const *high,
double boundary,
double nominal,
int doCutoff)
315 double total = nominal;
316 for (std::size_t i = 0; i <
n; ++i) {
320 return doCutoff && total <= 0 ? TMath::Limits<double>::Min() :
total;
345inline double nll(
double pdf,
double weight,
int binnedL,
int doBinOffset)
351 if (std::abs(pdf) < 1
e-10 && std::abs(weight) < 1
e-10) {
355 return pdf - weight - weight * (std::log(pdf) - std::log(weight));
359 return -weight * std::log(pdf);
367 for (
unsigned int i = 1; i <
n; ++i) {
376 double t = (
m - m0) /
sigma;
380 double absAlpha = std::abs((
double)alpha);
382 if (t >= -absAlpha) {
383 return std::exp(-0.5 * t * t);
385 double a = std::pow(
n / absAlpha,
n) * std::exp(-0.5 * absAlpha * absAlpha);
386 double b =
n / absAlpha - absAlpha;
388 return a / std::pow(
b - t,
n);
419 double scaledMin = 0.;
420 double scaledMax = 0.;
421 scaledMin = (xMin - mean) / xscale;
422 scaledMax = (xMax - mean) / xscale;
434 double prd = scaledMin * scaledMax;
436 cond = 2.0 - (ecmin + ecmax);
437 }
else if (scaledMax <= 0.0) {
438 cond = ecmax - ecmin;
440 cond = ecmin - ecmax;
442 return resultScale * cond;
450 const double resultScale = 0.5 * std::sqrt(
TMath::TwoPi());
453 return resultScale * (sigmaL * (
TMath::Erf((xMax - mean) / xscaleL) -
TMath::Erf((xMin - mean) / xscaleL)));
454 }
else if (xMin > mean) {
455 return resultScale * (sigmaR * (
TMath::Erf((xMax - mean) / xscaleR) -
TMath::Erf((xMin - mean) / xscaleR)));
464 if (constant == 0.0) {
468 return (std::exp(constant * xMax) - std::exp(constant * xMin)) / constant;
472template <
bool pdfMode = false>
473inline double polynomialIntegral(
double const *coeffs,
int nCoeffs,
int lowestOrder,
double xMin,
double xMax)
475 int denom = lowestOrder + nCoeffs;
476 double min = coeffs[nCoeffs - 1] /
double(denom);
477 double max = coeffs[nCoeffs - 1] /
double(denom);
479 for (
int i = nCoeffs - 2; i >= 0; i--) {
481 min = (coeffs[i] /
double(denom)) + xMin * min;
482 max = (coeffs[i] /
double(denom)) + xMax * max;
485 max = max * std::pow(xMax, 1 + lowestOrder);
486 min = min * std::pow(xMin, 1 + lowestOrder);
488 return max - min + (pdfMode && lowestOrder > 0.0 ? xMax - xMin : 0.0);
494#if defined(FP_FAST_FMA)
495 return std::fma(
x,
y, z);
498#if defined(__clang__)
499#pragma STDC FP_CONTRACT ON
505inline double chebychevIntegral(
double const *coeffs,
unsigned int nCoeffs,
double xMin,
double xMax,
double xMinFull,
508 const double halfrange = .5 * (xMax - xMin);
509 const double mid = .5 * (xMax + xMin);
512 const double b = (xMaxFull - mid) / halfrange;
513 const double a = (xMinFull - mid) / halfrange;
520 const unsigned int iend = nCoeffs;
524 const double c = coeffs[0];
529 double btwox = 2 *
b;
533 double atwox = 2 *
a;
536 double newval = atwox * acurr - alast;
540 newval = btwox * bcurr - blast;
544 for (
unsigned int i = 1; iend != i; ++i) {
546 const double c = coeffs[i];
547 const double term2 = (blast - alast) / nminus1;
549 newval = atwox * acurr - alast;
553 newval = btwox * bcurr - blast;
558 const double term1 = (bcurr - acurr) / (nminus1 + 1.);
559 const double intTn = 0.5 * (term1 - term2);
567 return halfrange *
sum;
572poissonIntegral(
int code,
double mu,
double x,
double integrandMin,
double integrandMax,
unsigned int protectNegative)
574 if (protectNegative && mu < 0.0) {
575 return std::exp(-2.0 * mu);
581 integrandMin = std::max(0., integrandMin);
583 if (integrandMax < 0. || integrandMax < integrandMin) {
586 const double delta = 100.0 * std::sqrt(mu);
590 if (integrandMin < std::max(mu - delta, 0.0) && integrandMax > mu + delta) {
595 const unsigned int ixMin = integrandMin;
596 const unsigned int ixMax = std::min(integrandMax + 1, (
double)std::numeric_limits<unsigned int>::max());
614 const double ix = 1 +
x;
621 const double root2 = std::sqrt(2.);
623 double ln_k = std::abs(std::log(k));
625 0.5 * (
TMath::Erf(std::log(xMax / m0) / (root2 * ln_k)) -
TMath::Erf(std::log(xMin / m0) / (root2 * ln_k)));
632 const double root2 = std::sqrt(2.);
634 double ln_k = std::abs(
sigma);
636 0.5 * (
TMath::Erf((std::log(xMax) - mu) / (root2 * ln_k)) -
TMath::Erf((std::log(xMin) - mu) / (root2 * ln_k)));
643 const double sqrtPiOver2 = 1.2533141373;
644 const double sqrt2 = 1.4142135624;
649 if (std::abs(
n - 1.0) < 1.0e-05)
652 double sig = std::abs(
sigma);
654 double tmin = (mMin - m0) / sig;
655 double tmax = (mMax - m0) / sig;
663 double absAlpha = std::abs(alpha);
665 if (tmin >= -absAlpha) {
667 }
else if (tmax <= -absAlpha) {
668 double a = std::pow(
n / absAlpha,
n) * std::exp(-0.5 * absAlpha * absAlpha);
669 double b =
n / absAlpha - absAlpha;
672 result +=
a * sig * (std::log(
b - tmin) - std::log(
b - tmax));
674 result +=
a * sig / (1.0 -
n) * (1.0 / (std::pow(
b - tmin,
n - 1.0)) - 1.0 / (std::pow(
b - tmax,
n - 1.0)));
677 double a = std::pow(
n / absAlpha,
n) * std::exp(-0.5 * absAlpha * absAlpha);
678 double b =
n / absAlpha - absAlpha;
682 term1 =
a * sig * (std::log(
b - tmin) - std::log(
n / absAlpha));
684 term1 =
a * sig / (1.0 -
n) * (1.0 / (std::pow(
b - tmin,
n - 1.0)) - 1.0 / (std::pow(
n / absAlpha,
n - 1.0)));
687 double term2 = sig * sqrtPiOver2 * (
approxErf(tmax / sqrt2) -
approxErf(-absAlpha / sqrt2));
702 int degree = nCoefs - 1;
705 for (
int i = 0; i <= degree; ++i) {
710 for (
int j = i; j <= degree; ++j) {
712 double oneOverJPlusOne = 1. / (j + 1.);
713 double powDiff = std::pow(xhiScaled, j + 1.) - std::pow(xloScaled, j + 1.);
714 temp += std::pow(-1., j - i) * binCoefs * powDiff * oneOverJPlusOne;
728 for (
int i = 0; i <
n; ++i) {
729 for (
int j = 0; j <
n; ++j) {
730 result += (
x[i] - mu[i]) * covI[i *
n + j] * (
x[j] - mu[j]);
733 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)