RandPoissonQ.cc

Go to the documentation of this file.
00001 // $Id:$
00002 // -*- C++ -*-
00003 //
00004 // -----------------------------------------------------------------------
00005 //                             HEP Random
00006 //                         --- RandPoissonQ ---
00007 //                      class implementation file
00008 // -----------------------------------------------------------------------
00009 
00010 // =======================================================================
00011 // M. Fischler    - Implemented new, much faster table-driven algorithm
00012 //                  applicable for mu < 100
00013 //                - Implemented "quick()" methods, shich are the same as the
00014 //                  new methods for mu < 100 and are a skew-corrected gaussian
00015 //                  approximation for large mu.
00016 // M. Fischler    - Removed mean=100 from the table-driven set, since it
00017 //                  uses a value just off the end of the table.  (April 2004)
00018 // M Fischler     - put and get to/from streams 12/15/04
00019 // M Fischler     - Utilize RandGaussQ rather than RandGauss, as clearly 
00020 //                  intended by the inclusion of RandGaussQ.h.  Using RandGauss
00021 //                  introduces a subtle trap in that the state of RandPoissonQ
00022 //                  can never be properly captured without also saveing the
00023 //                  state of RandGauss!  RandGaussQ is, on the other hand,
00024 //                  stateless except for the engine used.
00025 // M Fisculer     - Modified use of wrong engine when shoot (anEngine, mean)
00026 //                  is called.  This flaw was preventing any hope of proper
00027 //                  saving and restoring in the instance cases.
00028 // M Fischler     - fireArray using defaultMean 2/10/05
00029 // M Fischler         - put/get to/from streams uses pairs of ulongs when
00030 //                      + storing doubles avoid problems with precision 
00031 //                      4/14/05
00032 // M Fisculer     - Modified use of shoot (mean) instead of 
00033 //                  shoot(getLocalEngine(), mean) when fire(mean) is called.  
00034 //                  This flaw was causing bad "cross-talk" between modules
00035 //                  in CMS, where one used its own engine, and the other 
00036 //                  used the static generator.  10/18/07
00037 //
00038 // =======================================================================
00039 
00040 #include "CLHEP/Random/RandPoissonQ.h"
00041 #include "CLHEP/Random/RandGaussQ.h"
00042 #include "CLHEP/Random/DoubConv.h"
00043 #include "CLHEP/Random/Stat.h"
00044 #include <cmath>        // for std::pow()
00045 
00046 namespace CLHEP {
00047 
00048 std::string RandPoissonQ::name() const {return "RandPoissonQ";}
00049 HepRandomEngine & RandPoissonQ::engine() {return RandPoisson::engine();}
00050 
00051 // Initialization of static data:  Note that this is all const static data,
00052 // so that saveEngineStatus properly saves all needed information. 
00053 
00054   // The following MUST MATCH the corresponding values used (in
00055   // poissonTables.cc) when poissonTables.cdat was created.
00056 
00057 const double RandPoissonQ::FIRST_MU = 10;// lowest mu value in table
00058 const double RandPoissonQ::LAST_MU =  95;// highest mu value
00059 const double RandPoissonQ::S = 5;        // Spacing between mu values
00060 const int RandPoissonQ::BELOW = 30;      // Starting point for N is at mu - BELOW
00061 const int RandPoissonQ::ENTRIES = 51;    // Number of entries in each mu row
00062 
00063 const double RandPoissonQ::MAXIMUM_POISSON_DEVIATE = 2.0E9;
00064         // Careful -- this is NOT the maximum number that can be held in 
00065         // a long.  It actually should be some large number of sigma below
00066         // that.  
00067 
00068   // Here comes the big (9K bytes) table, kept in a file of 
00069   // ENTRIES * (FIRST_MU - LAST_MU + 1)/S doubles
00070 
00071 static const double poissonTables [ 51 * ( (95-10)/5 + 1 ) ] = {
00072 #include "CLHEP/Random/poissonTables.cdat"
00073 };
00074 
00075 //
00076 // Constructors and destructors:
00077 //
00078 
00079 RandPoissonQ::~RandPoissonQ() {
00080 }
00081 
00082 void RandPoissonQ::setupForDefaultMu() {
00083 
00084   // The following are useful for quick approximation, for large mu
00085   
00086   double sig2 = defaultMean * (.9998654 - .08346/defaultMean);
00087   sigma = std::sqrt(sig2);
00088         // sigma for the Guassian which approximates the Poisson -- naively
00089         // sqrt (defaultMean).
00090         //
00091         // The multiplier corrects for fact that discretization of the form
00092         // [gaussian+.5] increases the second moment by a small amount.
00093 
00094   double t = 1./(sig2);
00095 
00096   a2 = t/6 + t*t/324;
00097   a1 = std::sqrt (1-2*a2*a2*sig2);
00098   a0 = defaultMean + .5 - sig2 * a2;
00099 
00100   // The formula will be a0 + a1*x + a2*x*x where x has 2nd moment of sigma.
00101   // The coeffeicients are chosen to match the first THREE moments of the 
00102   // true Poisson distribution.   
00103   // 
00104   // Actually, if the correction for discretization were not needed, then 
00105   // a2 could be taken one order higher by adding t*t*t/5832.  However,
00106   // the discretization correction is not perfect, leading to inaccuracy
00107   // on the order to 1/mu**2, so adding a third term is overkill.  
00108 
00109 } // setupForDefaultMu() 
00110 
00111 
00112 //
00113 // fire, quick, operator(), and shoot methods:
00114 //
00115 
00116 long RandPoissonQ::shoot(double xm) {
00117   return shoot(getTheEngine(), xm);
00118 }
00119 
00120 double RandPoissonQ::operator()() {
00121   return (double) fire();
00122 }
00123 
00124 double RandPoissonQ::operator()( double mean ) {
00125   return (double) fire(mean);
00126 }
00127 
00128 long RandPoissonQ::fire(double mean) {
00129   return shoot(getLocalEngine(), mean);
00130 }
00131 
00132 long RandPoissonQ::fire() {
00133   if ( defaultMean < LAST_MU + S ) {
00134     return poissonDeviateSmall ( getLocalEngine(), defaultMean );
00135   } else {
00136     return poissonDeviateQuick ( getLocalEngine(), a0, a1, a2, sigma );
00137   }
00138 } // fire()
00139 
00140 long RandPoissonQ::shoot(HepRandomEngine* anEngine, double mean) {
00141 
00142   // The following variables, static to this method, apply to the 
00143   // last time a large mean was supplied; they obviate certain calculations
00144   // if consecutive calls use the same mean.
00145 
00146   static double lastLargeMean = -1.;    // Mean from previous shoot 
00147                                         // requiring poissonDeviateQuick()
00148   static double lastA0;         
00149   static double lastA1;         
00150   static double lastA2;         
00151   static double lastSigma;              
00152 
00153   if ( mean < LAST_MU + S ) {
00154     return poissonDeviateSmall ( anEngine, mean );
00155   } else {
00156     if ( mean != lastLargeMean ) {
00157       // Compute the coefficients defining the quadratic transformation from a 
00158       // Gaussian to a Poisson for this mean.  Also save these for next time.
00159       double sig2 = mean * (.9998654 - .08346/mean);
00160       lastSigma = std::sqrt(sig2);
00161       double t = 1./sig2;
00162       lastA2 = t*(1./6.) + t*t*(1./324.);
00163       lastA1 = std::sqrt (1-2*lastA2*lastA2*sig2);
00164       lastA0 = mean + .5 - sig2 * lastA2;
00165     }
00166     return poissonDeviateQuick ( anEngine, lastA0, lastA1, lastA2, lastSigma );
00167   }
00168 
00169 } // shoot (anEngine, mean)
00170 
00171 void RandPoissonQ::shootArray(const int size, long* vect, double m) {
00172   for( long* v = vect; v != vect + size; ++v )
00173     *v = shoot(m);
00174      // Note: We could test for m > 100, and if it is, precompute a0, a1, a2, 
00175      // and sigma and call the appropriate form of poissonDeviateQuick.  
00176      // But since those are cached anyway, not much time would be saved.
00177 }
00178 
00179 void RandPoissonQ::fireArray(const int size, long* vect, double m) {
00180   for( long* v = vect; v != vect + size; ++v )
00181     *v = fire( m );
00182 }
00183 
00184 void RandPoissonQ::fireArray(const int size, long* vect) {
00185   for( long* v = vect; v != vect + size; ++v )
00186     *v = fire( defaultMean );
00187 }
00188 
00189 
00190 // Quick Poisson deviate algorithm used by quick for large mu:
00191 
00192 long RandPoissonQ::poissonDeviateQuick ( HepRandomEngine *e, double mu ) {
00193 
00194   // Compute the coefficients defining the quadratic transformation from a 
00195   // Gaussian to a Poisson:
00196 
00197   double sig2 = mu * (.9998654 - .08346/mu);
00198   double sig = std::sqrt(sig2);
00199         // The multiplier corrects for fact that discretization of the form
00200         // [gaussian+.5] increases the second moment by a small amount.
00201 
00202   double t = 1./sig2;
00203 
00204   double sa2 = t*(1./6.) + t*t*(1./324.);
00205   double sa1 = std::sqrt (1-2*sa2*sa2*sig2);
00206   double sa0 = mu + .5 - sig2 * sa2;
00207 
00208   // The formula will be sa0 + sa1*x + sa2*x*x where x has sigma of sq.
00209   // The coeffeicients are chosen to match the first THREE moments of the 
00210   // true Poisson distribution.
00211 
00212   return poissonDeviateQuick ( e, sa0, sa1, sa2, sig ); 
00213 } 
00214 
00215 
00216 long RandPoissonQ::poissonDeviateQuick ( HepRandomEngine *e, 
00217                 double A0, double A1, double A2, double sig) {
00218 //
00219 // Quick Poisson deviate algorithm used by quick for large mu:
00220 //
00221 // The principle:  For very large mu, a poisson distribution can be approximated
00222 // by a gaussian: return the integer part of mu + .5 + g where g is a unit 
00223 // normal.  However, this yelds a miserable approximation at values as
00224 // "large" as 100.  The primary problem is that the poisson distribution is 
00225 // supposed to have a skew of 1/mu**2, and the zero skew of the Guassian 
00226 // leads to errors of order as big as 1/mu**2.
00227 //
00228 // We substitute for the gaussian a quadratic function of that gaussian random.
00229 // The expression looks very nearly like mu + .5 - 1/6 + g + g**2/(6*mu).  
00230 // The small positive quadratic term causes the resulting variate to have 
00231 // a positive skew; the -1/6 constant term is there to correct for this bias 
00232 // in the mean.  By adjusting these two and the linear term, we can match the
00233 // first three moments to high accuracy in 1/mu.
00234 //
00235 // The sigma used is not precisely sqrt(mu) since a rounded-off Gaussian
00236 // has a second moment which is slightly larger than that of the Gaussian.  
00237 // To compensate, sig is multiplied by a factor which is slightly less than 1.
00238 
00239   //  double g = RandGauss::shootQuick( e );   // TEMPORARY MOD:
00240   double g = RandGaussQ::shoot( e );   // Unit normal
00241   g *= sig;
00242   double p = A2*g*g + A1*g + A0;
00243   if ( p < 0 ) return 0;        // Shouldn't ever possibly happen since 
00244                                 // mean should not be less than 100, but
00245                                 // we check due to paranoia.
00246   if ( p > MAXIMUM_POISSON_DEVIATE ) p = MAXIMUM_POISSON_DEVIATE;
00247 
00248   return long(p);
00249 
00250 } // poissonDeviateQuick ()
00251 
00252 
00253 
00254 long RandPoissonQ::poissonDeviateSmall (HepRandomEngine * e, double mean) {
00255   long N1;
00256   long N2;
00257   // The following are for later use to form a secondary random s:
00258   double rRange;            // This will hold the interval between cdf for the
00259                             // computed N1 and cdf for N1+1.
00260   double rRemainder = 0; // This will hold the length into that interval.
00261 
00262   // Coming in, mean should not be more than LAST_MU + S.  However, we will 
00263   // be paranoid and test for this:
00264 
00265   if ( mean > LAST_MU + S ) {
00266     return RandPoisson::shoot(e, mean);
00267   }
00268 
00269   if (mean <= 0) {
00270     return 0;                   // Perhaps we ought to balk harder here!
00271   }
00272 
00273   // >>> 1 <<< 
00274   //    Generate the first random, which we always will need.
00275 
00276   double r = e->flat();
00277 
00278   // >>> 2 <<< 
00279   //    For small mean, below the start of the tables, 
00280   //    do the series for cdf directly.  
00281 
00282   // In this case, since we know the series will terminate relatively quickly, 
00283   // almost alwaye use a precomputed 1/N array without fear of overrunning it.
00284 
00285   static const double oneOverN[50] = 
00286   {    0,   1.,    1/2.,  1/3.,  1/4.,  1/5.,  1/6.,  1/7.,  1/8.,  1/9., 
00287    1/10.,  1/11.,  1/12., 1/13., 1/14., 1/15., 1/16., 1/17., 1/18., 1/19., 
00288    1/20.,  1/21.,  1/22., 1/23., 1/24., 1/25., 1/26., 1/27., 1/28., 1/29.,
00289    1/30.,  1/31.,  1/32., 1/33., 1/34., 1/35., 1/36., 1/37., 1/38., 1/39., 
00290    1/40.,  1/41.,  1/42., 1/43., 1/44., 1/45., 1/46., 1/47., 1/48., 1/49. };
00291 
00292 
00293   if ( mean < FIRST_MU ) {
00294 
00295     long N = 0;
00296     double term = std::exp(-mean);
00297     double cdf = term;
00298 
00299     if ( r < (1 - 1.0E-9) ) {
00300       //
00301       // **** This is a normal path: ****
00302       //
00303       // Except when r is very close to 1, it is certain that we will exceed r 
00304       // before the 30-th term in the series, so a simple while loop is OK.
00305       const double* oneOverNptr = oneOverN;
00306       while( cdf <= r ) {
00307         N++ ;  
00308         oneOverNptr++;
00309         term *= ( mean * (*oneOverNptr) );
00310         cdf  += term;
00311       }
00312       return N;
00313       //
00314       // **** ****
00315       //
00316     } else { // r is almost 1...
00317       // For r very near to 1 we would have to check that we don't fall
00318       // off the end of the table of 1/N.  Since this is very rare, we just
00319       // ignore the table and do the identical while loop, using explicit 
00320       // division.
00321       double cdf0;
00322       while ( cdf <= r ) {
00323         N++ ;  
00324         term *= ( mean / N );
00325         cdf0 = cdf;
00326         cdf  += term;
00327         if (cdf == cdf0) break; // Can't happen, but just in case...
00328       }
00329       return N;
00330     } // end of if ( r compared to (1 - 1.0E-9) )
00331 
00332   } // End of the code for mean < FIRST_MU
00333 
00334   // >>> 3 <<< 
00335   //    Find the row of the tables corresponding to the highest tabulated mu
00336   //    which is no greater than our actual mean.
00337 
00338   int rowNumber = int((mean - FIRST_MU)/S);
00339   const double * cdfs = &poissonTables [rowNumber*ENTRIES]; 
00340   double mu = FIRST_MU + rowNumber*S;
00341   double deltaMu = mean - mu;
00342   int Nmin = int(mu - BELOW);
00343   if (Nmin < 1) Nmin = 1;
00344   int Nmax = Nmin + (ENTRIES - 1);
00345 
00346 
00347   // >>> 4 <<< 
00348   //    If r is less that the smallest entry in the row, then 
00349   //    generate the deviate directly from the series.  
00350 
00351   if ( r < cdfs[0] ) {
00352   
00353     // In this case, we are tempted to use the actual mean, and not 
00354     // generate a second deviate to account for the leftover part mean - mu.
00355     // That would be an error, generating a distribution with enough excess
00356     // at Nmin + (mean-mu)/2 to be detectable in 4,000,000 trials.
00357 
00358     // Since this case is very rare (never more than .2% of the r values)
00359     // and can happen where N will be large (up to 65 for the mu=95 row)
00360     // we use explicit division so as to avoid having to worry about running
00361     // out of oneOverN table.
00362 
00363     long N = 0;
00364     double term = std::exp(-mu);
00365     double cdf = term;
00366     double cdf0;
00367 
00368     while(cdf <= r) {
00369         N++ ;  
00370         term *= ( mu / N );
00371         cdf0 = cdf;
00372         cdf  += term;
00373         if (cdf == cdf0) break; // Can't happen, but just in case...
00374     }
00375     N1 = N;
00376                 // std::cout << r << "   " << N << "   ";
00377                 // DBG_small = true;
00378     rRange = 0;         // In this case there is always a second r needed
00379 
00380   } // end of small-r case
00381 
00382 
00383   // >>> 5 <<< 
00384   //    Assuming r lies within the scope of the row for this mu, find the 
00385   //    largest entry not greater than r.  N1 is the N corresponding to the 
00386   //    index a.
00387 
00388   else if ( r < cdfs[ENTRIES-1] ) {             // r is also >= cdfs[0]
00389 
00390     //
00391     // **** This is the normal code path ****
00392     //
00393 
00394     int a = 0;                  // Highest value of index such that cdfs[a]
00395                                 // is known NOT to be greater than r.
00396     int b = ENTRIES - 1;        // Lowest value of index such that cdfs[b] is
00397                                 // known to exeed r.
00398 
00399     while (b != (a+1) ) {
00400       int c = (a+b+1)>>1;
00401       if (r > cdfs[c]) {
00402         a = c;
00403       } else {
00404         b = c;
00405       }
00406     }
00407 
00408     N1 = Nmin + a;
00409     rRange = cdfs[a+1] - cdfs[a];
00410     rRemainder = r - cdfs[a];
00411 
00412     //
00413     // **** ****
00414     //
00415 
00416   } // end of medium-r (normal) case
00417 
00418 
00419   // >>> 6 <<< 
00420   //    If r exceeds the greatest entry in the table for this mu, then start 
00421   //    from that cdf, and use the series to compute from there until r is 
00422   //    exceeded.  
00423 
00424   else { //               if ( r >= cdfs[ENTRIES-1] ) {
00425  
00426     // Here, division must be done explicitly, and we must also protect against
00427     // roundoff preventing termination.
00428 
00429         // 
00430         //+++ cdfs[ENTRIES-1] is exp(-mu) sum (mu**m/m! , m=0 to Nmax) 
00431         //+++ (where Nmax = mu - BELOW + ENTRIES - 1)
00432         //+++ cdfs[ENTRIES-1]-cdfs[ENTRIES-2] is exp(-mu) mu**(Nmax)/(Nmax)!
00433         //+++ If the sum up to k-1 <= r < sum up to k, then N = k-1
00434         //+++ Consider k = Nmax in the above statement:
00435         //+++ If cdfs[ENTRIES-2] <= r < cdfs[ENTRIES-1], N would be Nmax-1 
00436         //+++ But here r >= cdfs[ENTRIES-1] so N >= Nmax
00437         //
00438 
00439         // Erroneous:
00440         //+++ cdfs[ENTRIES-1] is exp(-mu) sum (mu**m/m! , m=0 to Nmax-1) 
00441         //+++ cdfs[ENTRIES-1]-cdfs[ENTRIES-2] is exp(-mu) mu**(Nmax-1)/(Nmax-1)!
00442         //+++ If a sum up to k-1 <= r < sum up to k, then N = k-1
00443         //+++ So if cdfs[ENTRIES-1] were > r, N would be Nmax-1 (or less)
00444         //+++ But here r >= cdfs[ENTRIES-1] so N >= Nmax
00445         //
00446 
00447                 //      std::cout << "r = " << r << " mu = " << mu << "\n";
00448     long N = Nmax -1;
00449     double cdf = cdfs[ENTRIES-1];
00450     double term = cdf - cdfs[ENTRIES-2];
00451     double cdf0;
00452     while(cdf <= r) {
00453         N++ ;  
00454                 //      std::cout << "  N " << N << " term " << 
00455                 //      term << " cdf " << cdf << "\n";
00456         term *= ( mu / N );
00457         cdf0  = cdf;
00458         cdf  += term;
00459         if (cdf == cdf0) break; // If term gets so small cdf stops increasing,
00460                                 // terminate using that value of N since we
00461                                 // would never reach r.
00462     }
00463     N1 = N;
00464     rRange = 0;         // We can't validly omit the second true random
00465 
00466         //          N = Nmax -1;
00467         //          cdf = cdfs[ENTRIES-1];
00468         //          term = cdf - cdfs[ENTRIES-2];
00469         //          for (int isxz=0; isxz < 100; isxz++) {
00470         //              N++ ;  
00471         //              term *= ( mu / N );
00472         //              cdf0  = cdf;
00473         //              cdf  += term;
00474         //          }
00475         //          std::cout.precision(20);
00476         //          std::cout << "Final sum is " << cdf << "\n";
00477 
00478   } // end of large-r case
00479 
00480 
00481 
00482   // >>> 7 <<< 
00483   //    Form a second random, s, based on the position of r within the range
00484   //    of this table entry to the next entry.  
00485 
00486   // However, if this range is very small, then we lose too many bits of
00487   // randomness.  In that situation, we generate a second random for s.
00488 
00489   double s;
00490 
00491   static const double MINRANGE = .01;   // Sacrifice up to two digits of 
00492                                         // randomness when using r to produce
00493                                         // a second random s.  Leads to up to
00494                                         // .09 extra randoms each time.
00495 
00496   if ( rRange > MINRANGE ) {
00497     //
00498     // **** This path taken 90% of the time ****
00499     //
00500     s = rRemainder / rRange;
00501   } else {
00502     s = e->flat();      // extra true random needed about one time in 10.
00503   }
00504 
00505   // >>> 8 <<< 
00506   //    Use the direct summation method to form a second poisson deviate N2 
00507   //    from deltaMu and s.
00508 
00509   N2 = 0;
00510   double term = std::exp(-deltaMu);
00511   double cdf = term;
00512 
00513   if ( s < (1 - 1.0E-10) ) {
00514       //
00515       // This is the normal path:
00516       //
00517       const double* oneOverNptr = oneOverN;
00518       while( cdf <= s ) {
00519         N2++ ;  
00520         oneOverNptr++;
00521         term *= ( deltaMu * (*oneOverNptr) );
00522         cdf  += term;
00523       }
00524   } else { // s is almost 1...
00525       while( cdf <= s ) {
00526         N2++ ;  
00527         term *= ( deltaMu / N2 );
00528         cdf  += term;
00529       }
00530   } // end of if ( s compared to (1 - 1.0E-10) )
00531 
00532   // >>> 9 <<< 
00533   //    The result is the sum of those two deviates
00534 
00535                 // if (DBG_small) {
00536                 //   std::cout << N2 << "   " << N1+N2 << "\n";
00537                 //   DBG_small = false;
00538                 // }
00539 
00540   return N1 + N2;
00541 
00542 } // poissonDeviate()
00543 
00544 std::ostream & RandPoissonQ::put ( std::ostream & os ) const {
00545   int pr=os.precision(20);
00546   std::vector<unsigned long> t(2);
00547   os << " " << name() << "\n";
00548   os << "Uvec" << "\n";
00549   t = DoubConv::dto2longs(a0);
00550   os << a0 << " " << t[0] << " " << t[1] << "\n";
00551   t = DoubConv::dto2longs(a1);
00552   os << a1 << " " << t[0] << " " << t[1] << "\n";
00553   t = DoubConv::dto2longs(a2);
00554   os << a2 << " " << t[0] << " " << t[1] << "\n";
00555   t = DoubConv::dto2longs(sigma);
00556   os << sigma << " " << t[0] << " " << t[1] << "\n";
00557   RandPoisson::put(os);
00558   os.precision(pr);
00559   return os;
00560 #ifdef REMOVED
00561   int pr=os.precision(20);
00562   os << " " << name() << "\n";
00563   os << a0 << " " << a1 << " " << a2 << "\n";
00564   os << sigma << "\n";
00565   RandPoisson::put(os);
00566   os.precision(pr);
00567   return os;
00568 #endif
00569 }
00570 
00571 std::istream & RandPoissonQ::get ( std::istream & is ) {
00572   std::string inName;
00573   is >> inName;
00574   if (inName != name()) {
00575     is.clear(std::ios::badbit | is.rdstate());
00576     std::cerr << "Mismatch when expecting to read state of a "
00577               << name() << " distribution\n"
00578               << "Name found was " << inName
00579               << "\nistream is left in the badbit state\n";
00580     return is;
00581   }
00582   if (possibleKeywordInput(is, "Uvec", a0)) {
00583     std::vector<unsigned long> t(2);
00584     is >> a0 >> t[0] >> t[1]; a0 = DoubConv::longs2double(t); 
00585     is >> a1 >> t[0] >> t[1]; a1 = DoubConv::longs2double(t); 
00586     is >> a2 >> t[0] >> t[1]; a2 = DoubConv::longs2double(t); 
00587     is >> sigma >> t[0] >> t[1]; sigma = DoubConv::longs2double(t); 
00588     RandPoisson::get(is);
00589     return is;
00590   }
00591   // is >> a0 encompassed by possibleKeywordInput
00592   is >> a1 >> a2 >> sigma;
00593   RandPoisson::get(is);
00594   return is;
00595 }
00596 
00597 }  // namespace CLHEP
00598 

Generated on Mon May 27 17:50:33 2013 for Geant4 by  doxygen 1.4.7