|
|
|||
File indexing completed on 2025-12-16 10:29:37
0001 // @(#)root/mathcore:$Id$ 0002 // Authors: Andras Zsenei & Lorenzo Moneta 06/2005 0003 0004 /********************************************************************** 0005 * * 0006 * Copyright (c) 2005 , LCG ROOT MathLib Team * 0007 * * 0008 * * 0009 **********************************************************************/ 0010 0011 /** 0012 0013 Probability density functions, cumulative distribution functions 0014 and their inverses (quantiles) for various statistical distributions (continuous and discrete). 0015 Whenever possible the conventions followed are those of the 0016 CRC Concise Encyclopedia of Mathematics, Second Edition 0017 (or <A HREF="http://mathworld.wolfram.com/">Mathworld</A>). 0018 By convention the distributions are centered around 0, so for 0019 example in the case of a Gaussian there is no parameter mu. The 0020 user must calculate the shift themselves if they wish. 0021 0022 MathCore provides the majority of the probability density functions, of the 0023 cumulative distributions and of the quantiles (inverses of the cumulatives). 0024 Additional distributions are also provided by the \ref MathMore library. 0025 0026 0027 @defgroup StatFunc Statistical functions 0028 @ingroup MathCore 0029 */ 0030 0031 #ifndef ROOT_Math_PdfFuncMathCore 0032 #define ROOT_Math_PdfFuncMathCore 0033 0034 #include "Math/Math.h" 0035 #include "Math/SpecFuncMathCore.h" 0036 0037 #include <limits> 0038 0039 namespace ROOT { 0040 namespace Math { 0041 0042 0043 0044 /** @defgroup PdfFunc Probability Density Functions (PDF) 0045 * @ingroup StatFunc 0046 * Probability density functions of various statistical distributions 0047 * (continuous and discrete). 0048 * The probability density function returns the probability that 0049 * the variate has the value x. 0050 * In statistics the PDF is also called the frequency function. 0051 * 0052 * 0053 */ 0054 0055 /** @name Probability Density Functions from MathCore 0056 * Additional PDFs are provided in the MathMore library when the GSL is available. 0057 */ 0058 0059 //@{ 0060 0061 /** 0062 0063 Probability density function of the beta distribution. 0064 0065 \f[ p(x) = \frac{\Gamma (a + b) } {\Gamma(a)\Gamma(b) } x ^{a-1} (1 - x)^{b-1} \f] 0066 0067 for \f$0 \leq x \leq 1 \f$. For detailed description see 0068 <A HREF="http://mathworld.wolfram.com/BetaDistribution.html"> 0069 Mathworld</A>. 0070 0071 @ingroup PdfFunc 0072 0073 */ 0074 0075 inline double beta_pdf(double x, double a, double b) { 0076 // Inlined to enable clad-auto-derivation for this function. 0077 0078 if (x < 0 || x > 1.0) return 0; 0079 if (x == 0 ) { 0080 // need this work Windows 0081 if (a < 1) return std::numeric_limits<double>::infinity(); 0082 else if (a > 1) return 0; 0083 else if ( a == 1) return b; // to avoid a nan from log(0)*0 0084 } 0085 if (x == 1 ) { 0086 // need this work Windows 0087 if (b < 1) return std::numeric_limits<double>::infinity(); 0088 else if (b > 1) return 0; 0089 else if ( b == 1) return a; // to avoid a nan from log(0)*0 0090 } 0091 return std::exp( ROOT::Math::lgamma(a + b) - ROOT::Math::lgamma(a) - ROOT::Math::lgamma(b) + 0092 std::log(x) * (a -1.) + ROOT::Math::log1p(-x ) * (b - 1.) ); 0093 } 0094 0095 0096 0097 /** 0098 0099 Probability density function of the binomial distribution. 0100 0101 \f[ p(k) = \frac{n!}{k! (n-k)!} p^k (1-p)^{n-k} \f] 0102 0103 for \f$ 0 \leq k \leq n \f$. For detailed description see 0104 <A HREF="http://mathworld.wolfram.com/BinomialDistribution.html"> 0105 Mathworld</A>. 0106 0107 @ingroup PdfFunc 0108 0109 */ 0110 0111 inline double binomial_pdf(unsigned int k, double p, unsigned int n) { 0112 // Inlined to enable clad-auto-derivation for this function. 0113 if (k > n) 0114 return 0.0; 0115 0116 double coeff = ROOT::Math::lgamma(n+1) - ROOT::Math::lgamma(k+1) - ROOT::Math::lgamma(n-k+1); 0117 return std::exp(coeff + k * std::log(p) + (n - k) * ROOT::Math::log1p(-p)); 0118 } 0119 0120 0121 0122 /** 0123 0124 Probability density function of the negative binomial distribution. 0125 0126 \f[ p(k) = \frac{(k+n-1)!}{k! (n-1)!} p^{n} (1-p)^{k} \f] 0127 0128 For detailed description see 0129 <A HREF="http://mathworld.wolfram.com/NegativeBinomialDistribution.html"> 0130 Mathworld</A> (where \f$k \to x\f$ and \f$n \to r\f$). 0131 The distribution in <A HREF="http://en.wikipedia.org/wiki/Negative_binomial_distribution"> 0132 Wikipedia</A> is defined with a \f$p\f$ corresponding to \f$1-p\f$ in this case. 0133 0134 0135 @ingroup PdfFunc 0136 0137 */ 0138 0139 inline double negative_binomial_pdf(unsigned int k, double p, double n) { 0140 // Inlined to enable clad-auto-derivation for this function. 0141 0142 // implement in term of gamma function 0143 0144 if (n < 0) return 0.0; 0145 if (p < 0 || p > 1.0) return 0.0; 0146 0147 double coeff = ROOT::Math::lgamma(k+n) - ROOT::Math::lgamma(k+1.0) - ROOT::Math::lgamma(n); 0148 return std::exp(coeff + n * std::log(p) + double(k) * ROOT::Math::log1p(-p)); 0149 0150 } 0151 0152 0153 0154 0155 /** 0156 0157 Probability density function of Breit-Wigner distribution, which is similar, just 0158 a different definition of the parameters, to the Cauchy distribution 0159 (see #cauchy_pdf ) 0160 0161 \f[ p(x) = \frac{1}{\pi} \frac{\frac{1}{2} \Gamma}{x^2 + (\frac{1}{2} \Gamma)^2} \f] 0162 0163 0164 @ingroup PdfFunc 0165 0166 */ 0167 0168 inline double breitwigner_pdf(double x, double gamma, double x0 = 0) { 0169 // Inlined to enable clad-auto-derivation for this function. 0170 double gammahalf = gamma/2.0; 0171 return gammahalf/(M_PI * ((x-x0)*(x-x0) + gammahalf*gammahalf)); 0172 } 0173 0174 0175 0176 0177 /** 0178 0179 Probability density function of the Cauchy distribution which is also 0180 called Lorentzian distribution. 0181 0182 0183 \f[ p(x) = \frac{1}{\pi} \frac{ b }{ (x-m)^2 + b^2} \f] 0184 0185 For detailed description see 0186 <A HREF="http://mathworld.wolfram.com/CauchyDistribution.html"> 0187 Mathworld</A>. It is also related to the #breitwigner_pdf which 0188 will call the same implementation. 0189 0190 @ingroup PdfFunc 0191 0192 */ 0193 0194 inline double cauchy_pdf(double x, double b = 1, double x0 = 0) { 0195 0196 return b/(M_PI * ((x-x0)*(x-x0) + b*b)); 0197 0198 } 0199 0200 0201 0202 0203 /** 0204 0205 Probability density function of the \f$\chi^2\f$ distribution with \f$r\f$ 0206 degrees of freedom. 0207 0208 \f[ p_r(x) = \frac{1}{\Gamma(r/2) 2^{r/2}} x^{r/2-1} e^{-x/2} \f] 0209 0210 for \f$x \geq 0\f$. For detailed description see 0211 <A HREF="http://mathworld.wolfram.com/Chi-SquaredDistribution.html"> 0212 Mathworld</A>. 0213 0214 @ingroup PdfFunc 0215 0216 */ 0217 0218 inline double chisquared_pdf(double x, double r, double x0 = 0) { 0219 // Inlined to enable clad-auto-derivation for this function. 0220 0221 if ((x-x0) < 0) { 0222 return 0.0; 0223 } 0224 double a = r/2 -1.; 0225 // let return inf for case x = x0 and treat special case of r = 2 otherwise will return nan 0226 if (x == x0 && a == 0) return 0.5; 0227 0228 return std::exp ((r/2 - 1) * std::log((x-x0)/2) - (x-x0)/2 - ROOT::Math::lgamma(r/2))/2; 0229 0230 } 0231 0232 0233 /** 0234 0235 Crystal ball function 0236 0237 See the definition at 0238 <A HREF="http://en.wikipedia.org/wiki/Crystal_Ball_function"> 0239 Wikipedia</A>. 0240 0241 It is not really a pdf since it is not normalized 0242 0243 @ingroup PdfFunc 0244 0245 */ 0246 0247 inline double crystalball_function(double x, double alpha, double n, double sigma, double mean = 0) { 0248 // Inlined to enable clad-auto-derivation for this function. 0249 0250 // evaluate the crystal ball function 0251 if (sigma < 0.) return 0.; 0252 double z = (x - mean)/sigma; 0253 if (alpha < 0) z = -z; 0254 double abs_alpha = std::abs(alpha); 0255 // double C = n/abs_alpha * 1./(n-1.) * std::exp(-alpha*alpha/2.); 0256 // double D = std::sqrt(M_PI/2.)*(1.+ROOT::Math::erf(abs_alpha/std::sqrt(2.))); 0257 // double N = 1./(sigma*(C+D)); 0258 if (z > - abs_alpha) 0259 return std::exp(- 0.5 * z * z); 0260 //double A = std::pow(n/abs_alpha,n) * std::exp(-0.5*abs_alpha*abs_alpha); 0261 double nDivAlpha = n/abs_alpha; 0262 double AA = std::exp(-0.5*abs_alpha*abs_alpha); 0263 double B = nDivAlpha -abs_alpha; 0264 double arg = nDivAlpha/(B-z); 0265 return AA * std::pow(arg,n); 0266 } 0267 0268 /** 0269 pdf definition of the crystal_ball which is defined only for n > 1 otherwise integral is diverging 0270 */ 0271 inline double crystalball_pdf(double x, double alpha, double n, double sigma, double mean = 0) { 0272 // Inlined to enable clad-auto-derivation for this function. 0273 0274 // evaluation of the PDF ( is defined only for n >1) 0275 if (sigma < 0.) return 0.; 0276 if ( n <= 1) return std::numeric_limits<double>::quiet_NaN(); // pdf is not normalized for n <=1 0277 double abs_alpha = std::abs(alpha); 0278 double C = n/abs_alpha * 1./(n-1.) * std::exp(-alpha*alpha/2.); 0279 double D = std::sqrt(M_PI/2.)*(1.+ROOT::Math::erf(abs_alpha/std::sqrt(2.))); 0280 double N = 1./(sigma*(C+D)); 0281 return N * crystalball_function(x,alpha,n,sigma,mean); 0282 } 0283 0284 /** 0285 0286 Probability density function of the exponential distribution. 0287 0288 \f[ p(x) = \lambda e^{-\lambda x} \f] 0289 0290 for x>0. For detailed description see 0291 <A HREF="http://mathworld.wolfram.com/ExponentialDistribution.html"> 0292 Mathworld</A>. 0293 0294 0295 @ingroup PdfFunc 0296 0297 */ 0298 0299 inline double exponential_pdf(double x, double lambda, double x0 = 0) { 0300 // Inlined to enable clad-auto-derivation for this function. 0301 0302 if ((x-x0) < 0) 0303 return 0.0; 0304 return lambda * std::exp (-lambda * (x-x0)); 0305 } 0306 0307 0308 0309 0310 /** 0311 0312 Probability density function of the F-distribution. 0313 0314 \f[ p_{n,m}(x) = \frac{\Gamma(\frac{n+m}{2})}{\Gamma(\frac{n}{2}) \Gamma(\frac{m}{2})} n^{n/2} m^{m/2} x^{n/2 -1} (m+nx)^{-(n+m)/2} \f] 0315 0316 for x>=0. For detailed description see 0317 <A HREF="http://mathworld.wolfram.com/F-Distribution.html"> 0318 Mathworld</A>. 0319 0320 @ingroup PdfFunc 0321 0322 */ 0323 0324 0325 inline double fdistribution_pdf(double x, double n, double m, double x0 = 0) { 0326 // Inlined to enable clad-auto-derivation for this function. 0327 0328 // function is defined only for both n and m > 0 0329 if (n < 0 || m < 0) 0330 return std::numeric_limits<double>::quiet_NaN(); 0331 if ((x-x0) < 0) 0332 return 0.0; 0333 0334 return std::exp((n/2) * std::log(n) + (m/2) * std::log(m) + ROOT::Math::lgamma((n+m)/2) - ROOT::Math::lgamma(n/2) - ROOT::Math::lgamma(m/2) 0335 + (n/2 -1) * std::log(x-x0) - ((n+m)/2) * std::log(m + n*(x-x0)) ); 0336 0337 } 0338 0339 0340 0341 0342 /** 0343 0344 Probability density function of the gamma distribution. 0345 0346 \f[ p(x) = {1 \over \Gamma(\alpha) \theta^{\alpha}} x^{\alpha-1} e^{-x/\theta} \f] 0347 0348 for x>0. For detailed description see 0349 <A HREF="http://mathworld.wolfram.com/GammaDistribution.html"> 0350 Mathworld</A>. 0351 0352 @ingroup PdfFunc 0353 0354 */ 0355 0356 inline double gamma_pdf(double x, double alpha, double theta, double x0 = 0) { 0357 // Inlined to enable clad-auto-derivation for this function. 0358 0359 if ((x-x0) < 0) { 0360 return 0.0; 0361 } else if ((x-x0) == 0) { 0362 0363 if (alpha == 1) { 0364 return 1.0/theta; 0365 } else { 0366 return 0.0; 0367 } 0368 0369 } else if (alpha == 1) { 0370 return std::exp(-(x-x0)/theta)/theta; 0371 } else { 0372 return std::exp((alpha - 1) * std::log((x-x0)/theta) - (x-x0)/theta - ROOT::Math::lgamma(alpha))/theta; 0373 } 0374 0375 } 0376 0377 0378 0379 0380 /** 0381 0382 Probability density function of the normal (Gaussian) distribution with mean x0 and standard deviation sigma. 0383 0384 \f[ p(x) = {1 \over \sqrt{2 \pi \sigma^2}} e^{-(x-x_0)^2 / 2\sigma^2} \f] 0385 0386 For detailed description see 0387 <A HREF="http://mathworld.wolfram.com/NormalDistribution.html"> 0388 Mathworld</A>. It can also be evaluated using #normal_pdf which will 0389 call the same implementation. 0390 0391 @ingroup PdfFunc 0392 0393 */ 0394 0395 inline double gaussian_pdf(double x, double sigma = 1, double x0 = 0) { 0396 0397 double tmp = (x-x0)/sigma; 0398 return (1.0/(std::sqrt(2 * M_PI) * std::abs(sigma))) * std::exp(-tmp*tmp/2); 0399 } 0400 0401 /** 0402 0403 Probability density function of the bi-dimensional (Gaussian) distribution. 0404 0405 \f[ p(x,y) = {1 \over 2 \pi \sigma_x \sigma_y \sqrt{1-\rho^2}} \exp (-((x-x0)^2/\sigma_x^2 + (y-y0)^2/\sigma_y^2 - 2 \rho x y/(\sigma_x\sigma_y))/2(1-\rho^2)) \f] 0406 0407 For detailed description see 0408 <A HREF="http://mathworld.wolfram.com/BivariateNormalDistribution.html"> 0409 Mathworld</A>. It can also be evaluated using #normal_pdf which will 0410 call the same implementation. 0411 0412 @param x x variable 0413 @param y y variable 0414 @param sigmax the stdev in x 0415 @param sigmay the stdev in y 0416 @param rho correlation, must be between -1,1 0417 @param x0 the offset in x 0418 @param y0 the offset in y 0419 0420 @ingroup PdfFunc 0421 0422 */ 0423 0424 inline double bigaussian_pdf(double x, double y, double sigmax = 1, double sigmay = 1, double rho = 0, double x0 = 0, double y0 = 0) { 0425 double u = (x-x0)/sigmax; 0426 double v = (y-y0)/sigmay; 0427 double c = 1. - rho*rho; 0428 double z = u*u - 2.*rho*u*v + v*v; 0429 return 1./(2 * M_PI * sigmax * sigmay * std::sqrt(c) ) * std::exp(- z / (2. * c) ); 0430 } 0431 0432 /** 0433 0434 Probability density function of the Landau distribution: 0435 \f[ p(x) = \frac{1}{\xi} \phi (\lambda) \f] 0436 with 0437 \f[ \phi(\lambda) = \frac{1}{2 \pi i}\int_{c-i\infty}^{c+i\infty} e^{\lambda s + s \log{s}} ds\f] 0438 where \f$\lambda = (x-x_0)/\xi\f$. For a detailed description see 0439 K.S. Kölbig and B. Schorr, A program package for the Landau distribution, 0440 <A HREF="http://dx.doi.org/10.1016/0010-4655(84)90085-7">Computer Phys. Comm. 31 (1984) 97-111</A> 0441 <A HREF="http://dx.doi.org/10.1016/j.cpc.2008.03.002">[Erratum-ibid. 178 (2008) 972]</A>. 0442 The same algorithms as in 0443 <A HREF="https://cern-tex.web.cern.ch/cern-tex/shortwrupsdir/g110/top.html"> 0444 CERNLIB</A> (DENLAN) is used 0445 0446 @param x The argument \f$x\f$ 0447 @param xi The width parameter \f$\xi\f$ 0448 @param x0 The location parameter \f$x_0\f$ 0449 0450 @ingroup PdfFunc 0451 0452 */ 0453 0454 double landau_pdf(double x, double xi = 1, double x0 = 0); 0455 0456 0457 0458 /** 0459 0460 Probability density function of the lognormal distribution. 0461 0462 \f[ p(x) = {1 \over x \sqrt{2 \pi s^2} } e^{-(\ln{x} - m)^2/2 s^2} \f] 0463 0464 for x>0. For detailed description see 0465 <A HREF="http://mathworld.wolfram.com/LogNormalDistribution.html"> 0466 Mathworld</A>. 0467 @param x x variable 0468 @param m M = 0 for lognormal 0469 @param s scale parameter (not the sigma of the distribution which is not even defined) 0470 @param x0 location parameter, corresponds approximately to the most probable value. For x0 = 0, sigma = 1, the x_mpv = -0.22278 0471 0472 @ingroup PdfFunc 0473 0474 */ 0475 0476 inline double lognormal_pdf(double x, double m, double s, double x0 = 0) { 0477 // Inlined to enable clad-auto-derivation for this function. 0478 if ((x-x0) <= 0) 0479 return 0.0; 0480 double tmp = (std::log((x-x0)) - m)/s; 0481 return 1.0 / ((x-x0) * std::abs(s) * std::sqrt(2 * M_PI)) * std::exp(-(tmp * tmp) /2); 0482 } 0483 0484 0485 0486 0487 /** 0488 0489 Probability density function of the normal (Gaussian) distribution with mean x0 and standard deviation sigma. 0490 0491 \f[ p(x) = {1 \over \sqrt{2 \pi \sigma^2}} e^{-(x-x_0)^2 / 2\sigma^2} \f] 0492 0493 For detailed description see 0494 <A HREF="http://mathworld.wolfram.com/NormalDistribution.html"> 0495 Mathworld</A>. It can also be evaluated using #gaussian_pdf which will call the same 0496 implementation. 0497 0498 @ingroup PdfFunc 0499 0500 */ 0501 0502 inline double normal_pdf(double x, double sigma =1, double x0 = 0) { 0503 // Inlined to enable clad-auto-derivation for this function. 0504 0505 double tmp = (x-x0)/sigma; 0506 return (1.0/(std::sqrt(2 * M_PI) * std::abs(sigma))) * std::exp(-tmp*tmp/2); 0507 0508 } 0509 0510 0511 /** 0512 0513 Probability density function of the Poisson distribution. 0514 0515 \f[ p(n) = \frac{\mu^n}{n!} e^{- \mu} \f] 0516 0517 For detailed description see 0518 <A HREF="http://mathworld.wolfram.com/PoissonDistribution.html"> 0519 Mathworld</A>. 0520 0521 @ingroup PdfFunc 0522 0523 */ 0524 0525 inline double poisson_pdf(unsigned int n, double mu) { 0526 // Inlined to enable clad-auto-derivation for this function. 0527 0528 if (n > 0 && mu >= 0) 0529 return std::exp (n*std::log(mu) - ROOT::Math::lgamma(n+1) - mu); 0530 0531 // when n = 0 and mu = 0, 1 is returned 0532 if (mu >= 0) 0533 return std::exp(-mu); 0534 0535 // return a nan for mu < 0 since it does not make sense 0536 return std::numeric_limits<double>::quiet_NaN(); 0537 } 0538 0539 0540 0541 0542 /** 0543 0544 Probability density function of Student's t-distribution. 0545 0546 \f[ p_{r}(x) = \frac{\Gamma(\frac{r+1}{2})}{\sqrt{r \pi}\Gamma(\frac{r}{2})} \left( 1+\frac{x^2}{r}\right)^{-(r+1)/2} \f] 0547 0548 for \f$r \geq 0\f$. For detailed description see 0549 <A HREF="http://mathworld.wolfram.com/Studentst-Distribution.html"> 0550 Mathworld</A>. 0551 0552 @ingroup PdfFunc 0553 0554 */ 0555 0556 inline double tdistribution_pdf(double x, double r, double x0 = 0) { 0557 // Inlined to enable clad-auto-derivation for this function. 0558 0559 return (std::exp (ROOT::Math::lgamma((r + 1.0)/2.0) - ROOT::Math::lgamma(r/2.0)) / std::sqrt (M_PI * r)) 0560 * std::pow ((1.0 + (x-x0)*(x-x0)/r), -(r + 1.0)/2.0); 0561 0562 } 0563 0564 0565 0566 0567 /** 0568 0569 Probability density function of the uniform (flat) distribution. 0570 0571 \f[ p(x) = {1 \over (b-a)} \f] 0572 0573 if \f$a \leq x<b\f$ and 0 otherwise. For detailed description see 0574 <A HREF="http://mathworld.wolfram.com/UniformDistribution.html"> 0575 Mathworld</A>. 0576 0577 @ingroup PdfFunc 0578 0579 */ 0580 0581 inline double uniform_pdf(double x, double a, double b, double x0 = 0) { 0582 // Inlined to enable clad-auto-derivation for this function. 0583 0584 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! when a=b 0585 0586 if ((x-x0) < b && (x-x0) >= a) 0587 return 1.0/(b - a); 0588 return 0.0; 0589 0590 } 0591 0592 0593 0594 } // namespace Math 0595 } // namespace ROOT 0596 0597 0598 0599 #endif // ROOT_Math_PdfFunc
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|