Jpp 19.3.0-rc.5
the software that should make you happy
Loading...
Searching...
No Matches
JMath/JMathSupportkit.hh
Go to the documentation of this file.
1#ifndef __JMATHSUPPORTKIT__
2#define __JMATHSUPPORTKIT__
3
4#include <limits>
5#include <cmath>
6
7#include "JMath/JConstants.hh"
8#include "JLang/JException.hh"
9
10
11/**
12 * \file
13 *
14 * Auxiliary methods for mathematics.
15 * \author mdejong
16 */
17
18namespace JMATH {}
19namespace JPP { using namespace JMATH; }
20
21namespace JMATH {
22
24
25
26 /**
27 * Determine factorial.
28 *
29 * \param n number
30 * \return factorial (= n!)
31 */
32 inline long long int factorial(const long long int n)
33 {
34 if (n < 0) {
35 THROW(JValueOutOfRange, "JMATH::factorial(): invalid argument " << n);
36 }
37
38 if (n != 1)
39 return n * factorial(n - 1);
40 else
41 return 1;
42 }
43
44
45 /**
46 * Determine combinatorics.
47 *
48 * \param n number
49 * \param m number
50 * \return n!/(m!*(n-m)!)
51 */
52 inline long long int factorial(const long long int n, const long long int m)
53 {
54 if (n < 0 || m < 0 || n < m) {
55 THROW(JValueOutOfRange, "JMATH::factorial(): invalid argument " << n << ' ' << m);
56 }
57
58 if (n == m)
59 return 1;
60 else if (m == 0)
61 return 1;
62 else
63 return factorial(n - 1, m - 1) + factorial(n - 1, m);
64 }
65
66
67 /**
68 * Gauss function (normalised to 1 at x = 0).
69 *
70 * \param x x
71 * \param sigma sigma
72 * \return function value
73 */
74 inline double gauss(const double x, const double sigma)
75 {
76 const double u = x / sigma;
77
78 if (fabs(u) < 20.0)
79 return exp(-0.5*u*u);
80 else
81 return 0.0;
82 }
83
84
85 /**
86 * Gauss function (normalised to 1 at x = x0).
87 *
88 * \param x x
89 * \param x0 central value
90 * \param sigma sigma
91 * \return function value
92 */
93 inline double gauss(const double x, const double x0, const double sigma)
94 {
95 return gauss(x - x0, sigma);
96 }
97
98
99 /**
100 * Normalised Gauss function.
101 *
102 * \param x x
103 * \param sigma sigma
104 * \return function value
105 */
106 inline double Gauss(const double x, const double sigma)
107 {
108 return gauss(x, sigma) / sqrt(2.0*PI) / sigma;
109 }
110
111
112 /**
113 * Normalised Gauss function.
114 *
115 * \param x x
116 * \param x0 central value
117 * \param sigma sigma
118 * \return function value
119 */
120 inline double Gauss(const double x, const double x0, const double sigma)
121 {
122 return Gauss(x - x0, sigma);
123 }
124
125
126 /**
127 * Incomplete gamma function.
128 *
129 * Source code is taken from reference:
130 * Numerical Recipes in C++, W.H. Press, S.A. Teukolsky, W.T. Vetterling and B.P. Flannery,
131 * Cambridge University Press.
132 *
133 * \param a a
134 * \param x x
135 * \return function value
136 */
137 inline double Gamma(const double a, const double x)
138 {
139 using namespace std;
140
141 const int max = 1000000;
142
143 if (x < 0.0) { THROW(JValueOutOfRange, "x < 0 " << x); }
144 if (a <= 0.0) { THROW(JValueOutOfRange, "a <= 0 " << a); }
145
146 const double gln = lgamma(a);
147
148 if (x < a + 1.0) {
149
150 if (x < 0.0) {
151 THROW(JValueOutOfRange, "x <= 0 " << x);
152 }
153
154 if (x == 0.0) {
155 return 0.0;
156 }
157
158 double ap = a;
159 double sum = 1.0 / a;
160 double del = sum;
161
162 for (int i = 0; i != max; ++i) {
163
164 ap += 1.0;
165 del *= x/ap;
166 sum += del;
167
168 if (fabs(del) < fabs(sum)*numeric_limits<double>::epsilon()) {
169 return sum*exp(-x + a*log(x) - gln);
170 }
171 }
172
173 THROW(JValueOutOfRange, "i == " << max);
174
175 } else {
176
177 const double FPMIN = numeric_limits<double>::min() / numeric_limits<double>::epsilon();
178
179 double b = x + 1.0 - a;
180 double c = 1.0 / FPMIN;
181 double d = 1.0 / b;
182 double h = d;
183
184 for (int i = 1; i != max; ++i) {
185
186 const double an = -i * (i-a);
187
188 b += 2.0;
189 d = an*d + b;
190
191 if (fabs(d) < FPMIN) {
192 d = FPMIN;
193 }
194
195 c = b + an/c;
196
197 if (fabs(c) < FPMIN) {
198 c = FPMIN;
199 }
200
201 d = 1.0/d;
202
203 const double del = d*c;
204
205 h *= del;
206
207 if (fabs(del - 1.0) < numeric_limits<double>::epsilon()) {
208 return 1.0 - exp(-x + a*log(x) - gln) * h;
209 }
210 }
211
212 THROW(JValueOutOfRange, "i == " << max);
213 }
214 }
215
216
217 /**
218 * Legendre polynome.
219 *
220 * \param n degree
221 * \param x x
222 * \return function value
223 */
224 inline double legendre(const size_t n, const double x)
225 {
226 switch (n) {
227
228 case 0:
229 return 1.0;
230
231 case 1:
232 return x;
233
234 default:
235 {
236 double p0;
237 double p1 = 1.0;
238 double p2 = x;
239
240 for (size_t i = 2; i <= n; ++i) {
241 p0 = p1;
242 p1 = p2;
243 p2 = ((2*i-1) * x*p1 - (i-1) * p0) / i;
244 }
245
246 return p2;
247 }
248 }
249 }
250
251
252 /**
253 * Binomial function.
254 *
255 * \param n n
256 * \param k k
257 * \return function value
258 */
259 inline double binomial(const size_t n, const size_t k)
260 {
261 if (n == 0 || n < k) {
262 return 0.0;
263 }
264
265 if (k == 0 || n == k) {
266 return 1.0;
267 }
268
269 const int k1 = std::min(k, n - k);
270 const int k2 = n - k1;
271
272 double value = k2 + 1;
273
274 for (int i = k1; i != 1; --i) {
275 value *= (double) (k2 + i) / (double) i;
276 }
277
278 return value;
279 }
280
281
282 /**
283 * Poisson probability density distribition.
284 *
285 * \param n number of occurences
286 * \param mu expectation value
287 * \return probability
288 */
289 inline double poisson(const size_t n, const double mu)
290 {
291 using namespace std;
292
293 if (mu > 0.0) {
294
295 if (n > 0)
296 return exp(n*log(mu) - lgamma(n+1) - mu);
297 else
298 return exp(-mu);
299 } else if (mu == 0.0) {
300
301 return (n == 0 ? 1.0 : 0.0);
302 }
303
304 THROW(JValueOutOfRange, "mu <= 0 " << mu);
305 }
306
307
308 /**
309 * Poisson cumulative density distribition.
310 *
311 * \param n number of occurences
312 * \param mu expectation value
313 * \return probability
314 */
315 inline double Poisson(const size_t n, const double mu)
316 {
317 return 1.0 - Gamma(n + 1, mu);
318 }
319
320
321 /**
322 * Get single-sided Gaussian probability for given number of standard deviations.
323 *
324 * \param stdev number of standard deviations
325 * \return probability
326 */
327 inline double getP(const double stdev)
328 {
329 return (2.0 * // single-sided Gauss
330 0.5 * // compensate factor 2 in C++ erfc
331 erfc(stdev / sqrt(2.0))); // compensate absent 1/2 in exponent of Gauss in C++ erfc
332 }
333
334
335 /**
336 * Get minimal number of events to exceed Poisson probability given number of background events.
337 *
338 * \param background number of background events
339 * \param P probability
340 * \return number of events
341 */
342 inline size_t getNs(const double background,
343 const double P)
344 {
345 double y = exp(-background);
346 double Y = y; // P(0)
347 size_t k = 1;
348
349 for ( ; Y < 1.0 - P; ++k) {
350 y *= background / (double) k; // P(k)
351 Y += y;
352 }
353
354 return k;
355 }
356
357
358 /**
359 * Get minimal number of events to exceed Poisson probability given number of background events.
360 * The precision refers to a step size.
361 * When set to one, the result is identical to that of method JMATH::getNs.
362 *
363 * \param background number of background events
364 * \param P probability
365 * \param precision precision
366 * \return number of events
367 */
368 inline double getFs(const double background,
369 const double P,
370 const double precision)
371 {
372 double u = 1.0 + floor(background);
373
374 for ( ; Gamma(u, background) > P; u += precision) {}
375
376 return u;
377 }
378}
379
380#endif
TPaveText * p1
Exceptions.
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Mathematical constants.
Exception for accessing a value in a collection that is outside of its range.
Auxiliary classes and methods for mathematical operations.
Definition JEigen3D.hh:88
double Gamma(const double a, const double x)
Incomplete gamma function.
double Gauss(const double x, const double sigma)
Normalised Gauss function.
long long int factorial(const long long int n)
Determine factorial.
double poisson(const size_t n, const double mu)
Poisson probability density distribition.
size_t getNs(const double background, const double P)
Get minimal number of events to exceed Poisson probability given number of background events.
double getP(const double stdev)
Get single-sided Gaussian probability for given number of standard deviations.
double gauss(const double x, const double sigma)
Gauss function (normalised to 1 at x = 0).
double getFs(const double background, const double P, const double precision)
Get minimal number of events to exceed Poisson probability given number of background events.
double Poisson(const size_t n, const double mu)
Poisson cumulative density distribition.
double legendre(const size_t n, const double x)
Legendre polynome.
double binomial(const size_t n, const size_t k)
Binomial function.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).