CLHEP 2.4.6.4
C++ Class Library for High Energy Physics
Loading...
Searching...
No Matches
CLHEP::HepStat Class Reference

#include <Stat.h>

Static Public Member Functions

static double flatToGaussian (double r)
 
static double inverseErf (double t)
 
static double erf (double x)
 
static double erfQ (double x)
 
static double gammln (double x)
 

Detailed Description

Author

Definition at line 53 of file Stat.h.

Member Function Documentation

◆ erf()

double CLHEP::HepStat::erf ( double  x)
static

Definition at line 275 of file flatToGaussian.cc.

275 {
276
277// Math:
278//
279// For any given x we can "quickly" find t0 = erfQ (x) = erf(x) + epsilon.
280//
281// Then we can find x1 = inverseErf (t0) = inverseErf (erf(x)+epsilon)
282//
283// Expanding in the small epsion,
284//
285// x1 = x + epsilon * [deriv(inverseErf(u),u) at u = t0] + O(epsilon**2)
286//
287// so epsilon is (x1-x) / [deriv(inverseErf(u),u) at u = t0] + O(epsilon**2)
288//
289// But the derivative of an inverse function is one over the derivative of the
290// function, so
291// epsilon = (x1-x) * [deriv(erf(v),v) at v = x] + O(epsilon**2)
292//
293// And the definition of the erf integral makes that derivative trivial.
294// Ultimately,
295//
296// erf(x) = erfQ(x) - (inverseErf(erfQ(x))-x) * std::exp(-x**2) * 2/std::sqrt(CLHEP::pi)
297//
298
299 double t0 = erfQ(x);
300 double deriv = std::exp(-x*x) * (2.0 / std::sqrt(CLHEP::pi));
301
302 return t0 - (inverseErf (t0) - x) * deriv;
303
304}
static double erfQ(double x)
Definition: erfQ.cc:25
static double inverseErf(double t)

◆ erfQ()

double CLHEP::HepStat::erfQ ( double  x)
static

Definition at line 25 of file erfQ.cc.

25 {
26//
27// erfQ is accurate to 7 places.
28// See Numerical Recipes P 221
29//
30
31 double t, z, erfc;
32
33 z = std::abs(x);
34 t = 1.0/(1.0+.5*z);
35
36 erfc= t*std::exp(-z*z-1.26551223+t*(1.00002368+t*(0.37409196+t*(0.09678418+
37 t*(-0.18628806+t*(0.27886807+t*(-1.13520398+t*(1.48851587+
38 t*(-0.82215223+t*0.17087277 ))) ))) )));
39
40 // (The derivation of this formula should be obvious.)
41
42 if ( x < 0 ) erfc = 2.0 - erfc;
43
44 return 1 - erfc;
45
46}

Referenced by erf().

◆ flatToGaussian()

double CLHEP::HepStat::flatToGaussian ( double  r)
static

Definition at line 92 of file flatToGaussian.cc.

92 {
93
94 double sign = +1.0; // We always compute a negative number of
95 // sigmas. For r > 0 we will multiply by
96 // sign = -1 to return a positive number.
97#ifdef Trace1
98std::cout << "r = " << r << "\n";
99#endif
100
101 if ( r > .5 ) {
102 r = 1-r;
103 sign = -1.0;
104#ifdef Trace1
105std::cout << "r = " << r << "sign negative \n";
106#endif
107 } else if ( r == .5 ) {
108 return 0.0;
109 }
110
111 // Find a pointer to the proper table entries, along with the fraction
112 // of the way in the relevant bin dx and the bin size h.
113
114 // Optimize for the case of table 4 by testing for that first.
115 // By removing that case from the for loop below, we save not only
116 // several table lookups, but also several index calculations that
117 // now become (compile-time) constants.
118 //
119 // Past the case of table 4, we need not be as concerned about speed since
120 // this will happen only .1% of the time.
121
122 const double* tptr = 0;
123 double dx = 0;
124 double h = 0;
125
126 // The following big if block will locate tptr, h, and dx from whichever
127 // table is applicable:
128
129 int index;
130
131 if ( r >= Table4step ) {
132
133 index = int((Table4size<<1) * r); // 1 to Table4size-1
134 if (index <= 0) index = 1; // in case of rounding problem
135 if (index >= Table4size) index = Table4size-1;
136 dx = (Table4size<<1) * r - index; // fraction of way to next bin
137 h = Table4step;
138#ifdef Trace2
139std::cout << "index = " << index << " dx = " << dx << " h = " << h << "\n";
140#endif
141 index = (index<<1) + (Table4offset-2);
142 // at r = table4step+eps, index refers to the start of table 4
143 // and at r = .5 - eps, index refers to the next-to-last entry:
144 // remember, the table has two numbers per actual entry.
145#ifdef Trace2
146std::cout << "offset index = " << index << "\n";
147#endif
148
149 tptr = &gaussTables [index];
150
151 } else if (r < Tsteps[0]) {
152
153 // If r is so small none of the tables apply, use the asymptotic formula.
154 return (sign * transformSmall (r));
155
156 } else {
157
158 for ( int tableN = 3; tableN >= 0; tableN-- ) {
159 if ( r < Tsteps[tableN] ) {continue;} // can't happen when tableN==0
160#ifdef Trace2
161std::cout << "Using table " << tableN << "\n";
162#endif
163 double step = Tsteps[tableN];
164 index = int(r/step); // 1 to TableNsize-1
165 // The following two tests should probably never be true, but
166 // roundoff might cause index to be outside its proper range.
167 // In such a case, the interpolation still makes sense, but we
168 // need to take care that tptr points to valid data in the right table.
169 if (index == 0) index = 1;
170 if (index >= Tsizes[tableN]) index = Tsizes[tableN] - 1;
171 dx = r/step - index; // fraction of way to next bin
172 h = step;
173#ifdef Trace2
174std::cout << "index = " << index << " dx = " << dx << " h = " << h << "\n";
175#endif
176 index = (index<<1) + Toffsets[tableN] - 2;
177 tptr = &gaussTables [index];
178 break;
179 } // end of the for loop which finds tptr, dx and h in one of the tables
180
181 // The code can only get to here by a break statement, having set dx etc.
182 // It not get to here without going through one of the breaks,
183 // because before the for loop we test for the case of r < Tsteps[0].
184
185 } // End of the big if block.
186
187 // At the end of this if block, we have tptr, dx and h -- and if r is less
188 // than the smallest step, we have already returned the proper answer.
189
190 double y0 = *tptr++;
191 double d0 = *tptr++;
192 double y1 = *tptr++;
193 double d1 = *tptr;
194
195#ifdef Trace3
196std::cout << "y0: " << y0 << " y1: " << y1 << " d0: " << d0 << " d1: " << d1 << "\n";
197#endif
198
199 double x2 = dx * dx;
200 double oneMinusX = 1 - dx;
201 double oneMinusX2 = oneMinusX * oneMinusX;
202
203 double f0 = (2. * dx + 1.) * oneMinusX2;
204 double f1 = (3. - 2. * dx) * x2;
205 double g0 = h * dx * oneMinusX2;
206 double g1 = - h * oneMinusX * x2;
207
208#ifdef Trace3
209std::cout << "f0: " << f0 << " f1: " << f1 << " g0: " << g0 << " g1: " << g1 << "\n";
210#endif
211
212 double answer = f0 * y0 + f1 * y1 + g0 * d0 + g1 * d1;
213
214#ifdef Trace1
215std::cout << "variate is: " << sign*answer << "\n";
216#endif
217
218 return sign * answer;
219
220} // flatToGaussian
#define Table4step
#define Table4offset
#define Table4size
double transformSmall(double r)

Referenced by inverseErf(), and CLHEP::RandGaussT::operator()().

◆ gammln()

double CLHEP::HepStat::gammln ( double  x)
static

Definition at line 20 of file gammln.cc.

20 {
21
22// Returns the value ln(Gamma(xx) for xx > 0. Full accuracy is obtained for
23// xx > 1. For 0 < xx < 1. the reflection formula (6.1.4) can be used first.
24// (Adapted from Numerical Recipes in C. Relative to that routine, this
25// subtracts one from x at the very start, and in exchange does not have to
26// divide ser by x at the end. The results are formally equal, and practically
27// indistinguishable.)
28
29 static const double cof[6] = {76.18009172947146,-86.50532032941677,
30 24.01409824083091, -1.231739572450155,
31 0.1208650973866179e-2, -0.5395239384953e-5};
32 int j;
33 double x = xx - 1.0;
34 double tmp = x + 5.5;
35 tmp -= (x + 0.5) * std::log(tmp);
36 double ser = 1.000000000190015;
37
38 for ( j = 0; j <= 5; j++ ) {
39 x += 1.0;
40 ser += cof[j]/x;
41 }
42 return -tmp + std::log(2.5066282746310005*ser);
43}

◆ inverseErf()

double CLHEP::HepStat::inverseErf ( double  t)
static

Definition at line 266 of file flatToGaussian.cc.

266 {
267
268 // This uses erf(x) = 2*gaussCDF(std::sqrt(2)*x) - 1
269
270 return std::sqrt(0.5) * flatToGaussian(.5*(t+1));
271
272}
static double flatToGaussian(double r)

Referenced by erf().


The documentation for this class was generated from the following files: