Geant4 Cross Reference

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


                                                   >>   1 // $Id:$
  1 // -*- C++ -*-                                      2 // -*- C++ -*-
  2 //                                                  3 //
  3 // -------------------------------------------      4 // -----------------------------------------------------------------------
  4 //                             HEP Random           5 //                             HEP Random
  5 //                         --- RandPoissonQ --      6 //                         --- RandPoissonQ ---
  6 //                      class implementation f      7 //                      class implementation file
  7 // -------------------------------------------      8 // -----------------------------------------------------------------------
  8                                                     9 
  9 // ===========================================     10 // =======================================================================
 10 // M. Fischler    - Implemented new, much fast     11 // M. Fischler    - Implemented new, much faster table-driven algorithm
 11 //        applicable for mu < 100                  12 //        applicable for mu < 100
 12 //      - Implemented "quick()" methods, shich     13 //      - Implemented "quick()" methods, shich are the same as the
 13 //        new methods for mu < 100 and are a s     14 //        new methods for mu < 100 and are a skew-corrected gaussian
 14 //        approximation for large mu.              15 //        approximation for large mu.
 15 // M. Fischler    - Removed mean=100 from the      16 // M. Fischler    - Removed mean=100 from the table-driven set, since it
 16 //        uses a value just off the end of the     17 //        uses a value just off the end of the table.  (April 2004)
 17 // M Fischler     - put and get to/from stream     18 // M Fischler     - put and get to/from streams 12/15/04
 18 // M Fischler     - Utilize RandGaussQ rather      19 // M Fischler     - Utilize RandGaussQ rather than RandGauss, as clearly 
 19 //        intended by the inclusion of RandGau     20 //        intended by the inclusion of RandGaussQ.h.  Using RandGauss
 20 //        introduces a subtle trap in that the     21 //        introduces a subtle trap in that the state of RandPoissonQ
 21 //        can never be properly captured witho     22 //        can never be properly captured without also saveing the
 22 //        state of RandGauss!  RandGaussQ is,      23 //        state of RandGauss!  RandGaussQ is, on the other hand,
 23 //        stateless except for the engine used     24 //        stateless except for the engine used.
 24 // M Fischler   - Modified use of wrong engine <<  25 // M Fisculer   - Modified use of wrong engine when shoot (anEngine, mean)
 25 //        is called.  This flaw was preventing     26 //        is called.  This flaw was preventing any hope of proper
 26 //        saving and restoring in the instance     27 //        saving and restoring in the instance cases.
 27 // M Fischler     - fireArray using defaultMea     28 // M Fischler     - fireArray using defaultMean 2/10/05
 28 // M Fischler       - put/get to/from streams      29 // M Fischler       - put/get to/from streams uses pairs of ulongs when
 29 //      + storing doubles avoid problems with      30 //      + storing doubles avoid problems with precision 
 30 //      4/14/05                                    31 //      4/14/05
 31 // M Fischler   - Modified use of shoot (mean) <<  32 // M Fisculer   - Modified use of shoot (mean) instead of 
 32 //        shoot(getLocalEngine(), mean) when f     33 //        shoot(getLocalEngine(), mean) when fire(mean) is called.  
 33 //        This flaw was causing bad "cross-tal     34 //        This flaw was causing bad "cross-talk" between modules
 34 //        in CMS, where one used its own engin     35 //        in CMS, where one used its own engine, and the other 
 35 //        used the static generator.  10/18/07     36 //        used the static generator.  10/18/07
 36 //                                                 37 //
 37 // ===========================================     38 // =======================================================================
 38                                                    39 
 39 #include "CLHEP/Random/RandPoissonQ.h"             40 #include "CLHEP/Random/RandPoissonQ.h"
 40 #include "CLHEP/Random/RandGaussQ.h"               41 #include "CLHEP/Random/RandGaussQ.h"
 41 #include "CLHEP/Random/DoubConv.h"                 42 #include "CLHEP/Random/DoubConv.h"
 42 #include "CLHEP/Random/Stat.h"                     43 #include "CLHEP/Random/Stat.h"
 43 #include "CLHEP/Utility/thread_local.h"        << 
 44 #include <cmath>  // for std::pow()                44 #include <cmath>  // for std::pow()
 45 #include <iostream>                            << 
 46 #include <string>                              << 
 47 #include <vector>                              << 
 48                                                    45 
 49 namespace CLHEP {                                  46 namespace CLHEP {
 50                                                    47 
 51 std::string RandPoissonQ::name() const {return     48 std::string RandPoissonQ::name() const {return "RandPoissonQ";}
 52 HepRandomEngine & RandPoissonQ::engine() {retu     49 HepRandomEngine & RandPoissonQ::engine() {return RandPoisson::engine();}
 53                                                    50 
 54 // Initialization of static data:  Note that t     51 // Initialization of static data:  Note that this is all const static data,
 55 // so that saveEngineStatus properly saves all     52 // so that saveEngineStatus properly saves all needed information. 
 56                                                    53 
 57   // The following MUST MATCH the correspondin     54   // The following MUST MATCH the corresponding values used (in
 58   // poissonTables.cc) when poissonTables.cdat     55   // poissonTables.cc) when poissonTables.cdat was created.
 59                                                    56 
 60 const double RandPoissonQ::FIRST_MU = 10;// lo     57 const double RandPoissonQ::FIRST_MU = 10;// lowest mu value in table
 61 const double RandPoissonQ::LAST_MU =  95;// hi     58 const double RandPoissonQ::LAST_MU =  95;// highest mu value
 62 const double RandPoissonQ::S = 5;        // Sp     59 const double RandPoissonQ::S = 5;        // Spacing between mu values
 63 const int RandPoissonQ::BELOW = 30;      // St     60 const int RandPoissonQ::BELOW = 30;      // Starting point for N is at mu - BELOW
 64 const int RandPoissonQ::ENTRIES = 51;    // Nu     61 const int RandPoissonQ::ENTRIES = 51;    // Number of entries in each mu row
 65                                                    62 
 66 const double RandPoissonQ::MAXIMUM_POISSON_DEV     63 const double RandPoissonQ::MAXIMUM_POISSON_DEVIATE = 2.0E9;
 67   // Careful -- this is NOT the maximum number     64   // Careful -- this is NOT the maximum number that can be held in 
 68   // a long.  It actually should be some large     65   // a long.  It actually should be some large number of sigma below
 69   // that.                                         66   // that.  
 70                                                    67 
 71   // Here comes the big (9K bytes) table, kept     68   // Here comes the big (9K bytes) table, kept in a file of 
 72   // ENTRIES * (FIRST_MU - LAST_MU + 1)/S doub     69   // ENTRIES * (FIRST_MU - LAST_MU + 1)/S doubles
 73                                                    70 
 74 static const double poissonTables [ 51 * ( (95     71 static const double poissonTables [ 51 * ( (95-10)/5 + 1 ) ] = {
 75 #include "CLHEP/Random/poissonTables.cdat"         72 #include "CLHEP/Random/poissonTables.cdat"
 76 };                                                 73 };
 77                                                    74 
 78 //                                                 75 //
 79 // Constructors and destructors:                   76 // Constructors and destructors:
 80 //                                                 77 //
 81                                                    78 
 82 RandPoissonQ::~RandPoissonQ() {                    79 RandPoissonQ::~RandPoissonQ() {
 83 }                                                  80 }
 84                                                    81 
 85 void RandPoissonQ::setupForDefaultMu() {           82 void RandPoissonQ::setupForDefaultMu() {
 86                                                    83 
 87   // The following are useful for quick approx     84   // The following are useful for quick approximation, for large mu
 88                                                    85   
 89   double sig2 = defaultMean * (.9998654 - .083     86   double sig2 = defaultMean * (.9998654 - .08346/defaultMean);
 90   sigma = std::sqrt(sig2);                         87   sigma = std::sqrt(sig2);
 91   // sigma for the Guassian which approximates     88   // sigma for the Guassian which approximates the Poisson -- naively
 92   // sqrt (defaultMean).                           89   // sqrt (defaultMean).
 93   //                                               90   //
 94   // The multiplier corrects for fact that dis     91   // The multiplier corrects for fact that discretization of the form
 95   // [gaussian+.5] increases the second moment     92   // [gaussian+.5] increases the second moment by a small amount.
 96                                                    93 
 97   double t = 1./(sig2);                            94   double t = 1./(sig2);
 98                                                    95 
 99   a2 = t/6 + t*t/324;                              96   a2 = t/6 + t*t/324;
100   a1 = std::sqrt (1-2*a2*a2*sig2);                 97   a1 = std::sqrt (1-2*a2*a2*sig2);
101   a0 = defaultMean + .5 - sig2 * a2;               98   a0 = defaultMean + .5 - sig2 * a2;
102                                                    99 
103   // The formula will be a0 + a1*x + a2*x*x wh    100   // The formula will be a0 + a1*x + a2*x*x where x has 2nd moment of sigma.
104   // The coeffeicients are chosen to match the    101   // The coeffeicients are chosen to match the first THREE moments of the 
105   // true Poisson distribution.                   102   // true Poisson distribution.   
106   //                                              103   // 
107   // Actually, if the correction for discretiz    104   // Actually, if the correction for discretization were not needed, then 
108   // a2 could be taken one order higher by add    105   // a2 could be taken one order higher by adding t*t*t/5832.  However,
109   // the discretization correction is not perf    106   // the discretization correction is not perfect, leading to inaccuracy
110   // on the order to 1/mu**2, so adding a thir    107   // on the order to 1/mu**2, so adding a third term is overkill.  
111                                                   108 
112 } // setupForDefaultMu()                          109 } // setupForDefaultMu() 
113                                                   110 
114                                                   111 
115 //                                                112 //
116 // fire, quick, operator(), and shoot methods:    113 // fire, quick, operator(), and shoot methods:
117 //                                                114 //
118                                                   115 
119 long RandPoissonQ::shoot(double xm) {             116 long RandPoissonQ::shoot(double xm) {
120   return shoot(getTheEngine(), xm);               117   return shoot(getTheEngine(), xm);
121 }                                                 118 }
122                                                   119 
123 double RandPoissonQ::operator()() {               120 double RandPoissonQ::operator()() {
124   return (double) fire();                         121   return (double) fire();
125 }                                                 122 }
126                                                   123 
127 double RandPoissonQ::operator()( double mean )    124 double RandPoissonQ::operator()( double mean ) {
128   return (double) fire(mean);                     125   return (double) fire(mean);
129 }                                                 126 }
130                                                   127 
131 long RandPoissonQ::fire(double mean) {            128 long RandPoissonQ::fire(double mean) {
132   return shoot(getLocalEngine(), mean);           129   return shoot(getLocalEngine(), mean);
133 }                                                 130 }
134                                                   131 
135 long RandPoissonQ::fire() {                       132 long RandPoissonQ::fire() {
136   if ( defaultMean < LAST_MU + S ) {              133   if ( defaultMean < LAST_MU + S ) {
137     return poissonDeviateSmall ( getLocalEngin    134     return poissonDeviateSmall ( getLocalEngine(), defaultMean );
138   } else {                                        135   } else {
139     return poissonDeviateQuick ( getLocalEngin    136     return poissonDeviateQuick ( getLocalEngine(), a0, a1, a2, sigma );
140   }                                               137   }
141 } // fire()                                       138 } // fire()
142                                                   139 
143 long RandPoissonQ::shoot(HepRandomEngine* anEn    140 long RandPoissonQ::shoot(HepRandomEngine* anEngine, double mean) {
144                                                   141 
145   // The following variables, static to this m    142   // The following variables, static to this method, apply to the 
146   // last time a large mean was supplied; they    143   // last time a large mean was supplied; they obviate certain calculations
147   // if consecutive calls use the same mean.      144   // if consecutive calls use the same mean.
148                                                   145 
149   static CLHEP_THREAD_LOCAL double lastLargeMe << 146   static double lastLargeMean = -1.;  // Mean from previous shoot 
150           // requiring poissonDeviateQuick()      147           // requiring poissonDeviateQuick()
151   static CLHEP_THREAD_LOCAL double lastA0;     << 148   static double lastA0;   
152   static CLHEP_THREAD_LOCAL double lastA1;     << 149   static double lastA1;   
153   static CLHEP_THREAD_LOCAL double lastA2;     << 150   static double lastA2;   
154   static CLHEP_THREAD_LOCAL double lastSigma;  << 151   static double lastSigma;    
155                                                   152 
156   if ( mean < LAST_MU + S ) {                     153   if ( mean < LAST_MU + S ) {
157     return poissonDeviateSmall ( anEngine, mea    154     return poissonDeviateSmall ( anEngine, mean );
158   } else {                                        155   } else {
159     if ( mean != lastLargeMean ) {                156     if ( mean != lastLargeMean ) {
160       // Compute the coefficients defining the    157       // Compute the coefficients defining the quadratic transformation from a 
161       // Gaussian to a Poisson for this mean.     158       // Gaussian to a Poisson for this mean.  Also save these for next time.
162       double sig2 = mean * (.9998654 - .08346/    159       double sig2 = mean * (.9998654 - .08346/mean);
163       lastSigma = std::sqrt(sig2);                160       lastSigma = std::sqrt(sig2);
164       double t = 1./sig2;                         161       double t = 1./sig2;
165       lastA2 = t*(1./6.) + t*t*(1./324.);         162       lastA2 = t*(1./6.) + t*t*(1./324.);
166       lastA1 = std::sqrt (1-2*lastA2*lastA2*si    163       lastA1 = std::sqrt (1-2*lastA2*lastA2*sig2);
167       lastA0 = mean + .5 - sig2 * lastA2;         164       lastA0 = mean + .5 - sig2 * lastA2;
168     }                                             165     }
169     return poissonDeviateQuick ( anEngine, las    166     return poissonDeviateQuick ( anEngine, lastA0, lastA1, lastA2, lastSigma );
170   }                                               167   }
171                                                   168 
172 } // shoot (anEngine, mean)                       169 } // shoot (anEngine, mean)
173                                                   170 
174 void RandPoissonQ::shootArray(const int size,     171 void RandPoissonQ::shootArray(const int size, long* vect, double m) {
175   for( long* v = vect; v != vect + size; ++v )    172   for( long* v = vect; v != vect + size; ++v )
176     *v = shoot(m);                                173     *v = shoot(m);
177      // Note: We could test for m > 100, and i    174      // Note: We could test for m > 100, and if it is, precompute a0, a1, a2, 
178      // and sigma and call the appropriate for    175      // and sigma and call the appropriate form of poissonDeviateQuick.  
179      // But since those are cached anyway, not    176      // But since those are cached anyway, not much time would be saved.
180 }                                                 177 }
181                                                   178 
182 void RandPoissonQ::shootArray(HepRandomEngine* << 
183                              long* vect, doubl << 
184   for( long* v = vect; v != vect + size; ++v ) << 
185     *v = shoot(anEngine,m1);                   << 
186 }                                              << 
187                                                << 
188 void RandPoissonQ::fireArray(const int size, l    179 void RandPoissonQ::fireArray(const int size, long* vect, double m) {
189   for( long* v = vect; v != vect + size; ++v )    180   for( long* v = vect; v != vect + size; ++v )
190     *v = fire( m );                               181     *v = fire( m );
191 }                                                 182 }
192                                                   183 
193 void RandPoissonQ::fireArray(const int size, l    184 void RandPoissonQ::fireArray(const int size, long* vect) {
194   for( long* v = vect; v != vect + size; ++v )    185   for( long* v = vect; v != vect + size; ++v )
195     *v = fire( defaultMean );                     186     *v = fire( defaultMean );
196 }                                                 187 }
197                                                   188 
198                                                   189 
199 // Quick Poisson deviate algorithm used by qui    190 // Quick Poisson deviate algorithm used by quick for large mu:
200                                                   191 
201 long RandPoissonQ::poissonDeviateQuick ( HepRa    192 long RandPoissonQ::poissonDeviateQuick ( HepRandomEngine *e, double mu ) {
202                                                   193 
203   // Compute the coefficients defining the qua    194   // Compute the coefficients defining the quadratic transformation from a 
204   // Gaussian to a Poisson:                       195   // Gaussian to a Poisson:
205                                                   196 
206   double sig2 = mu * (.9998654 - .08346/mu);      197   double sig2 = mu * (.9998654 - .08346/mu);
207   double sig = std::sqrt(sig2);                   198   double sig = std::sqrt(sig2);
208   // The multiplier corrects for fact that dis    199   // The multiplier corrects for fact that discretization of the form
209   // [gaussian+.5] increases the second moment    200   // [gaussian+.5] increases the second moment by a small amount.
210                                                   201 
211   double t = 1./sig2;                             202   double t = 1./sig2;
212                                                   203 
213   double sa2 = t*(1./6.) + t*t*(1./324.);         204   double sa2 = t*(1./6.) + t*t*(1./324.);
214   double sa1 = std::sqrt (1-2*sa2*sa2*sig2);      205   double sa1 = std::sqrt (1-2*sa2*sa2*sig2);
215   double sa0 = mu + .5 - sig2 * sa2;              206   double sa0 = mu + .5 - sig2 * sa2;
216                                                   207 
217   // The formula will be sa0 + sa1*x + sa2*x*x    208   // The formula will be sa0 + sa1*x + sa2*x*x where x has sigma of sq.
218   // The coeffeicients are chosen to match the    209   // The coeffeicients are chosen to match the first THREE moments of the 
219   // true Poisson distribution.                   210   // true Poisson distribution.
220                                                   211 
221   return poissonDeviateQuick ( e, sa0, sa1, sa    212   return poissonDeviateQuick ( e, sa0, sa1, sa2, sig ); 
222 }                                                 213 } 
223                                                   214 
224                                                   215 
225 long RandPoissonQ::poissonDeviateQuick ( HepRa    216 long RandPoissonQ::poissonDeviateQuick ( HepRandomEngine *e, 
226     double A0, double A1, double A2, double si    217     double A0, double A1, double A2, double sig) {
227 //                                                218 //
228 // Quick Poisson deviate algorithm used by qui    219 // Quick Poisson deviate algorithm used by quick for large mu:
229 //                                                220 //
230 // The principle:  For very large mu, a poisso    221 // The principle:  For very large mu, a poisson distribution can be approximated
231 // by a gaussian: return the integer part of m    222 // by a gaussian: return the integer part of mu + .5 + g where g is a unit 
232 // normal.  However, this yelds a miserable ap    223 // normal.  However, this yelds a miserable approximation at values as
233 // "large" as 100.  The primary problem is tha    224 // "large" as 100.  The primary problem is that the poisson distribution is 
234 // supposed to have a skew of 1/mu**2, and the    225 // supposed to have a skew of 1/mu**2, and the zero skew of the Guassian 
235 // leads to errors of order as big as 1/mu**2.    226 // leads to errors of order as big as 1/mu**2.
236 //                                                227 //
237 // We substitute for the gaussian a quadratic     228 // We substitute for the gaussian a quadratic function of that gaussian random.
238 // The expression looks very nearly like mu +     229 // The expression looks very nearly like mu + .5 - 1/6 + g + g**2/(6*mu).  
239 // The small positive quadratic term causes th    230 // The small positive quadratic term causes the resulting variate to have 
240 // a positive skew; the -1/6 constant term is     231 // a positive skew; the -1/6 constant term is there to correct for this bias 
241 // in the mean.  By adjusting these two and th    232 // in the mean.  By adjusting these two and the linear term, we can match the
242 // first three moments to high accuracy in 1/m    233 // first three moments to high accuracy in 1/mu.
243 //                                                234 //
244 // The sigma used is not precisely sqrt(mu) si    235 // The sigma used is not precisely sqrt(mu) since a rounded-off Gaussian
245 // has a second moment which is slightly large    236 // has a second moment which is slightly larger than that of the Gaussian.  
246 // To compensate, sig is multiplied by a facto    237 // To compensate, sig is multiplied by a factor which is slightly less than 1.
247                                                   238 
248   //  double g = RandGauss::shootQuick( e );      239   //  double g = RandGauss::shootQuick( e );   // TEMPORARY MOD:
249   double g = RandGaussQ::shoot( e );   // Unit    240   double g = RandGaussQ::shoot( e );   // Unit normal
250   g *= sig;                                       241   g *= sig;
251   double p = A2*g*g + A1*g + A0;                  242   double p = A2*g*g + A1*g + A0;
252   if ( p < 0 ) return 0;  // Shouldn't ever po    243   if ( p < 0 ) return 0;  // Shouldn't ever possibly happen since 
253         // mean should not be less than 100, b    244         // mean should not be less than 100, but
254         // we check due to paranoia.              245         // we check due to paranoia.
255   if ( p > MAXIMUM_POISSON_DEVIATE ) p = MAXIM    246   if ( p > MAXIMUM_POISSON_DEVIATE ) p = MAXIMUM_POISSON_DEVIATE;
256                                                   247 
257   return long(p);                                 248   return long(p);
258                                                   249 
259 } // poissonDeviateQuick ()                       250 } // poissonDeviateQuick ()
260                                                   251 
261                                                   252 
262                                                   253 
263 long RandPoissonQ::poissonDeviateSmall (HepRan    254 long RandPoissonQ::poissonDeviateSmall (HepRandomEngine * e, double mean) {
264   long N1;                                        255   long N1;
265   long N2;                                        256   long N2;
266   // The following are for later use to form a    257   // The following are for later use to form a secondary random s:
267   double rRange;      // This will hold the in    258   double rRange;      // This will hold the interval between cdf for the
268           // computed N1 and cdf for N1+1.        259           // computed N1 and cdf for N1+1.
269   double rRemainder = 0; // This will hold the    260   double rRemainder = 0; // This will hold the length into that interval.
270                                                   261 
271   // Coming in, mean should not be more than L    262   // Coming in, mean should not be more than LAST_MU + S.  However, we will 
272   // be paranoid and test for this:               263   // be paranoid and test for this:
273                                                   264 
274   if ( mean > LAST_MU + S ) {                     265   if ( mean > LAST_MU + S ) {
275     return RandPoisson::shoot(e, mean);           266     return RandPoisson::shoot(e, mean);
276   }                                               267   }
277                                                   268 
278   if (mean <= 0) {                                269   if (mean <= 0) {
279     return 0;     // Perhaps we ought to balk     270     return 0;     // Perhaps we ought to balk harder here!
280   }                                               271   }
281                                                   272 
282   // >>> 1 <<<                                    273   // >>> 1 <<< 
283   //  Generate the first random, which we alwa    274   //  Generate the first random, which we always will need.
284                                                   275 
285   double r = e->flat();                           276   double r = e->flat();
286                                                   277 
287   // >>> 2 <<<                                    278   // >>> 2 <<< 
288   //  For small mean, below the start of the t    279   //  For small mean, below the start of the tables, 
289   //  do the series for cdf directly.             280   //  do the series for cdf directly.  
290                                                   281 
291   // In this case, since we know the series wi    282   // In this case, since we know the series will terminate relatively quickly, 
292   // almost alwaye use a precomputed 1/N array    283   // almost alwaye use a precomputed 1/N array without fear of overrunning it.
293                                                   284 
294   static const double oneOverN[50] =              285   static const double oneOverN[50] = 
295   {    0,   1.,    1/2.,  1/3.,  1/4.,  1/5.,     286   {    0,   1.,    1/2.,  1/3.,  1/4.,  1/5.,  1/6.,  1/7.,  1/8.,  1/9., 
296    1/10.,  1/11.,  1/12., 1/13., 1/14., 1/15.,    287    1/10.,  1/11.,  1/12., 1/13., 1/14., 1/15., 1/16., 1/17., 1/18., 1/19., 
297    1/20.,  1/21.,  1/22., 1/23., 1/24., 1/25.,    288    1/20.,  1/21.,  1/22., 1/23., 1/24., 1/25., 1/26., 1/27., 1/28., 1/29.,
298    1/30.,  1/31.,  1/32., 1/33., 1/34., 1/35.,    289    1/30.,  1/31.,  1/32., 1/33., 1/34., 1/35., 1/36., 1/37., 1/38., 1/39., 
299    1/40.,  1/41.,  1/42., 1/43., 1/44., 1/45.,    290    1/40.,  1/41.,  1/42., 1/43., 1/44., 1/45., 1/46., 1/47., 1/48., 1/49. };
300                                                   291 
301                                                   292 
302   if ( mean < FIRST_MU ) {                        293   if ( mean < FIRST_MU ) {
303                                                   294 
304     long N = 0;                                   295     long N = 0;
305     double term = std::exp(-mean);                296     double term = std::exp(-mean);
306     double cdf = term;                            297     double cdf = term;
307                                                   298 
308     if ( r < (1 - 1.0E-9) ) {                     299     if ( r < (1 - 1.0E-9) ) {
309       //                                          300       //
310       // **** This is a normal path: ****         301       // **** This is a normal path: ****
311       //                                          302       //
312       // Except when r is very close to 1, it     303       // Except when r is very close to 1, it is certain that we will exceed r 
313       // before the 30-th term in the series,     304       // before the 30-th term in the series, so a simple while loop is OK.
314       const double* oneOverNptr = oneOverN;       305       const double* oneOverNptr = oneOverN;
315       while( cdf <= r ) {                         306       while( cdf <= r ) {
316         N++ ;                                     307         N++ ;  
317         oneOverNptr++;                            308         oneOverNptr++;
318         term *= ( mean * (*oneOverNptr) );        309         term *= ( mean * (*oneOverNptr) );
319         cdf  += term;                             310         cdf  += term;
320       }                                           311       }
321       return N;                                   312       return N;
322       //                                          313       //
323       // **** ****                                314       // **** ****
324       //                                          315       //
325     } else { // r is almost 1...                  316     } else { // r is almost 1...
326       // For r very near to 1 we would have to    317       // For r very near to 1 we would have to check that we don't fall
327       // off the end of the table of 1/N.  Sin    318       // off the end of the table of 1/N.  Since this is very rare, we just
328       // ignore the table and do the identical    319       // ignore the table and do the identical while loop, using explicit 
329       // division.                                320       // division.
330       double cdf0;                                321       double cdf0;
331       while ( cdf <= r ) {                        322       while ( cdf <= r ) {
332         N++ ;                                     323         N++ ;  
333         term *= ( mean / N );                     324         term *= ( mean / N );
334         cdf0 = cdf;                               325         cdf0 = cdf;
335         cdf  += term;                             326         cdf  += term;
336   if (cdf == cdf0) break; // Can't happen, but    327   if (cdf == cdf0) break; // Can't happen, but just in case...
337       }                                           328       }
338       return N;                                   329       return N;
339     } // end of if ( r compared to (1 - 1.0E-9    330     } // end of if ( r compared to (1 - 1.0E-9) )
340                                                   331 
341   } // End of the code for mean < FIRST_MU        332   } // End of the code for mean < FIRST_MU
342                                                   333 
343   // >>> 3 <<<                                    334   // >>> 3 <<< 
344   //  Find the row of the tables corresponding    335   //  Find the row of the tables corresponding to the highest tabulated mu
345   //  which is no greater than our actual mean    336   //  which is no greater than our actual mean.
346                                                   337 
347   int rowNumber = int((mean - FIRST_MU)/S);       338   int rowNumber = int((mean - FIRST_MU)/S);
348   const double * cdfs = &poissonTables [rowNum    339   const double * cdfs = &poissonTables [rowNumber*ENTRIES]; 
349   double mu = FIRST_MU + rowNumber*S;             340   double mu = FIRST_MU + rowNumber*S;
350   double deltaMu = mean - mu;                     341   double deltaMu = mean - mu;
351   int Nmin = int(mu - BELOW);                     342   int Nmin = int(mu - BELOW);
352   if (Nmin < 1) Nmin = 1;                         343   if (Nmin < 1) Nmin = 1;
353   int Nmax = Nmin + (ENTRIES - 1);                344   int Nmax = Nmin + (ENTRIES - 1);
354                                                   345 
355                                                   346 
356   // >>> 4 <<<                                    347   // >>> 4 <<< 
357   //  If r is less that the smallest entry in     348   //  If r is less that the smallest entry in the row, then 
358   //  generate the deviate directly from the s    349   //  generate the deviate directly from the series.  
359                                                   350 
360   if ( r < cdfs[0] ) {                            351   if ( r < cdfs[0] ) {
361                                                   352   
362     // In this case, we are tempted to use the    353     // In this case, we are tempted to use the actual mean, and not 
363     // generate a second deviate to account fo    354     // generate a second deviate to account for the leftover part mean - mu.
364     // That would be an error, generating a di    355     // That would be an error, generating a distribution with enough excess
365     // at Nmin + (mean-mu)/2 to be detectable     356     // at Nmin + (mean-mu)/2 to be detectable in 4,000,000 trials.
366                                                   357 
367     // Since this case is very rare (never mor    358     // Since this case is very rare (never more than .2% of the r values)
368     // and can happen where N will be large (u    359     // and can happen where N will be large (up to 65 for the mu=95 row)
369     // we use explicit division so as to avoid    360     // we use explicit division so as to avoid having to worry about running
370     // out of oneOverN table.                     361     // out of oneOverN table.
371                                                   362 
372     long N = 0;                                   363     long N = 0;
373     double term = std::exp(-mu);                  364     double term = std::exp(-mu);
374     double cdf = term;                            365     double cdf = term;
375     double cdf0;                                  366     double cdf0;
376                                                   367 
377     while(cdf <= r) {                             368     while(cdf <= r) {
378         N++ ;                                     369         N++ ;  
379         term *= ( mu / N );                       370         term *= ( mu / N );
380         cdf0 = cdf;                               371         cdf0 = cdf;
381         cdf  += term;                             372         cdf  += term;
382   if (cdf == cdf0) break; // Can't happen, but    373   if (cdf == cdf0) break; // Can't happen, but just in case...
383     }                                             374     }
384     N1 = N;                                       375     N1 = N;
385     // std::cout << r << "   " << N << "   ";     376     // std::cout << r << "   " << N << "   ";
386     // DBG_small = true;                          377     // DBG_small = true;
387     rRange = 0;   // In this case there is alw    378     rRange = 0;   // In this case there is always a second r needed
388                                                   379 
389   } // end of small-r case                        380   } // end of small-r case
390                                                   381 
391                                                   382 
392   // >>> 5 <<<                                    383   // >>> 5 <<< 
393   //  Assuming r lies within the scope of the     384   //  Assuming r lies within the scope of the row for this mu, find the 
394   //  largest entry not greater than r.  N1 is    385   //  largest entry not greater than r.  N1 is the N corresponding to the 
395   //  index a.                                    386   //  index a.
396                                                   387 
397   else if ( r < cdfs[ENTRIES-1] ) {     // r i    388   else if ( r < cdfs[ENTRIES-1] ) {     // r is also >= cdfs[0]
398                                                   389 
399     //                                            390     //
400     // **** This is the normal code path ****     391     // **** This is the normal code path ****
401     //                                            392     //
402                                                   393 
403     int a = 0;                  // Highest val    394     int a = 0;                  // Highest value of index such that cdfs[a]
404         // is known NOT to be greater than r.     395         // is known NOT to be greater than r.
405     int b = ENTRIES - 1;  // Lowest value of i    396     int b = ENTRIES - 1;  // Lowest value of index such that cdfs[b] is
406         // known to exeed r.                      397         // known to exeed r.
407                                                   398 
408     while (b != (a+1) ) {                         399     while (b != (a+1) ) {
409       int c = (a+b+1)>>1;                         400       int c = (a+b+1)>>1;
410       if (r > cdfs[c]) {                          401       if (r > cdfs[c]) {
411         a = c;                                    402         a = c;
412       } else {                                    403       } else {
413         b = c;                                    404         b = c;
414       }                                           405       }
415     }                                             406     }
416                                                   407 
417     N1 = Nmin + a;                                408     N1 = Nmin + a;
418     rRange = cdfs[a+1] - cdfs[a];                 409     rRange = cdfs[a+1] - cdfs[a];
419     rRemainder = r - cdfs[a];                     410     rRemainder = r - cdfs[a];
420                                                   411 
421     //                                            412     //
422     // **** ****                                  413     // **** ****
423     //                                            414     //
424                                                   415 
425   } // end of medium-r (normal) case              416   } // end of medium-r (normal) case
426                                                   417 
427                                                   418 
428   // >>> 6 <<<                                    419   // >>> 6 <<< 
429   //  If r exceeds the greatest entry in the t    420   //  If r exceeds the greatest entry in the table for this mu, then start 
430   //  from that cdf, and use the series to com    421   //  from that cdf, and use the series to compute from there until r is 
431   //  exceeded.                                   422   //  exceeded.  
432                                                   423 
433   else { //     if ( r >= cdfs[ENTRIES-1] ) {     424   else { //     if ( r >= cdfs[ENTRIES-1] ) {
434                                                   425  
435     // Here, division must be done explicitly,    426     // Here, division must be done explicitly, and we must also protect against
436     // roundoff preventing termination.           427     // roundoff preventing termination.
437                                                   428 
438   //                                              429   // 
439   //+++ cdfs[ENTRIES-1] is exp(-mu) sum (mu**m    430   //+++ cdfs[ENTRIES-1] is exp(-mu) sum (mu**m/m! , m=0 to Nmax) 
440   //+++ (where Nmax = mu - BELOW + ENTRIES - 1    431   //+++ (where Nmax = mu - BELOW + ENTRIES - 1)
441   //+++ cdfs[ENTRIES-1]-cdfs[ENTRIES-2] is exp    432   //+++ cdfs[ENTRIES-1]-cdfs[ENTRIES-2] is exp(-mu) mu**(Nmax)/(Nmax)!
442   //+++ If the sum up to k-1 <= r < sum up to     433   //+++ If the sum up to k-1 <= r < sum up to k, then N = k-1
443   //+++ Consider k = Nmax in the above stateme    434   //+++ Consider k = Nmax in the above statement:
444   //+++ If cdfs[ENTRIES-2] <= r < cdfs[ENTRIES    435   //+++ If cdfs[ENTRIES-2] <= r < cdfs[ENTRIES-1], N would be Nmax-1 
445   //+++ But here r >= cdfs[ENTRIES-1] so N >=     436   //+++ But here r >= cdfs[ENTRIES-1] so N >= Nmax
446   //                                              437   //
447                                                   438 
448   // Erroneous:                                   439   // Erroneous:
449   //+++ cdfs[ENTRIES-1] is exp(-mu) sum (mu**m    440   //+++ cdfs[ENTRIES-1] is exp(-mu) sum (mu**m/m! , m=0 to Nmax-1) 
450   //+++ cdfs[ENTRIES-1]-cdfs[ENTRIES-2] is exp    441   //+++ cdfs[ENTRIES-1]-cdfs[ENTRIES-2] is exp(-mu) mu**(Nmax-1)/(Nmax-1)!
451   //+++ If a sum up to k-1 <= r < sum up to k,    442   //+++ If a sum up to k-1 <= r < sum up to k, then N = k-1
452   //+++ So if cdfs[ENTRIES-1] were > r, N woul    443   //+++ So if cdfs[ENTRIES-1] were > r, N would be Nmax-1 (or less)
453   //+++ But here r >= cdfs[ENTRIES-1] so N >=     444   //+++ But here r >= cdfs[ENTRIES-1] so N >= Nmax
454   //                                              445   //
455                                                   446 
456     //  std::cout << "r = " << r << " mu = " <    447     //  std::cout << "r = " << r << " mu = " << mu << "\n";
457     long N = Nmax -1;                             448     long N = Nmax -1;
458     double cdf = cdfs[ENTRIES-1];                 449     double cdf = cdfs[ENTRIES-1];
459     double term = cdf - cdfs[ENTRIES-2];          450     double term = cdf - cdfs[ENTRIES-2];
460     double cdf0;                                  451     double cdf0;
461     while(cdf <= r) {                             452     while(cdf <= r) {
462         N++ ;                                     453         N++ ;  
463     //  std::cout << "  N " << N << " term " <    454     //  std::cout << "  N " << N << " term " << 
464     //  term << " cdf " << cdf << "\n";           455     //  term << " cdf " << cdf << "\n";
465         term *= ( mu / N );                       456         term *= ( mu / N );
466   cdf0  = cdf;                                    457   cdf0  = cdf;
467         cdf  += term;                             458         cdf  += term;
468   if (cdf == cdf0) break; // If term gets so s    459   if (cdf == cdf0) break; // If term gets so small cdf stops increasing,
469         // terminate using that value of N sin    460         // terminate using that value of N since we
470         // would never reach r.                   461         // would never reach r.
471     }                                             462     }
472     N1 = N;                                       463     N1 = N;
473     rRange = 0;   // We can't validly omit the    464     rRange = 0;   // We can't validly omit the second true random
474                                                   465 
475   //      N = Nmax -1;                            466   //      N = Nmax -1;
476   //      cdf = cdfs[ENTRIES-1];                  467   //      cdf = cdfs[ENTRIES-1];
477   //      term = cdf - cdfs[ENTRIES-2];           468   //      term = cdf - cdfs[ENTRIES-2];
478   //      for (int isxz=0; isxz < 100; isxz++)    469   //      for (int isxz=0; isxz < 100; isxz++) {
479   //          N++ ;                               470   //          N++ ;  
480   //          term *= ( mu / N );                 471   //          term *= ( mu / N );
481   //    cdf0  = cdf;                              472   //    cdf0  = cdf;
482   //          cdf  += term;                       473   //          cdf  += term;
483   //      }                                       474   //      }
484   //      std::cout.precision(20);                475   //      std::cout.precision(20);
485   //      std::cout << "Final sum is " << cdf     476   //      std::cout << "Final sum is " << cdf << "\n";
486                                                   477 
487   } // end of large-r case                        478   } // end of large-r case
488                                                   479 
489                                                   480 
490                                                   481 
491   // >>> 7 <<<                                    482   // >>> 7 <<< 
492   //  Form a second random, s, based on the po    483   //  Form a second random, s, based on the position of r within the range
493   //  of this table entry to the next entry.      484   //  of this table entry to the next entry.  
494                                                   485 
495   // However, if this range is very small, the    486   // However, if this range is very small, then we lose too many bits of
496   // randomness.  In that situation, we genera    487   // randomness.  In that situation, we generate a second random for s.
497                                                   488 
498   double s;                                       489   double s;
499                                                   490 
500   static const double MINRANGE = .01;   // Sac    491   static const double MINRANGE = .01;   // Sacrifice up to two digits of 
501                 // randomness when using r to     492                 // randomness when using r to produce
502           // a second random s.  Leads to up t    493           // a second random s.  Leads to up to
503           // .09 extra randoms each time.         494           // .09 extra randoms each time.
504                                                   495 
505   if ( rRange > MINRANGE ) {                      496   if ( rRange > MINRANGE ) {
506     //                                            497     //
507     // **** This path taken 90% of the time **    498     // **** This path taken 90% of the time ****
508     //                                            499     //
509     s = rRemainder / rRange;                      500     s = rRemainder / rRange;
510   } else {                                        501   } else {
511     s = e->flat();  // extra true random neede    502     s = e->flat();  // extra true random needed about one time in 10.
512   }                                               503   }
513                                                   504 
514   // >>> 8 <<<                                    505   // >>> 8 <<< 
515   //  Use the direct summation method to form     506   //  Use the direct summation method to form a second poisson deviate N2 
516   //  from deltaMu and s.                         507   //  from deltaMu and s.
517                                                   508 
518   N2 = 0;                                         509   N2 = 0;
519   double term = std::exp(-deltaMu);               510   double term = std::exp(-deltaMu);
520   double cdf = term;                              511   double cdf = term;
521                                                   512 
522   if ( s < (1 - 1.0E-10) ) {                      513   if ( s < (1 - 1.0E-10) ) {
523       //                                          514       //
524       // This is the normal path:                 515       // This is the normal path:
525       //                                          516       //
526       const double* oneOverNptr = oneOverN;       517       const double* oneOverNptr = oneOverN;
527       while( cdf <= s ) {                         518       while( cdf <= s ) {
528         N2++ ;                                    519         N2++ ;  
529         oneOverNptr++;                            520         oneOverNptr++;
530         term *= ( deltaMu * (*oneOverNptr) );     521         term *= ( deltaMu * (*oneOverNptr) );
531         cdf  += term;                             522         cdf  += term;
532       }                                           523       }
533   } else { // s is almost 1...                    524   } else { // s is almost 1...
534       while( cdf <= s ) {                         525       while( cdf <= s ) {
535         N2++ ;                                    526         N2++ ;  
536         term *= ( deltaMu / N2 );                 527         term *= ( deltaMu / N2 );
537         cdf  += term;                             528         cdf  += term;
538       }                                           529       }
539   } // end of if ( s compared to (1 - 1.0E-10)    530   } // end of if ( s compared to (1 - 1.0E-10) )
540                                                   531 
541   // >>> 9 <<<                                    532   // >>> 9 <<< 
542   //  The result is the sum of those two devia    533   //  The result is the sum of those two deviates
543                                                   534 
544     // if (DBG_small) {                           535     // if (DBG_small) {
545     //   std::cout << N2 << "   " << N1+N2 <<     536     //   std::cout << N2 << "   " << N1+N2 << "\n";
546     //   DBG_small = false;                       537     //   DBG_small = false;
547     // }                                          538     // }
548                                                   539 
549   return N1 + N2;                                 540   return N1 + N2;
550                                                   541 
551 } // poissonDeviate()                             542 } // poissonDeviate()
552                                                   543 
553 std::ostream & RandPoissonQ::put ( std::ostrea    544 std::ostream & RandPoissonQ::put ( std::ostream & os ) const {
554   long pr=os.precision(20);                    << 545   int pr=os.precision(20);
555   std::vector<unsigned long> t(2);                546   std::vector<unsigned long> t(2);
556   os << " " << name() << "\n";                    547   os << " " << name() << "\n";
557   os << "Uvec" << "\n";                           548   os << "Uvec" << "\n";
558   t = DoubConv::dto2longs(a0);                    549   t = DoubConv::dto2longs(a0);
559   os << a0 << " " << t[0] << " " << t[1] << "\    550   os << a0 << " " << t[0] << " " << t[1] << "\n";
560   t = DoubConv::dto2longs(a1);                    551   t = DoubConv::dto2longs(a1);
561   os << a1 << " " << t[0] << " " << t[1] << "\    552   os << a1 << " " << t[0] << " " << t[1] << "\n";
562   t = DoubConv::dto2longs(a2);                    553   t = DoubConv::dto2longs(a2);
563   os << a2 << " " << t[0] << " " << t[1] << "\    554   os << a2 << " " << t[0] << " " << t[1] << "\n";
564   t = DoubConv::dto2longs(sigma);                 555   t = DoubConv::dto2longs(sigma);
565   os << sigma << " " << t[0] << " " << t[1] <<    556   os << sigma << " " << t[0] << " " << t[1] << "\n";
566   RandPoisson::put(os);                           557   RandPoisson::put(os);
567   os.precision(pr);                               558   os.precision(pr);
568   return os;                                      559   return os;
569 #ifdef REMOVED                                    560 #ifdef REMOVED
570   int pr=os.precision(20);                        561   int pr=os.precision(20);
571   os << " " << name() << "\n";                    562   os << " " << name() << "\n";
572   os << a0 << " " << a1 << " " << a2 << "\n";     563   os << a0 << " " << a1 << " " << a2 << "\n";
573   os << sigma << "\n";                            564   os << sigma << "\n";
574   RandPoisson::put(os);                           565   RandPoisson::put(os);
575   os.precision(pr);                               566   os.precision(pr);
576   return os;                                      567   return os;
577 #endif                                            568 #endif
578 }                                                 569 }
579                                                   570 
580 std::istream & RandPoissonQ::get ( std::istrea    571 std::istream & RandPoissonQ::get ( std::istream & is ) {
581   std::string inName;                             572   std::string inName;
582   is >> inName;                                   573   is >> inName;
583   if (inName != name()) {                         574   if (inName != name()) {
584     is.clear(std::ios::badbit | is.rdstate());    575     is.clear(std::ios::badbit | is.rdstate());
585     std::cerr << "Mismatch when expecting to r    576     std::cerr << "Mismatch when expecting to read state of a "
586             << name() << " distribution\n"        577             << name() << " distribution\n"
587         << "Name found was " << inName            578         << "Name found was " << inName
588         << "\nistream is left in the badbit st    579         << "\nistream is left in the badbit state\n";
589     return is;                                    580     return is;
590   }                                               581   }
591   if (possibleKeywordInput(is, "Uvec", a0)) {     582   if (possibleKeywordInput(is, "Uvec", a0)) {
592     std::vector<unsigned long> t(2);              583     std::vector<unsigned long> t(2);
593     is >> a0 >> t[0] >> t[1]; a0 = DoubConv::l    584     is >> a0 >> t[0] >> t[1]; a0 = DoubConv::longs2double(t); 
594     is >> a1 >> t[0] >> t[1]; a1 = DoubConv::l    585     is >> a1 >> t[0] >> t[1]; a1 = DoubConv::longs2double(t); 
595     is >> a2 >> t[0] >> t[1]; a2 = DoubConv::l    586     is >> a2 >> t[0] >> t[1]; a2 = DoubConv::longs2double(t); 
596     is >> sigma >> t[0] >> t[1]; sigma = DoubC    587     is >> sigma >> t[0] >> t[1]; sigma = DoubConv::longs2double(t); 
597     RandPoisson::get(is);                         588     RandPoisson::get(is);
598     return is;                                    589     return is;
599   }                                               590   }
600   // is >> a0 encompassed by possibleKeywordIn    591   // is >> a0 encompassed by possibleKeywordInput
601   is >> a1 >> a2 >> sigma;                        592   is >> a1 >> a2 >> sigma;
602   RandPoisson::get(is);                           593   RandPoisson::get(is);
603   return is;                                      594   return is;
604 }                                                 595 }
605                                                   596 
606 }  // namespace CLHEP                             597 }  // namespace CLHEP
607                                                   598 
608                                                   599