40#include "CLHEP/Random/defs.h"
41#include "CLHEP/Random/RandPoissonQ.h"
42#include "CLHEP/Random/RandGaussQ.h"
43#include "CLHEP/Random/DoubConv.h"
44#include "CLHEP/Random/Stat.h"
45#include "CLHEP/Utility/thread_local.h"
62const double RandPoissonQ::FIRST_MU = 10;
63const double RandPoissonQ::LAST_MU = 95;
64const double RandPoissonQ::S = 5;
65const int RandPoissonQ::BELOW = 30;
66const int RandPoissonQ::ENTRIES = 51;
76static const double poissonTables [ 51 * ( (95-10)/5 + 1 ) ] = {
77#include "poissonTables.cdat"
87void RandPoissonQ::setupForDefaultMu() {
92 sigma = std::sqrt(sig2);
102 a1 = std::sqrt (1-2*a2*a2*sig2);
126 return (
double)
fire();
130 return (
double)
fire(mean);
141 return poissonDeviateQuick (
getLocalEngine(), a0, a1, a2, sigma );
151 static CLHEP_THREAD_LOCAL
double lastLargeMean = -1.;
153 static CLHEP_THREAD_LOCAL
double lastA0;
154 static CLHEP_THREAD_LOCAL
double lastA1;
155 static CLHEP_THREAD_LOCAL
double lastA2;
156 static CLHEP_THREAD_LOCAL
double lastSigma;
158 if ( mean < LAST_MU + S ) {
159 return poissonDeviateSmall ( anEngine, mean );
161 if ( mean != lastLargeMean ) {
164 double sig2 = mean * (.9998654 - .08346/mean);
165 lastSigma = std::sqrt(sig2);
167 lastA2 = t*(1./6.) + t*t*(1./324.);
168 lastA1 = std::sqrt (1-2*lastA2*lastA2*sig2);
169 lastA0 = mean + .5 - sig2 * lastA2;
171 return poissonDeviateQuick ( anEngine, lastA0, lastA1, lastA2, lastSigma );
177 for(
long* v = vect; v != vect + size; ++v )
185 for(
long* v = vect; v != vect + size; ++v )
190 for(
long* v = vect; v != vect + size; ++v )
197long RandPoissonQ::poissonDeviateQuick (
HepRandomEngine *e,
double mu ) {
202 double sig2 = mu * (.9998654 - .08346/mu);
203 double sig = std::sqrt(sig2);
209 double sa2 = t*(1./6.) + t*t*(1./324.);
210 double sa1 = std::sqrt (1-2*sa2*sa2*sig2);
211 double sa0 = mu + .5 - sig2 * sa2;
217 return poissonDeviateQuick ( e, sa0, sa1, sa2, sig );
221long RandPoissonQ::poissonDeviateQuick ( HepRandomEngine *e,
222 double A0,
double A1,
double A2,
double sig) {
247 double p = A2*
g*
g + A1*
g + A0;
248 if ( p < 0 )
return 0;
259long RandPoissonQ::poissonDeviateSmall (HepRandomEngine * e,
double mean) {
265 double rRemainder = 0;
270 if ( mean > LAST_MU + S ) {
281 double r = e->flat();
290 static const double oneOverN[50] =
291 { 0, 1., 1/2., 1/3., 1/4., 1/5., 1/6., 1/7., 1/8., 1/9.,
292 1/10., 1/11., 1/12., 1/13., 1/14., 1/15., 1/16., 1/17., 1/18., 1/19.,
293 1/20., 1/21., 1/22., 1/23., 1/24., 1/25., 1/26., 1/27., 1/28., 1/29.,
294 1/30., 1/31., 1/32., 1/33., 1/34., 1/35., 1/36., 1/37., 1/38., 1/39.,
295 1/40., 1/41., 1/42., 1/43., 1/44., 1/45., 1/46., 1/47., 1/48., 1/49. };
298 if ( mean < FIRST_MU ) {
301 double term = std::exp(-mean);
304 if ( r < (1 - 1.0E-9) ) {
310 const double* oneOverNptr = oneOverN;
314 term *= ( mean * (*oneOverNptr) );
329 term *= ( mean / N );
332 if (cdf == cdf0)
break;
343 int rowNumber = int((mean - FIRST_MU)/S);
344 const double * cdfs = &poissonTables [rowNumber*ENTRIES];
345 double mu = FIRST_MU + rowNumber*S;
346 double deltaMu = mean - mu;
347 int Nmin = int(mu - BELOW);
348 if (Nmin < 1) Nmin = 1;
349 int Nmax = Nmin + (ENTRIES - 1);
369 double term = std::exp(-mu);
378 if (cdf == cdf0)
break;
393 else if ( r < cdfs[ENTRIES-1] ) {
404 while (b != (a+1) ) {
414 rRange = cdfs[a+1] - cdfs[a];
415 rRemainder = r - cdfs[a];
454 double cdf = cdfs[ENTRIES-1];
455 double term = cdf - cdfs[ENTRIES-2];
464 if (cdf == cdf0)
break;
496 static const double MINRANGE = .01;
501 if ( rRange > MINRANGE ) {
505 s = rRemainder / rRange;
515 double term = std::exp(-deltaMu);
518 if ( s < (1 - 1.0E-10) ) {
522 const double* oneOverNptr = oneOverN;
526 term *= ( deltaMu * (*oneOverNptr) );
532 term *= ( deltaMu / N2 );
550 long pr=os.precision(20);
551 std::vector<unsigned long> t(2);
552 os <<
" " <<
name() <<
"\n";
553 os <<
"Uvec" <<
"\n";
555 os << a0 <<
" " << t[0] <<
" " << t[1] <<
"\n";
557 os << a1 <<
" " << t[0] <<
" " << t[1] <<
"\n";
559 os << a2 <<
" " << t[0] <<
" " << t[1] <<
"\n";
561 os << sigma <<
" " << t[0] <<
" " << t[1] <<
"\n";
566 int pr=os.precision(20);
567 os <<
" " <<
name() <<
"\n";
568 os << a0 <<
" " << a1 <<
" " << a2 <<
"\n";
579 if (inName !=
name()) {
580 is.clear(std::ios::badbit | is.rdstate());
581 std::cerr <<
"Mismatch when expecting to read state of a "
582 <<
name() <<
" distribution\n"
583 <<
"Name found was " << inName
584 <<
"\nistream is left in the badbit state\n";
588 std::vector<unsigned long> t(2);
597 is >> a1 >> a2 >> sigma;
static double longs2double(const std::vector< unsigned long > &v)
static std::vector< unsigned long > dto2longs(double d)
static HepRandomEngine * getTheEngine()
static void shootArray(const int size, long *vect, double mean=1.0)
std::ostream & put(std::ostream &os) const
void fireArray(const int size, long *vect)
std::istream & get(std::istream &is)
HepRandomEngine & engine()
static const double MAXIMUM_POISSON_DEVIATE
static long shoot(double mean=1.0)
std::ostream & put(std::ostream &os) const
HepRandomEngine * getLocalEngine()
static long shoot(double mean=1.0)
std::istream & get(std::istream &is)
HepRandomEngine & engine()
bool possibleKeywordInput(IS &is, const std::string &key, T &t)