Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/clhep/src/flatToGaussian.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /externals/clhep/src/flatToGaussian.cc (Version 11.3.0) and /externals/clhep/src/flatToGaussian.cc (Version 10.1.p3)


                                                   >>   1 // $Id:$
  1 // -*- C++ -*-                                      2 // -*- C++ -*-
  2 //                                                  3 //
  3 // -------------------------------------------      4 // -----------------------------------------------------------------------
  4 //                             HEP Random           5 //                             HEP Random
  5 //                          --- flatToGaussian      6 //                          --- flatToGaussian ---
  6 //                      class implementation f      7 //                      class implementation file
  7 // -------------------------------------------      8 // -----------------------------------------------------------------------
  8                                                     9 
  9 // Contains the methods that depend on the 30K     10 // Contains the methods that depend on the 30K-footpring gaussTables.cdat.
 10 //                                                 11 //
 11 // flatToGaussian (double x)                       12 // flatToGaussian (double x)
 12 // inverseErf     (double x)                       13 // inverseErf     (double x)
 13 // erf      (double x)                             14 // erf      (double x)
 14                                                    15 
 15 // ===========================================     16 // =======================================================================
 16 // M Fischler   - Created 1/25/00.                 17 // M Fischler   - Created 1/25/00.
 17 //                                                 18 //
 18 // ===========================================     19 // =======================================================================
 19                                                    20 
 20 #include "CLHEP/Random/Stat.h"                     21 #include "CLHEP/Random/Stat.h"
 21 #include "CLHEP/Units/PhysicalConstants.h"         22 #include "CLHEP/Units/PhysicalConstants.h"
 22 #include <iostream>                                23 #include <iostream>
 23 #include <cmath>                                   24 #include <cmath>
 24                                                    25 
 25 namespace CLHEP {                                  26 namespace CLHEP {
 26                                                    27 
 27 double transformSmall (double r);                  28 double transformSmall (double r);
 28                                                    29 
 29 //                                                 30 //
 30 // Table of errInts, for use with transform(r)     31 // Table of errInts, for use with transform(r) and quickTransform(r)
 31 //                                                 32 //
 32                                                    33 
 33 #ifdef Traces                                      34 #ifdef Traces
 34 #define Trace1                                     35 #define Trace1
 35 #define Trace2                                     36 #define Trace2
 36 #define Trace3                                     37 #define Trace3
 37 #endif                                             38 #endif
 38                                                    39 
 39 // Since all these are this is static to this      40 // Since all these are this is static to this compilation unit only, the 
 40 // info is establised a priori and not at each     41 // info is establised a priori and not at each invocation.
 41                                                    42 
 42 // The main data is of course the gaussTables      43 // The main data is of course the gaussTables table; the rest is all 
 43 // bookkeeping to know what the tables mean.       44 // bookkeeping to know what the tables mean.
 44                                                    45 
 45 #define Table0size   200                           46 #define Table0size   200
 46 #define Table1size   250                           47 #define Table1size   250
 47 #define Table2size   200                           48 #define Table2size   200
 48 #define Table3size   250                           49 #define Table3size   250
 49 #define Table4size  1000                           50 #define Table4size  1000
 50 #define TableSize   (Table0size+Table1size+Tab     51 #define TableSize   (Table0size+Table1size+Table2size+Table3size+Table4size)
 51                                                    52 
 52 static const int Tsizes[5] =   { Table0size,       53 static const int Tsizes[5] =   { Table0size,
 53          Table1size,                               54          Table1size,
 54          Table2size,                               55          Table2size,
 55          Table3size,                               56          Table3size,
 56          Table4size };                             57          Table4size };
 57                                                    58 
 58 #define Table0step  (2.0E-13)                      59 #define Table0step  (2.0E-13)
 59 #define Table1step  (4.0E-11)                      60 #define Table1step  (4.0E-11)  
 60 #define Table2step  (1.0E-8)                       61 #define Table2step  (1.0E-8) 
 61 #define Table3step  (2.0E-6)                       62 #define Table3step  (2.0E-6) 
 62 #define Table4step  (5.0E-4)                       63 #define Table4step  (5.0E-4)
 63                                                    64 
 64 static const double Tsteps[5] = { Table0step,      65 static const double Tsteps[5] = { Table0step,
 65          Table1step,                               66          Table1step,
 66          Table2step,                               67          Table2step,
 67          Table3step,                               68          Table3step,
 68          Table4step };                             69          Table4step };
 69                                                    70 
 70 #define Table0offset 0                             71 #define Table0offset 0
 71 #define Table1offset (2*(Table0size))              72 #define Table1offset (2*(Table0size))
 72 #define Table2offset (2*(Table0size + Table1si     73 #define Table2offset (2*(Table0size + Table1size))
 73 #define Table3offset (2*(Table0size + Table1si     74 #define Table3offset (2*(Table0size + Table1size + Table2size))
 74 #define Table4offset (2*(Table0size + Table1si     75 #define Table4offset (2*(Table0size + Table1size + Table2size + Table3size))
 75                                                    76 
 76 static const int Toffsets[5] = { Table0offset,     77 static const int Toffsets[5] = { Table0offset,
 77          Table1offset,                             78          Table1offset,
 78          Table2offset,                             79          Table2offset,
 79          Table3offset,                             80          Table3offset,
 80          Table4offset };                           81          Table4offset };
 81                                                    82 
 82   // Here comes the big (30K bytes) table, kep     83   // Here comes the big (30K bytes) table, kept in a file ---
 83                                                    84 
 84 static const double gaussTables [2*TableSize]      85 static const double gaussTables [2*TableSize] = {
 85 #include "CLHEP/Random/gaussTables.cdat"           86 #include "CLHEP/Random/gaussTables.cdat"
 86 };                                                 87 };
 87                                                    88 
 88 double HepStat::flatToGaussian (double r) {        89 double HepStat::flatToGaussian (double r) {
 89                                                    90 
 90   double sign = +1.0; // We always compute a n     91   double sign = +1.0; // We always compute a negative number of 
 91         // sigmas.  For r > 0 we will multiply     92         // sigmas.  For r > 0 we will multiply by
 92         // sign = -1 to return a positive numb     93         // sign = -1 to return a positive number.
 93 #ifdef Trace1                                      94 #ifdef Trace1
 94 std::cout << "r = " << r << "\n";                  95 std::cout << "r = " << r << "\n";
 95 #endif                                             96 #endif
 96                                                    97 
 97   if ( r > .5 ) {                                  98   if ( r > .5 ) {
 98     r = 1-r;                                       99     r = 1-r;
 99     sign = -1.0;                                  100     sign = -1.0;
100 #ifdef Trace1                                     101 #ifdef Trace1
101 std::cout << "r = " << r << "sign negative \n"    102 std::cout << "r = " << r << "sign negative \n";
102 #endif                                            103 #endif
103   } else if ( r == .5 ) {                         104   } else if ( r == .5 ) {
104     return 0.0;                                   105     return 0.0;
105   }                                               106   }  
106                                                   107 
107   // Find a pointer to the proper table entrie    108   // Find a pointer to the proper table entries, along with the fraction 
108   // of the way in the relevant bin dx and the    109   // of the way in the relevant bin dx and the bin size h.
109                                                   110   
110   // Optimize for the case of table 4 by testi    111   // Optimize for the case of table 4 by testing for that first.  
111   // By removing that case from the for loop b    112   // By removing that case from the for loop below, we save not only
112   // several table lookups, but also several i    113   // several table lookups, but also several index calculations that
113   // now become (compile-time) constants.         114   // now become (compile-time) constants.
114   //                                              115   //
115   // Past the case of table 4, we need not be     116   // Past the case of table 4, we need not be as concerned about speed since
116   // this will happen only .1% of the time.       117   // this will happen only .1% of the time.
117                                                   118 
118   const double* tptr = 0;                         119   const double* tptr = 0;
119   double  dx = 0;                                 120   double  dx = 0;
120   double  h = 0;                                  121   double  h = 0;
121                                                   122 
122   // The following big if block will locate tp    123   // The following big if block will locate tptr, h, and dx from whichever
123   // table is applicable:                         124   // table is applicable:
124                                                   125 
125   int index;                                      126   int index;
126                                                   127 
127   if ( r >= Table4step ) {                        128   if ( r >= Table4step ) {
128                                                   129 
129     index = int((Table4size<<1) * r); // 1 to     130     index = int((Table4size<<1) * r); // 1 to Table4size-1 
130     if (index <= 0) index = 1;      // in case    131     if (index <= 0) index = 1;      // in case of rounding problem
131     if (index >= Table4size) index = Table4siz    132     if (index >= Table4size) index = Table4size-1;
132     dx = (Table4size<<1) * r - index;     // f    133     dx = (Table4size<<1) * r - index;     // fraction of way to next bin
133     h = Table4step;                               134     h = Table4step;
134 #ifdef Trace2                                     135 #ifdef Trace2 
135 std::cout << "index = " << index << " dx = " <    136 std::cout << "index = " << index << " dx = " << dx << " h = " << h << "\n";
136 #endif                                            137 #endif
137     index = (index<<1) + (Table4offset-2);        138     index = (index<<1) + (Table4offset-2);  
138   // at r = table4step+eps, index refers to th    139   // at r = table4step+eps, index refers to the start of table 4 
139   // and at r = .5 - eps, index refers to the     140   // and at r = .5 - eps, index refers to the next-to-last entry:
140   // remember, the table has two numbers per a    141   // remember, the table has two numbers per actual entry.
141 #ifdef Trace2                                     142 #ifdef Trace2 
142 std::cout << "offset index = " << index << "\n    143 std::cout << "offset index = " << index << "\n";
143 #endif                                            144 #endif
144                                                   145 
145     tptr = &gaussTables [index];                  146     tptr = &gaussTables [index];
146                                                   147     
147   } else if (r < Tsteps[0])  {                    148   } else if (r < Tsteps[0])  {
148                                                   149 
149     // If r is so small none of the tables app    150     // If r is so small none of the tables apply, use the asymptotic formula.
150     return (sign * transformSmall (r));           151     return (sign * transformSmall (r));
151                                                   152 
152   } else {                                        153   } else {
153                                                   154     
154     for ( int tableN = 3; tableN >= 0; tableN-    155     for ( int tableN = 3; tableN >= 0; tableN-- ) {
155       if ( r < Tsteps[tableN] ) {continue;}       156       if ( r < Tsteps[tableN] ) {continue;}   // can't happen when tableN==0
156 #ifdef Trace2                                     157 #ifdef Trace2 
157 std::cout << "Using table " << tableN << "\n";    158 std::cout << "Using table " << tableN << "\n";
158 #endif                                            159 #endif
159       double step = Tsteps[tableN];               160       double step = Tsteps[tableN];
160       index = int(r/step);      // 1 to TableN    161       index = int(r/step);      // 1 to TableNsize-1 
161         // The following two tests should prob    162         // The following two tests should probably never be true, but
162         // roundoff might cause index to be ou    163         // roundoff might cause index to be outside its proper range.
163         // In such a case, the interpolation s    164         // In such a case, the interpolation still makes sense, but we
164         // need to take care that tptr points     165         // need to take care that tptr points to valid data in the right table.
165       if (index == 0) index = 1;                  166       if (index == 0) index = 1;      
166       if (index >= Tsizes[tableN]) index = Tsi    167       if (index >= Tsizes[tableN]) index = Tsizes[tableN] - 1;
167       dx =  r/step - index;       // fraction     168       dx =  r/step - index;       // fraction of way to next bin
168       h  =  step;                                 169       h  =  step;
169 #ifdef Trace2                                     170 #ifdef Trace2 
170 std::cout << "index = " << index << " dx = " <    171 std::cout << "index = " << index << " dx = " << dx << " h = " << h << "\n";
171 #endif                                            172 #endif
172       index = (index<<1) + Toffsets[tableN] -     173       index = (index<<1) + Toffsets[tableN] - 2;
173       tptr = &gaussTables [index];                174       tptr = &gaussTables [index];
174       break;                                      175       break;
175     } // end of the for loop which finds tptr,    176     } // end of the for loop which finds tptr, dx and h in one of the tables
176                                                   177 
177     // The code can only get to here by a brea    178     // The code can only get to here by a break statement, having set dx etc.
178     // It not get to here without going throug    179     // It not get to here without going through one of the breaks,
179     // because before the for loop we test for    180     // because before the for loop we test for the case of r < Tsteps[0].
180                                                   181 
181   } // End of the big if block.                   182   } // End of the big if block.
182                                                   183 
183   // At the end of this if block, we have tptr    184   // At the end of this if block, we have tptr, dx and h -- and if r is less 
184   // than the smallest step, we have already r    185   // than the smallest step, we have already returned the proper answer.  
185                                                   186 
186   double  y0 = *tptr++;                           187   double  y0 = *tptr++;
187   double  d0 = *tptr++;                           188   double  d0 = *tptr++;
188   double  y1 = *tptr++;                           189   double  y1 = *tptr++;
189   double  d1 = *tptr;                             190   double  d1 = *tptr;
190                                                   191 
191 #ifdef Trace3                                     192 #ifdef Trace3
192 std::cout << "y0: " << y0 << " y1: " << y1 <<     193 std::cout << "y0: " << y0 << " y1: " << y1 << " d0: " << d0 << " d1: " << d1 << "\n";
193 #endif                                            194 #endif
194                                                   195 
195   double  x2 = dx * dx;                           196   double  x2 = dx * dx;
196   double  oneMinusX = 1 - dx;                     197   double  oneMinusX = 1 - dx;
197   double  oneMinusX2 = oneMinusX * oneMinusX;     198   double  oneMinusX2 = oneMinusX * oneMinusX;
198                                                   199 
199   double  f0 = (2. * dx + 1.) * oneMinusX2;       200   double  f0 = (2. * dx + 1.) * oneMinusX2;
200   double  f1 = (3. - 2. * dx) * x2;               201   double  f1 = (3. - 2. * dx) * x2;
201   double  g0 =  h * dx * oneMinusX2;              202   double  g0 =  h * dx * oneMinusX2;
202   double  g1 =  - h * oneMinusX * x2;             203   double  g1 =  - h * oneMinusX * x2;
203                                                   204 
204 #ifdef Trace3                                     205 #ifdef Trace3
205 std::cout << "f0: " << f0 << " f1: " << f1 <<     206 std::cout << "f0: " << f0 << " f1: " << f1 << " g0: " << g0 << " g1: " << g1 << "\n";
206 #endif                                            207 #endif
207                                                   208 
208   double answer = f0 * y0 + f1 * y1 + g0 * d0     209   double answer = f0 * y0 + f1 * y1 + g0 * d0 + g1 * d1;
209                                                   210 
210 #ifdef Trace1                                     211 #ifdef Trace1
211 std::cout << "variate is: " << sign*answer <<     212 std::cout << "variate is: " << sign*answer << "\n";
212 #endif                                            213 #endif
213                                                   214 
214   return sign * answer;                           215   return sign * answer;
215                                                   216 
216 } // flatToGaussian                               217 } // flatToGaussian
217                                                   218 
218 double transformSmall (double r) {                219 double transformSmall (double r) {
219                                                   220 
220   // Solve for -v in the asymtotic formula        221   // Solve for -v in the asymtotic formula 
221   //                                              222   //
222   // errInt (-v) =  exp(-v*v/2)         1         223   // errInt (-v) =  exp(-v*v/2)         1     1*3    1*3*5
223   //       ------------ * (1 - ---- + ---- - -    224   //       ------------ * (1 - ---- + ---- - ----- + ... )
224   //       v*sqrt(2*pi)        v**2   v**4   v    225   //       v*sqrt(2*pi)        v**2   v**4   v**6
225                                                   226 
226   // The value of r (=errInt(-v)) supplied is     227   // The value of r (=errInt(-v)) supplied is going to less than 2.0E-13,
227   // which is such that v < -7.25.  Since the     228   // which is such that v < -7.25.  Since the value of r is meaningful only
228   // to an absolute error of 1E-16 (double pre    229   // to an absolute error of 1E-16 (double precision accuracy for a number 
229   // which on the high side could be of the fo    230   // which on the high side could be of the form 1-epsilon), computing
230   // v to more than 3-4 digits of accuracy is     231   // v to more than 3-4 digits of accuracy is suspect; however, to ensure 
231   // smoothness with the table generator (whic    232   // smoothness with the table generator (which uses quite a few terms) we
232   // also use terms up to 1*3*5* ... *13/v**14    233   // also use terms up to 1*3*5* ... *13/v**14, and insist on accuracy of
233   // solution at the level of 1.0e-7.             234   // solution at the level of 1.0e-7.
234                                                   235 
235   // This routine is called less than one time    236   // This routine is called less than one time in a trillion firings, so
236   // speed is of no concern.  As a matter of t    237   // speed is of no concern.  As a matter of technique, we terminate the
237   // iterations in case they would be infinite    238   // iterations in case they would be infinite, but this should not happen.
238                                                   239 
239   double eps = 1.0e-7;                            240   double eps = 1.0e-7;
240   double guess = 7.5;                             241   double guess = 7.5;
241   double v;                                       242   double v;
242                                                   243   
243   for ( int i = 1; i < 50; i++ ) {                244   for ( int i = 1; i < 50; i++ ) {
244     double vn2 = 1.0/(guess*guess);               245     double vn2 = 1.0/(guess*guess);
245     double s1 = -13*11*9*7*5*3 * vn2*vn2*vn2*v    246     double s1 = -13*11*9*7*5*3 * vn2*vn2*vn2*vn2*vn2*vn2*vn2;
246             s1 +=    11*9*7*5*3 * vn2*vn2*vn2*    247             s1 +=    11*9*7*5*3 * vn2*vn2*vn2*vn2*vn2*vn2;
247             s1 +=      -9*7*5*3 * vn2*vn2*vn2*    248             s1 +=      -9*7*5*3 * vn2*vn2*vn2*vn2*vn2;
248             s1 +=         7*5*3 * vn2*vn2*vn2*    249             s1 +=         7*5*3 * vn2*vn2*vn2*vn2;
249             s1 +=          -5*3 * vn2*vn2*vn2;    250             s1 +=          -5*3 * vn2*vn2*vn2;
250             s1 +=            3 * vn2*vn2    -     251             s1 +=            3 * vn2*vn2    - vn2  +    1.0;
251     v = std::sqrt ( 2.0 * std::log ( s1 / (r*g    252     v = std::sqrt ( 2.0 * std::log ( s1 / (r*guess*std::sqrt(CLHEP::twopi)) ) );
252     if ( std::abs(v-guess) < eps ) break;         253     if ( std::abs(v-guess) < eps ) break;
253     guess = v;                                    254     guess = v;
254   }                                               255   }
255                                                   256  
256   return -v;                                      257   return -v;
257                                                   258 
258 } // transformSmall()                             259 } // transformSmall()
259                                                   260 
260 double HepStat::inverseErf (double t) {           261 double HepStat::inverseErf (double t) {
261                                                   262 
262   // This uses erf(x) = 2*gaussCDF(sqrt(2)*x)     263   // This uses erf(x) = 2*gaussCDF(sqrt(2)*x) - 1
263                                                   264 
264   return std::sqrt(0.5) * flatToGaussian(.5*(t    265   return std::sqrt(0.5) * flatToGaussian(.5*(t+1));
265                                                   266 
266 }                                                 267 }
267                                                   268 
268 double HepStat::erf (double x) {                  269 double HepStat::erf (double x) {
269                                                   270 
270 // Math:                                          271 // Math:
271 //                                                272 //
272 // For any given x we can "quickly" find t0 =     273 // For any given x we can "quickly" find t0 = erfQ (x) = erf(x) + epsilon.
273 //                                                274 //
274 // Then we can find x1 = inverseErf (t0) = inv    275 // Then we can find x1 = inverseErf (t0) = inverseErf (erf(x)+epsilon)
275 //                                                276 //
276 // Expanding in the small epsion,                 277 // Expanding in the small epsion, 
277 //                                                278 // 
278 //  x1 = x + epsilon * [deriv(inverseErf(u),u)    279 //  x1 = x + epsilon * [deriv(inverseErf(u),u) at u = t0] + O(epsilon**2)
279 //                                                280 //
280 // so epsilon is (x1-x) / [deriv(inverseErf(u)    281 // so epsilon is (x1-x) / [deriv(inverseErf(u),u) at u = t0] + O(epsilon**2)
281 //                                                282 //
282 // But the derivative of an inverse function i    283 // But the derivative of an inverse function is one over the derivative of the
283 // function, so                                   284 // function, so 
284 // epsilon  = (x1-x) * [deriv(erf(v),v) at v =    285 // epsilon  = (x1-x) * [deriv(erf(v),v) at v = x] + O(epsilon**2)
285 //                                                286 //
286 // And the definition of the erf integral make    287 // And the definition of the erf integral makes that derivative trivial.
287 // Ultimately,                                    288 // Ultimately,
288 //                                                289 //
289 // erf(x) = erfQ(x) - (inverseErf(erfQ(x))-x)     290 // erf(x) = erfQ(x) - (inverseErf(erfQ(x))-x) * exp(-x**2) * 2/sqrt(CLHEP::pi)
290 //                                                291 //
291                                                   292 
292   double t0 = erfQ(x);                            293   double t0 = erfQ(x);
293   double deriv = std::exp(-x*x) * (2.0 / std::    294   double deriv = std::exp(-x*x) * (2.0 / std::sqrt(CLHEP::pi));
294                                                   295 
295   return t0 - (inverseErf (t0) - x) * deriv;      296   return t0 - (inverseErf (t0) - x) * deriv;
296                                                   297 
297 }                                                 298 }
298                                                   299 
299                                                   300 
300 }  // namespace CLHEP                             301 }  // namespace CLHEP
301                                                   302 
302                                                   303