40 #include "CLHEP/Random/RandPoissonQ.h" 
   41 #include "CLHEP/Random/RandGaussQ.h" 
   42 #include "CLHEP/Random/DoubConv.h" 
   43 #include "CLHEP/Random/Stat.h" 
   44 #include "CLHEP/Utility/thread_local.h" 
   58 const double RandPoissonQ::FIRST_MU = 10;
 
   59 const double RandPoissonQ::LAST_MU =  95;
 
   60 const double RandPoissonQ::S = 5;        
 
   61 const int RandPoissonQ::BELOW = 30;      
 
   62 const int RandPoissonQ::ENTRIES = 51;    
 
   64 const double RandPoissonQ::MAXIMUM_POISSON_DEVIATE = 2.0E9;
 
   73 #include "CLHEP/Random/poissonTables.cdat" 
   80 RandPoissonQ::~RandPoissonQ() {
 
   83 void RandPoissonQ::setupForDefaultMu() {
 
   87   double sig2 = defaultMean * (.9998654 - .08346/defaultMean);
 
   88   sigma = std::sqrt(sig2);
 
   98   a1 = std::sqrt (1-2*
a2*
a2*sig2);
 
   99   a0 = defaultMean + .5 - sig2 * 
a2;
 
  118   return shoot(getTheEngine(), xm);
 
  121 double RandPoissonQ::operator()() {
 
  122   return (
double) fire();
 
  125 double RandPoissonQ::operator()( 
double mean ) {
 
  126   return (
double) fire(mean);
 
  129 long RandPoissonQ::fire(
double mean) {
 
  130   return shoot(getLocalEngine(), mean);
 
  133 long RandPoissonQ::fire() {
 
  134   if ( defaultMean < LAST_MU + S ) {
 
  135     return poissonDeviateSmall ( getLocalEngine(), defaultMean );
 
  137     return poissonDeviateQuick ( getLocalEngine(), 
a0, 
a1, 
a2, sigma );
 
  147   static CLHEP_THREAD_LOCAL 
double lastLargeMean = -1.; 
 
  149   static CLHEP_THREAD_LOCAL 
double lastA0;              
 
  150   static CLHEP_THREAD_LOCAL 
double lastA1;              
 
  151   static CLHEP_THREAD_LOCAL 
double lastA2;              
 
  152   static CLHEP_THREAD_LOCAL 
double lastSigma;           
 
  154   if ( mean < LAST_MU + S ) {
 
  155     return poissonDeviateSmall ( anEngine, mean );
 
  157     if ( mean != lastLargeMean ) {
 
  160       double sig2 = mean * (.9998654 - .08346/mean);
 
  161       lastSigma = std::sqrt(sig2);
 
  163       lastA2 = t*(1./6.) + t*t*(1./324.);
 
  164       lastA1 = std::sqrt (1-2*lastA2*lastA2*sig2);
 
  165       lastA0 = mean + .5 - sig2 * lastA2;
 
  167     return poissonDeviateQuick ( anEngine, lastA0, lastA1, lastA2, lastSigma );
 
  172 void RandPoissonQ::shootArray(
const int size, 
long* vect, 
double m) {
 
  173   for( 
long* v = vect; v != vect + size; ++v )
 
  180 void RandPoissonQ::fireArray(
const int size, 
long* vect, 
double m) {
 
  181   for( 
long* v = vect; v != vect + size; ++v )
 
  185 void RandPoissonQ::fireArray(
const int size, 
long* vect) {
 
  186   for( 
long* v = vect; v != vect + size; ++v )
 
  187     *v = fire( defaultMean );
 
  193 long RandPoissonQ::poissonDeviateQuick ( HepRandomEngine *e, 
double mu ) {
 
  198   double sig2 = mu * (.9998654 - .08346/mu);
 
  199   double sig = std::sqrt(sig2);
 
  205   double sa2 = t*(1./6.) + t*t*(1./324.);
 
  206   double sa1 = std::sqrt (1-2*sa2*sa2*sig2);
 
  207   double sa0 = mu + .5 - sig2 * sa2;
 
  213   return poissonDeviateQuick ( e, sa0, sa1, sa2, sig ); 
 
  217 long RandPoissonQ::poissonDeviateQuick ( HepRandomEngine *e, 
 
  218                 double A0, 
double A1, 
double A2, 
double sig) {
 
  243   double p = A2*g*g + A1*g + A0;
 
  244   if ( p < 0 ) 
return 0;        
 
  247   if ( p > MAXIMUM_POISSON_DEVIATE ) p = MAXIMUM_POISSON_DEVIATE;
 
  255 long RandPoissonQ::poissonDeviateSmall (HepRandomEngine * e, 
double mean) {
 
  261   double rRemainder = 0; 
 
  266   if ( mean > LAST_MU + S ) {
 
  277   double r = e->flat();
 
  286   static const double oneOverN[50] = 
 
  287   {    0,   1.,    1/2.,  1/3.,  1/4.,  1/5.,  1/6.,  1/7.,  1/8.,  1/9., 
 
  288    1/10.,  1/11.,  1/12., 1/13., 1/14., 1/15., 1/16., 1/17., 1/18., 1/19., 
 
  289    1/20.,  1/21.,  1/22., 1/23., 1/24., 1/25., 1/26., 1/27., 1/28., 1/29.,
 
  290    1/30.,  1/31.,  1/32., 1/33., 1/34., 1/35., 1/36., 1/37., 1/38., 1/39., 
 
  291    1/40.,  1/41.,  1/42., 1/43., 1/44., 1/45., 1/46., 1/47., 1/48., 1/49. };
 
  294   if ( mean < FIRST_MU ) {
 
  297     double term = std::exp(-mean);
 
  300     if ( r < (1 - 1.0E-9) ) {
 
  306       const double* oneOverNptr = oneOverN;
 
  310         term *= ( mean * (*oneOverNptr) );
 
  325         term *= ( mean / N );
 
  328         if (cdf == cdf0) 
break; 
 
  339   int rowNumber = int((mean - FIRST_MU)/S);
 
  341   double mu = FIRST_MU + rowNumber*S;
 
  342   double deltaMu = mean - mu;
 
  343   int Nmin = int(mu - BELOW);
 
  344   if (Nmin < 1) Nmin = 1;
 
  345   int Nmax = Nmin + (ENTRIES - 1);
 
  365     double term = std::exp(-mu);
 
  374         if (cdf == cdf0) 
break; 
 
  389   else if ( r < cdfs[ENTRIES-1] ) {             
 
  400     while (b != (a+1) ) {
 
  410     rRange = cdfs[a+1] - cdfs[
a];
 
  411     rRemainder = r - cdfs[
a];
 
  450     double cdf = cdfs[ENTRIES-1];
 
  451     double term = cdf - cdfs[ENTRIES-2];
 
  460         if (cdf == cdf0) 
break; 
 
  492   static const double MINRANGE = .01;   
 
  497   if ( rRange > MINRANGE ) {
 
  501     s = rRemainder / rRange;
 
  511   double term = std::exp(-deltaMu);
 
  514   if ( s < (1 - 1.0E-10) ) {
 
  518       const double* oneOverNptr = oneOverN;
 
  522         term *= ( deltaMu * (*oneOverNptr) );
 
  528         term *= ( deltaMu / N2 );
 
  545 std::ostream & RandPoissonQ::put ( std::ostream & os )
 const {
 
  546   int pr=os.precision(20);
 
  547   std::vector<unsigned long> t(2);
 
  548   os << 
" " << 
name() << 
"\n";
 
  549   os << 
"Uvec" << 
"\n";
 
  550   t = DoubConv::dto2longs(
a0);
 
  551   os << 
a0 << 
" " << t[0] << 
" " << t[1] << 
"\n";
 
  552   t = DoubConv::dto2longs(
a1);
 
  553   os << 
a1 << 
" " << t[0] << 
" " << t[1] << 
"\n";
 
  554   t = DoubConv::dto2longs(
a2);
 
  555   os << 
a2 << 
" " << t[0] << 
" " << t[1] << 
"\n";
 
  556   t = DoubConv::dto2longs(sigma);
 
  557   os << sigma << 
" " << t[0] << 
" " << t[1] << 
"\n";
 
  558   RandPoisson::put(os);
 
  562   int pr=os.precision(20);
 
  563   os << 
" " << 
name() << 
"\n";
 
  564   os << 
a0 << 
" " << 
a1 << 
" " << 
a2 << 
"\n";
 
  566   RandPoisson::put(os);
 
  572 std::istream & RandPoissonQ::get ( std::istream & is ) {
 
  575   if (inName != 
name()) {
 
  576     is.clear(std::ios::badbit | is.rdstate());
 
  577     std::cerr << 
"Mismatch when expecting to read state of a " 
  578               << 
name() << 
" distribution\n" 
  579               << 
"Name found was " << inName
 
  580               << 
"\nistream is left in the badbit state\n";
 
  583   if (possibleKeywordInput(is, 
"Uvec", 
a0)) {
 
  584     std::vector<unsigned long> t(2);
 
  585     is >> 
a0 >> t[0] >> t[1]; 
a0 = DoubConv::longs2double(t); 
 
  586     is >> 
a1 >> t[0] >> t[1]; 
a1 = DoubConv::longs2double(t); 
 
  587     is >> a2 >> t[0] >> t[1]; a2 = DoubConv::longs2double(t); 
 
  588     is >> sigma >> t[0] >> t[1]; sigma = DoubConv::longs2double(t); 
 
  589     RandPoisson::get(is);
 
  593   is >> 
a1 >> a2 >> sigma;
 
  594   RandPoisson::get(is);
 
ThreeVector shoot(const G4int Ap, const G4int Af)
 
static int engine(pchar, pchar, double &, pchar &, const dic_type &)
 
static const double poissonTables[51 *((95-10)/5+1)]