00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "RandPoisson.h"
00034
00035 RandPoisson::~RandPoisson() {
00036 if ( deleteEngine ) delete localEngine;
00037 }
00038
00039 HepDouble RandPoisson::operator()() {
00040 return HepDouble(fire());
00041 }
00042
00043 HepDouble gammln(HepDouble xx) {
00044
00045
00046
00047
00048
00049 static HepDouble cof[6] = {76.18009172947146,-86.50532032941677,
00050 24.01409824083091, -1.231739572450155,
00051 0.1208650973866179e-2, -0.5395239384953e-5};
00052 register HepInt j;
00053 HepDouble x = xx - 1.0;
00054 HepDouble tmp = x + 5.5;
00055 tmp -= (x + 0.5) * ::log(tmp);
00056 HepDouble ser = 1.000000000190015;
00057
00058 for ( j = 0; j <= 5; j++ ) {
00059 x += 1.0;
00060 ser += cof[j]/x;
00061 }
00062 return -tmp + ::log(2.5066282746310005*ser);
00063 }
00064
00065 long RandPoisson::shoot(HepDouble xm) {
00066
00067
00068
00069
00070
00071
00072 register HepDouble em;
00073 HepDouble t, y;
00074 HepDouble sq, alxm, g;
00075 HepDouble om = getOldMean();
00076
00077 HepDouble* status = getPStatus();
00078 sq = status[0];
00079 alxm = status[1];
00080 g = status[2];
00081
00082 if( xm == -1 ) return 0;
00083 if( xm < 12.0 ) {
00084 if( xm != om ) {
00085 setOldMean(xm);
00086 g = exp(-xm);
00087 }
00088 em = -1;
00089 t = 1.0;
00090 do {
00091 em += 1.0;
00092 t *= HepRandom::getTheGenerator()->flat();
00093 } while( t > g );
00094 }
00095 else if ( xm < getMaxMean() ) {
00096 if ( xm != om ) {
00097 setOldMean(xm);
00098 sq = ::sqrt(2.0*xm);
00099 alxm = ::log(xm);
00100 g = xm*alxm - gammln(xm + 1.0);
00101 }
00102 do {
00103 do {
00104 y = tan(M_PI*HepRandom::getTheGenerator()->flat());
00105 em = sq*y + xm;
00106 } while( em < 0.0 );
00107 em = floor(em);
00108 t = 0.9*(1.0 + y*y)* exp(em*alxm - gammln(em + 1.0) - g);
00109 } while( HepRandom::getTheGenerator()->flat() > t );
00110 }
00111 else {
00112 if ( xm != om ) {
00113 setOldMean(xm);
00114 sq = ::sqrt(2.0*xm);
00115 alxm = ::log(xm);
00116 g = xm*alxm - gammln(xm + 1.0);
00117 }
00118 em = xm;
00119 }
00120 setPStatus(sq,alxm,g);
00121 return long(em);
00122 }
00123
00124 void RandPoisson::shootArray(const HepInt size, long* vect, HepDouble m)
00125 {
00126 for (int i=0; i<size; ++i)
00127 vect[i] = shoot(m);
00128 }
00129
00130 void
00131 #ifndef ST_NO_TEMPLATE_DEF_ARGS
00132 RandPoisson::shootArray(vector<long>& vec, HepDouble m)
00133 #else
00134 RandPoisson::shootArray(vector<long,allocator<long> >& vec, HepDouble m)
00135 #endif
00136 {
00137 for (unsigned int i=0; i<vec.size(); ++i)
00138 vec[i] = shoot(m);
00139 }
00140
00141 long RandPoisson::shoot(HepRandomEngine* anEngine, HepDouble xm) {
00142
00143
00144
00145
00146
00147
00148 register HepDouble em;
00149 HepDouble t, y;
00150 HepDouble sq, alxm, g;
00151 HepDouble om = getOldMean();
00152
00153 HepDouble* status = getPStatus();
00154 sq = status[0];
00155 alxm = status[1];
00156 g = status[2];
00157
00158 if( xm == -1 ) return 0;
00159 if( xm < 12.0 ) {
00160 if( xm != om ) {
00161 setOldMean(xm);
00162 g = exp(-xm);
00163 }
00164 em = -1;
00165 t = 1.0;
00166 do {
00167 em += 1.0;
00168 t *= anEngine->flat();
00169 } while( t > g );
00170 }
00171 else if ( xm < getMaxMean() ) {
00172 if ( xm != om ) {
00173 setOldMean(xm);
00174 sq = ::sqrt(2.0*xm);
00175 alxm = ::log(xm);
00176 g = xm*alxm - gammln(xm + 1.0);
00177 }
00178 do {
00179 do {
00180 y = tan(M_PI*anEngine->flat());
00181 em = sq*y + xm;
00182 } while( em < 0.0 );
00183 em = floor(em);
00184 t = 0.9*(1.0 + y*y)* exp(em*alxm - gammln(em + 1.0) - g);
00185 } while( anEngine->flat() > t );
00186 }
00187 else {
00188 if ( xm != om ) {
00189 setOldMean(xm);
00190 sq = ::sqrt(2.0*xm);
00191 alxm = ::log(xm);
00192 g = xm*alxm - gammln(xm + 1.0);
00193 }
00194 em = xm;
00195 }
00196 setPStatus(sq,alxm,g);
00197 return long(em);
00198 }
00199
00200 void RandPoisson::shootArray(HepRandomEngine* anEngine, const HepInt size,
00201 long* vect, HepDouble m)
00202 {
00203 register HepInt i;
00204
00205 for (i=0; i<size; ++i)
00206 vect[i] = shoot(anEngine,m);
00207 }
00208 void
00209 #ifndef ST_NO_TEMPLATE_DEF_ARGS
00210 RandPoisson::shootArray(HepRandomEngine* anEngine,
00211 vector<long>& vec, HepDouble m)
00212 #else
00213 RandPoisson::shootArray(HepRandomEngine* anEngine,
00214 vector<long,allocator<long> >& vec, HepDouble m)
00215 #endif
00216 {
00217 for (unsigned int i=0; i<vec.size(); ++i)
00218 vec[i] = shoot(anEngine,m);
00219 }
00220 long RandPoisson::fire(HepDouble xm) {
00221
00222
00223
00224
00225
00226
00227 register HepDouble em;
00228 HepDouble t, y;
00229 HepDouble sq, alxm, g;
00230
00231 sq = status[0];
00232 alxm = status[1];
00233 g = status[2];
00234
00235 if( xm == -1 ) return 0;
00236 if( xm < 12.0 ) {
00237 if( xm != oldm ) {
00238 oldm = xm;
00239 g = exp(-xm);
00240 }
00241 em = -1;
00242 t = 1.0;
00243 do {
00244 em += 1.0;
00245 t *= localEngine->flat();
00246 } while( t > g );
00247 }
00248 else if ( xm < meanMax ) {
00249 if ( xm != oldm ) {
00250 oldm = xm;
00251 sq = ::sqrt(2.0*xm);
00252 alxm = ::log(xm);
00253 g = xm*alxm - gammln(xm + 1.0);
00254 }
00255 do {
00256 do {
00257 y = tan(M_PI*localEngine->flat());
00258 em = sq*y + xm;
00259 } while( em < 0.0 );
00260 em = floor(em);
00261 t = 0.9*(1.0 + y*y)* exp(em*alxm - gammln(em + 1.0) - g);
00262 } while( localEngine->flat() > t );
00263 }
00264 else {
00265 if ( xm != oldm ) {
00266 oldm = xm;
00267 sq = ::sqrt(2.0*xm);
00268 alxm = ::log(xm);
00269 g = xm*alxm - gammln(xm + 1.0);
00270 }
00271 em = xm;
00272 }
00273 status[0] = sq; status[1] = alxm; status[2] = g;
00274 return long(em);
00275 }
00276
00277 void RandPoisson::fireArray(const HepInt size, long* vect, HepDouble m)
00278 {
00279 register HepInt i;
00280
00281 for (i=0; i<size; ++i)
00282 vect[i] = fire(m);
00283 }
00284
00285 void
00286 #ifndef ST_NO_TEMPLATE_DEF_ARGS
00287 RandPoisson::fireArray(vector<long>& vec, HepDouble m)
00288 #else
00289 RandPoisson::fireArray(vector<long,allocator<long> >& vec, HepDouble m)
00290 #endif
00291 {
00292 for (unsigned int i=0; i<vec.size(); ++i)
00293 vec[i] = fire(m);
00294 }