Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/clhep/src/RandGamma.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/RandGamma.cc (Version 11.3.0) and /externals/clhep/src/RandGamma.cc (Version 10.6)


  1 // -*- C++ -*-                                      1 // -*- C++ -*-
  2 //                                                  2 //
  3 // -------------------------------------------      3 // -----------------------------------------------------------------------
  4 //                             HEP Random           4 //                             HEP Random
  5 //                          --- RandGamma ---       5 //                          --- RandGamma ---
  6 //                      class implementation f      6 //                      class implementation file
  7 // -------------------------------------------      7 // -----------------------------------------------------------------------
  8                                                     8 
  9 // ===========================================      9 // =======================================================================
 10 // John Marraffino - Created: 12th May 1998        10 // John Marraffino - Created: 12th May 1998
 11 // M Fischler      - put and get to/from strea     11 // M Fischler      - put and get to/from streams 12/13/04
 12 // M Fischler       - put/get to/from streams      12 // M Fischler       - put/get to/from streams uses pairs of ulongs when
 13 //      + storing doubles avoid problems with      13 //      + storing doubles avoid problems with precision 
 14 //      4/14/05                                    14 //      4/14/05
 15 // ===========================================     15 // =======================================================================
 16                                                    16 
 17 #include "CLHEP/Random/RandGamma.h"                17 #include "CLHEP/Random/RandGamma.h"
 18 #include "CLHEP/Random/DoubConv.h"                 18 #include "CLHEP/Random/DoubConv.h"
 19 #include "CLHEP/Utility/thread_local.h"            19 #include "CLHEP/Utility/thread_local.h"
 20 #include <cmath>  // for std::log()                20 #include <cmath>  // for std::log()
 21 #include <iostream>                            << 
 22 #include <string>                              << 
 23 #include <vector>                              << 
 24                                                    21 
 25 namespace CLHEP {                                  22 namespace CLHEP {
 26                                                    23 
 27 std::string RandGamma::name() const {return "R     24 std::string RandGamma::name() const {return "RandGamma";}
 28 HepRandomEngine & RandGamma::engine() {return      25 HepRandomEngine & RandGamma::engine() {return *localEngine;}
 29                                                    26 
 30 RandGamma::~RandGamma() {                          27 RandGamma::~RandGamma() {
 31 }                                                  28 }
 32                                                    29 
 33 double RandGamma::shoot( HepRandomEngine *anEn     30 double RandGamma::shoot( HepRandomEngine *anEngine,  double k,
 34                                                    31                                                         double lambda ) {
 35   return genGamma( anEngine, k, lambda );          32   return genGamma( anEngine, k, lambda );
 36 }                                                  33 }
 37                                                    34 
 38 double RandGamma::shoot( double k, double lamb     35 double RandGamma::shoot( double k, double lambda ) {
 39   HepRandomEngine *anEngine = HepRandom::getTh     36   HepRandomEngine *anEngine = HepRandom::getTheEngine();
 40   return genGamma( anEngine, k, lambda );          37   return genGamma( anEngine, k, lambda );
 41 }                                                  38 }
 42                                                    39 
 43 double RandGamma::fire( double k, double lambd     40 double RandGamma::fire( double k, double lambda ) {
 44   return genGamma( localEngine.get(), k, lambd     41   return genGamma( localEngine.get(), k, lambda );
 45 }                                                  42 }
 46                                                    43 
 47 void RandGamma::shootArray( const int size, do     44 void RandGamma::shootArray( const int size, double* vect,
 48                             double k, double l     45                             double k, double lambda )
 49 {                                                  46 {
 50   for( double* v = vect; v != vect + size; ++v     47   for( double* v = vect; v != vect + size; ++v )
 51     *v = shoot(k,lambda);                          48     *v = shoot(k,lambda);
 52 }                                                  49 }
 53                                                    50 
 54 void RandGamma::shootArray( HepRandomEngine* a     51 void RandGamma::shootArray( HepRandomEngine* anEngine,
 55                             const int size, do     52                             const int size, double* vect,
 56                             double k, double l     53                             double k, double lambda )
 57 {                                                  54 {
 58   for( double* v = vect; v != vect + size; ++v     55   for( double* v = vect; v != vect + size; ++v )
 59     *v = shoot(anEngine,k,lambda);                 56     *v = shoot(anEngine,k,lambda);
 60 }                                                  57 }
 61                                                    58 
 62 void RandGamma::fireArray( const int size, dou     59 void RandGamma::fireArray( const int size, double* vect)
 63 {                                                  60 {
 64   for( double* v = vect; v != vect + size; ++v     61   for( double* v = vect; v != vect + size; ++v )
 65     *v = fire(defaultK,defaultLambda);             62     *v = fire(defaultK,defaultLambda);
 66 }                                                  63 }
 67                                                    64 
 68 void RandGamma::fireArray( const int size, dou     65 void RandGamma::fireArray( const int size, double* vect,
 69                            double k, double la     66                            double k, double lambda )
 70 {                                                  67 {
 71   for( double* v = vect; v != vect + size; ++v     68   for( double* v = vect; v != vect + size; ++v )
 72     *v = fire(k,lambda);                           69     *v = fire(k,lambda);
 73 }                                                  70 }
 74                                                    71 
 75 double RandGamma::genGamma( HepRandomEngine *a     72 double RandGamma::genGamma( HepRandomEngine *anEngine,
 76                                double a, doubl     73                                double a, double lambda ) {
 77 /*********************************************     74 /*************************************************************************
 78  *         Gamma Distribution - Rejection algo     75  *         Gamma Distribution - Rejection algorithm gs combined with     *
 79  *                              Acceptance com     76  *                              Acceptance complement method gd          *
 80  *********************************************     77  *************************************************************************/
 81                                                    78 
 82   double aa = -1.0, aaa = -1.0, b{0.}, c{0.},  <<  79   static CLHEP_THREAD_LOCAL double aa = -1.0, aaa = -1.0, b, c, d, e, r, s, si, ss, q0;
 83   constexpr double q1 = 0.0416666664, q2 =  0. <<  80   static const double q1 = 0.0416666664, q2 =  0.0208333723, q3 = 0.0079849875,
 84        q4 = 0.0015746717, q5 = -0.0003349403,      81        q4 = 0.0015746717, q5 = -0.0003349403, q6 = 0.0003340332,
 85        q7 = 0.0006053049, q8 = -0.0004701849,      82        q7 = 0.0006053049, q8 = -0.0004701849, q9 = 0.0001710320,
 86        a1 = 0.333333333,  a2 = -0.249999949,       83        a1 = 0.333333333,  a2 = -0.249999949,  a3 = 0.199999867,
 87        a4 =-0.166677482,  a5 =  0.142873973,       84        a4 =-0.166677482,  a5 =  0.142873973,  a6 =-0.124385581,
 88        a7 = 0.110368310,  a8 = -0.112750886,       85        a7 = 0.110368310,  a8 = -0.112750886,  a9 = 0.104089866,
 89        e1 = 1.000000000,  e2 =  0.499999994,       86        e1 = 1.000000000,  e2 =  0.499999994,  e3 = 0.166666848,
 90        e4 = 0.041664508,  e5 =  0.008345522,       87        e4 = 0.041664508,  e5 =  0.008345522,  e6 = 0.001353826,
 91        e7 = 0.000247453;                           88        e7 = 0.000247453;
 92                                                    89 
 93  double gds{0.},p{0.},q{0.},t{0.},sign_u{0.},u <<  90 double gds,p,q,t,sign_u,u,v,w,x;
 94  double v1{0.},v2{0.},v12{0.};                 <<  91 double v1,v2,v12;
 95                                                    92 
 96 // Check for invalid input values                  93 // Check for invalid input values
 97                                                    94 
 98  if( a <= 0.0 ) return (-1.0);                     95  if( a <= 0.0 ) return (-1.0);
 99  if( lambda <= 0.0 ) return (-1.0);                96  if( lambda <= 0.0 ) return (-1.0);
100                                                    97 
101  if (a < 1.0)                                      98  if (a < 1.0)
102    {          // CASE A: Acceptance rejection      99    {          // CASE A: Acceptance rejection algorithm gs
103     b = 1.0 + 0.36788794412 * a;       // Step    100     b = 1.0 + 0.36788794412 * a;       // Step 1
104     for(;;)                                       101     for(;;)
105       {                                           102       {
106        p = b * anEngine->flat();                  103        p = b * anEngine->flat();
107        if (p <= 1.0)                              104        if (p <= 1.0)
108     {                            // Step 2. Ca    105     {                            // Step 2. Case gds <= 1
109      gds = std::exp(std::log(p) / a);             106      gds = std::exp(std::log(p) / a);
110      if (std::log(anEngine->flat()) <= -gds) r    107      if (std::log(anEngine->flat()) <= -gds) return(gds/lambda);
111     }                                             108     }
112        else                                       109        else
113     {                            // Step 3. Ca    110     {                            // Step 3. Case gds > 1
114      gds = - std::log ((b - p) / a);              111      gds = - std::log ((b - p) / a);
115      if (std::log(anEngine->flat()) <= ((a - 1    112      if (std::log(anEngine->flat()) <= ((a - 1.0) * std::log(gds))) return(gds/lambda);
116     }                                             113     }
117       }                                           114       }
118    }                                              115    }
119  else                                             116  else
120    {          // CASE B: Acceptance complement    117    {          // CASE B: Acceptance complement algorithm gd
121     if (a != aa)                                  118     if (a != aa)
122        {                               // Step    119        {                               // Step 1. Preparations
123   aa = a;                                         120   aa = a;
124   ss = a - 0.5;                                   121   ss = a - 0.5;
125   s = std::sqrt(ss);                              122   s = std::sqrt(ss);
126   d = 5.656854249 - 12.0 * s;                     123   d = 5.656854249 - 12.0 * s;
127        }                                          124        }
128                                                   125                                               // Step 2. Normal deviate
129     do {                                          126     do {
130       v1 = 2.0 * anEngine->flat() - 1.0;          127       v1 = 2.0 * anEngine->flat() - 1.0;
131       v2 = 2.0 * anEngine->flat() - 1.0;          128       v2 = 2.0 * anEngine->flat() - 1.0;
132       v12 = v1*v1 + v2*v2;                        129       v12 = v1*v1 + v2*v2;
133     } while ( v12 > 1.0 );                        130     } while ( v12 > 1.0 );
134     t = v1*std::sqrt(-2.0*std::log(v12)/v12);     131     t = v1*std::sqrt(-2.0*std::log(v12)/v12);
135     x = s + 0.5 * t;                              132     x = s + 0.5 * t;
136     gds = x * x;                                  133     gds = x * x;
137     if (t >= 0.0) return(gds/lambda);             134     if (t >= 0.0) return(gds/lambda);         // Immediate acceptance
138                                                   135 
139     u = anEngine->flat();            // Step 3    136     u = anEngine->flat();            // Step 3. Uniform random number
140     if (d * u <= t * t * t) return(gds/lambda)    137     if (d * u <= t * t * t) return(gds/lambda); // Squeeze acceptance
141                                                   138 
142     if (a != aaa)                                 139     if (a != aaa)
143        {                               // Step    140        {                               // Step 4. Set-up for hat case
144   aaa = a;                                        141   aaa = a;
145   r = 1.0 / a;                                    142   r = 1.0 / a;
146   q0 = ((((((((q9 * r + q8) * r + q7) * r + q6    143   q0 = ((((((((q9 * r + q8) * r + q7) * r + q6) * r + q5) * r + q4) *
147         r + q3) * r + q2) * r + q1) * r;          144         r + q3) * r + q2) * r + q1) * r;
148   if (a > 3.686)                                  145   if (a > 3.686)
149      {                                            146      {
150       if (a > 13.022)                             147       if (a > 13.022)
151          {                                        148          {
152     b = 1.77;                                     149     b = 1.77;
153     si = 0.75;                                    150     si = 0.75;
154     c = 0.1515 / s;                               151     c = 0.1515 / s;
155          }                                        152          }
156       else                                        153       else
157          {                                        154          {
158     b = 1.654 + 0.0076 * ss;                      155     b = 1.654 + 0.0076 * ss;
159     si = 1.68 / s + 0.275;                        156     si = 1.68 / s + 0.275;
160     c = 0.062 / s + 0.024;                        157     c = 0.062 / s + 0.024;
161          }                                        158          }
162      }                                            159      }
163   else                                            160   else
164      {                                            161      {
165       b = 0.463 + s - 0.178 * ss;                 162       b = 0.463 + s - 0.178 * ss;
166       si = 1.235;                                 163       si = 1.235;
167       c = 0.195 / s - 0.079 + 0.016 * s;          164       c = 0.195 / s - 0.079 + 0.016 * s;
168      }                                            165      }
169        }                                          166        }
170     if (x > 0.0)                       // Step    167     if (x > 0.0)                       // Step 5. Calculation of q
171        {                                          168        {
172   v = t / (s + s);               // Step 6.       169   v = t / (s + s);               // Step 6.
173   if (std::fabs(v) > 0.25)                        170   if (std::fabs(v) > 0.25)
174      {                                            171      {
175       q = q0 - s * t + 0.25 * t * t + (ss + ss    172       q = q0 - s * t + 0.25 * t * t + (ss + ss) * std::log(1.0 + v);
176      }                                            173      }
177   else                                            174   else
178      {                                            175      {
179       q = q0 + 0.5 * t * t * ((((((((a9 * v +     176       q = q0 + 0.5 * t * t * ((((((((a9 * v + a8) * v + a7) * v + a6) *
180           v + a5) * v + a4) * v + a3) * v + a2    177           v + a5) * v + a4) * v + a3) * v + a2) * v + a1) * v;
181      }                // Step 7. Quotient acce    178      }                // Step 7. Quotient acceptance
182   if (std::log(1.0 - u) <= q) return(gds/lambd    179   if (std::log(1.0 - u) <= q) return(gds/lambda);
183        }                                          180        }
184                                                   181 
185     for(;;)                                       182     for(;;)
186        {                    // Step 8. Double     183        {                    // Step 8. Double exponential deviate t
187   do                                              184   do
188   {                                               185   {
189    e = -std::log(anEngine->flat());               186    e = -std::log(anEngine->flat());
190    u = anEngine->flat();                          187    u = anEngine->flat();
191    u = u + u - 1.0;                               188    u = u + u - 1.0;
192    sign_u = (u > 0)? 1.0 : -1.0;                  189    sign_u = (u > 0)? 1.0 : -1.0;
193    t = b + (e * si) * sign_u;                     190    t = b + (e * si) * sign_u;
194   }                                               191   }
195   while (t <= -0.71874483771719);   // Step 9.    192   while (t <= -0.71874483771719);   // Step 9. Rejection of t
196   v = t / (s + s);                  // Step 10    193   v = t / (s + s);                  // Step 10. New q(t)
197   if (std::fabs(v) > 0.25)                        194   if (std::fabs(v) > 0.25)
198      {                                            195      {
199       q = q0 - s * t + 0.25 * t * t + (ss + ss    196       q = q0 - s * t + 0.25 * t * t + (ss + ss) * std::log(1.0 + v);
200      }                                            197      }
201   else                                            198   else
202      {                                            199      {
203       q = q0 + 0.5 * t * t * ((((((((a9 * v +     200       q = q0 + 0.5 * t * t * ((((((((a9 * v + a8) * v + a7) * v + a6) *
204           v + a5) * v + a4) * v + a3) * v + a2    201           v + a5) * v + a4) * v + a3) * v + a2) * v + a1) * v;
205      }                                            202      }
206   if (q <= 0.0) continue;           // Step 11    203   if (q <= 0.0) continue;           // Step 11.
207   if (q > 0.5)                                    204   if (q > 0.5)
208      {                                            205      {
209       w = std::exp(q) - 1.0;                      206       w = std::exp(q) - 1.0;
210      }                                            207      }
211   else                                            208   else
212      {                                            209      {
213       w = ((((((e7 * q + e6) * q + e5) * q + e    210       w = ((((((e7 * q + e6) * q + e5) * q + e4) * q + e3) * q + e2) *
214              q + e1) * q;                         211              q + e1) * q;
215      }                    // Step 12. Hat acce    212      }                    // Step 12. Hat acceptance
216   if ( c * u * sign_u <= w * std::exp(e - 0.5     213   if ( c * u * sign_u <= w * std::exp(e - 0.5 * t * t))
217      {                                            214      {
218       x = s + 0.5 * t;                            215       x = s + 0.5 * t;
219       return(x*x/lambda);                         216       return(x*x/lambda);
220      }                                            217      }
221        }                                          218        }
222    }                                              219    }
223 }                                                 220 }
224                                                   221 
225 std::ostream & RandGamma::put ( std::ostream &    222 std::ostream & RandGamma::put ( std::ostream & os ) const {
226   long pr=os.precision(20);                    << 223   int pr=os.precision(20);
227   std::vector<unsigned long> t(2);                224   std::vector<unsigned long> t(2);
228   os << " " << name() << "\n";                    225   os << " " << name() << "\n";
229   os << "Uvec" << "\n";                           226   os << "Uvec" << "\n";
230   t = DoubConv::dto2longs(defaultK);              227   t = DoubConv::dto2longs(defaultK);
231   os << defaultK << " " << t[0] << " " << t[1]    228   os << defaultK << " " << t[0] << " " << t[1] << "\n";
232   t = DoubConv::dto2longs(defaultLambda);         229   t = DoubConv::dto2longs(defaultLambda);
233   os << defaultLambda << " " << t[0] << " " <<    230   os << defaultLambda << " " << t[0] << " " << t[1] << "\n";
234   os.precision(pr);                               231   os.precision(pr);
235   return os;                                      232   return os;
236 }                                                 233 }
237                                                   234 
238 std::istream & RandGamma::get ( std::istream &    235 std::istream & RandGamma::get ( std::istream & is ) {
239   std::string inName;                             236   std::string inName;
240   is >> inName;                                   237   is >> inName;
241   if (inName != name()) {                         238   if (inName != name()) {
242     is.clear(std::ios::badbit | is.rdstate());    239     is.clear(std::ios::badbit | is.rdstate());
243     std::cerr << "Mismatch when expecting to r    240     std::cerr << "Mismatch when expecting to read state of a "
244             << name() << " distribution\n"        241             << name() << " distribution\n"
245         << "Name found was " << inName            242         << "Name found was " << inName
246         << "\nistream is left in the badbit st    243         << "\nistream is left in the badbit state\n";
247     return is;                                    244     return is;
248   }                                               245   }
249   if (possibleKeywordInput(is, "Uvec", default    246   if (possibleKeywordInput(is, "Uvec", defaultK)) {
250     std::vector<unsigned long> t(2);              247     std::vector<unsigned long> t(2);
251     is >> defaultK >> t[0] >> t[1]; defaultK =    248     is >> defaultK >> t[0] >> t[1]; defaultK = DoubConv::longs2double(t); 
252     is >> defaultLambda>>t[0]>>t[1]; defaultLa    249     is >> defaultLambda>>t[0]>>t[1]; defaultLambda = DoubConv::longs2double(t); 
253     return is;                                    250     return is;
254   }                                               251   }
255   // is >> defaultK encompassed by possibleKey    252   // is >> defaultK encompassed by possibleKeywordInput
256   is >> defaultLambda;                            253   is >> defaultLambda;
257   return is;                                      254   return is;
258 }                                                 255 }
259                                                   256 
260 }  // namespace CLHEP                             257 }  // namespace CLHEP
261                                                   258 
262                                                   259