|
|
|||
File indexing completed on 2026-08-06 09:38:31
0001 // -*- C++ -*- 0002 // 0003 // RandomGenerator.h is a part of ThePEG - Toolkit for HEP Event Generation 0004 // Copyright (C) 1999-2019 Leif Lonnblad 0005 // 0006 // ThePEG is licenced under version 3 of the GPL, see COPYING for details. 0007 // Please respect the MCnet academic guidelines, see GUIDELINES for details. 0008 // 0009 #ifndef ThePEG_RandomGenerator_H 0010 #define ThePEG_RandomGenerator_H 0011 // This is the declaration of the RandomGenerator class. 0012 0013 #include "ThePEG/Config/ThePEG.h" 0014 #include "ThePEG/Interface/Interfaced.h" 0015 #include "gsl/gsl_rng.h" 0016 0017 namespace ThePEG { 0018 0019 /** 0020 * RandomGenerator is an interface to the CLHEP::RandomEngine 0021 * classes. To avoid excessive virtual function calls, the 0022 * RandomGenerator caches random numbers generated by the engine which 0023 * are then retrieved by the non-virtual inlined rnd() method. 0024 * 0025 * Sub-classes of RandomGenerator should be used to 0026 * implement a particular random engine. 0027 * 0028 * RandomGenerator only provides a flat distribution between 0 and 0029 * 1. Any other distribution can be achieved using the CLHEP random 0030 * classes using the engine returned from the randomGenerator() 0031 * method. 0032 * 0033 * @see \ref RandomGeneratorInterfaces "The interfaces" 0034 * defined for RandomGenerator. 0035 * @see UseRandom 0036 */ 0037 class RandomGenerator: public Interfaced { 0038 0039 public: 0040 0041 /** A vector of doubles. */ 0042 typedef vector<double> RndVector; 0043 0044 /** The size_type of RndVector. */ 0045 typedef RndVector::size_type size_type; 0046 0047 public: 0048 0049 /** @name Standard constructors and destructors. */ 0050 //@{ 0051 /** 0052 * Default constructor. 0053 */ 0054 RandomGenerator(); 0055 0056 /** 0057 * Copy-constructor. 0058 */ 0059 RandomGenerator(const RandomGenerator &); 0060 0061 /** 0062 * Destructor. 0063 */ 0064 virtual ~RandomGenerator(); 0065 //@} 0066 0067 /** 0068 * Reset the underlying random engine with the given \a seed. If the 0069 * \a seed is set to -1 a standard seed will be used. 0070 */ 0071 virtual void setSeed(long seed) = 0; 0072 0073 /** @name Functions to return random numbers. */ 0074 //@{ 0075 /** 0076 * Return a (possibly cached) flat random number in the interval 0077 * \f$]0,1[\f$. 0078 */ 0079 double rnd() { 0080 if ( nextNumber == theNumbers.end() ) fill(); 0081 return *nextNumber++; 0082 } 0083 0084 /** 0085 * Return a flat random number in the interval 0086 * \f$]0,b[\f$. 0087 */ 0088 template <typename Unit> Unit rnd(Unit b) { return b*rnd(); } 0089 0090 /** 0091 * Return a flat random number in the interval 0092 * \f$]a,b[\f$. 0093 */ 0094 template <typename Unit> 0095 Unit rnd(Unit a, Unit b) { return a + rnd(b - a); } 0096 0097 /** 0098 * Return \a n flat random number in the interval 0099 * \f$]0,1[\f$. 0100 */ 0101 RndVector rndvec(int n) { 0102 RndVector ret(n); 0103 for ( int i = 0; i < n; ++i ) ret[i] = rnd(); 0104 return ret; 0105 } 0106 0107 /** 0108 * Return a (possibly cached) flat random number in the interval 0109 * \f$]0,1[\f$. 0110 */ 0111 double operator()() { return rnd(); } 0112 0113 /** 0114 * Return a (possibly cached) flat integer random number in the 0115 * interval \f$[0,N[\f$. 0116 * Function was introduced since otherwise operator()() is used if a double is given 0117 * resulting in a \f$]0,1[\f$ distribution. 0118 */ 0119 double operator()(double N) { return double(rnd() * N); } 0120 0121 /** 0122 * Return a (possibly cached) flat integer random number in the 0123 * interval \f$[0,N[\f$. 0124 */ 0125 long operator()(long N) { return long(rnd() * N); } 0126 0127 /** 0128 * Return a true with probability \a p. Uses rnd(). 0129 */ 0130 bool rndbool(double p = 0.5) { 0131 return rnd() < p; 0132 } 0133 0134 /** 0135 * Return a true with probability \a p. Uses rnd(). Also uses 0136 * push_back(double). 0137 */ 0138 bool prndbool(double p = 0.5); 0139 0140 /** 0141 * Return a true with probability \a p1/(\a p1+\a p2). Uses 0142 * rnd(). 0143 */ 0144 bool rndbool(double p1, double p2) { return rndbool(p1/(p1 + p2)); } 0145 0146 /** 0147 * Return a true with probability \a p1/(\a p1+\a p2). Uses 0148 * rnd(). Also uses push_back(double). 0149 */ 0150 bool prndbool(double p1, double p2) { return prndbool(p1/(p1 + p2)); } 0151 0152 /** 0153 * Return -1, 0, or 1 with relative probabilities \a p1, \a p2, \a 0154 * p3. Uses rnd(). 0155 */ 0156 int rndsign(double p1, double p2, double p3); 0157 0158 /** 0159 * Return -1, 0, or 1 with relative probabilities \a p1, \a p2, \a 0160 * p3. Uses rnd(). Also uses push_back(double). 0161 */ 0162 int prndsign(double p1, double p2, double p3); 0163 0164 /** 0165 * Return an integer \f$i\f$ with probability p\f$i\f$/(\a p0+\a 0166 * p1). Uses rnd(). 0167 */ 0168 int rnd2(double p0, double p1) { 0169 return rndbool(p0, p1)? 0: 1; 0170 } 0171 0172 /** 0173 * Return an integer \f$i\f$ with probability p\f$i\f$/(\a p0+\a 0174 * p1+\a p2). Uses rnd(). 0175 */ 0176 int rnd3(double p0, double p1, double p2) { 0177 return 1 + rndsign(p0, p1, p2); 0178 } 0179 0180 /** 0181 * Return an integer/ \f$i\f$ with probability p\f$i\f$(\a p0+\a 0182 * p1+\a p2+\a p3). Uses rnd(). 0183 */ 0184 int rnd4(double p0, double p1, double p2, double p3); 0185 0186 /** 0187 * Return an integer/ \f$i\f$ with probability p\f$i\f$(\a p0+\a 0188 * p1+\a p2+\a p3+\a p4). Uses rnd(). 0189 */ 0190 int rnd5(double p0, double p1, double p2, double p3, double p4); 0191 0192 /** 0193 * Return a number between zero and infinity, distributed according 0194 * to \f$e^-x\f$. 0195 */ 0196 double rndExp() { 0197 return -log(rnd()); 0198 } 0199 0200 /** 0201 * Return a number between zero and infinity, distributed according 0202 * to \f$e^-{x/\mu}\f$ where \f$\mu\f$ is the \a mean value. 0203 */ 0204 template <typename Unit> 0205 Unit rndExp(Unit mean) { return mean*rndExp(); } 0206 0207 /** 0208 * Return two numbers distributed according to a Gaussian distribution 0209 * with zero mean and unit variance. 0210 * 0211 * @param[out] First random number 0212 * @param[out] Second random number 0213 */ 0214 void rndGaussTwoNumbers(double & randomNumberOne, double & randomNumberTwo) { 0215 double r = sqrt(-2.0*log(rnd())); 0216 double phi = rnd()*2.0*Constants::pi; 0217 randomNumberOne = r*sin(phi); 0218 randomNumberTwo = r*cos(phi); 0219 } 0220 0221 /** 0222 * Return a number distributed according to a Gaussian distribution 0223 * with zero mean and unit variance. 0224 * A second number is cached and returned the next time. 0225 * This function calls the rndGaussTwoNumbers function which returns two numbers at once. 0226 */ 0227 double rndGauss() { 0228 if ( gaussSaved ) { 0229 gaussSaved = false; 0230 return savedGauss; 0231 } 0232 double randomNumberOne, randomNumberTwo; 0233 rndGaussTwoNumbers(randomNumberOne, randomNumberTwo); 0234 savedGauss = randomNumberTwo; 0235 gaussSaved = true; 0236 return randomNumberOne; 0237 } 0238 0239 /** 0240 * Return a number distributed according to a Gaussian distribution 0241 * with a given standard deviation, \a sigma, and a given \a mean. 0242 */ 0243 template <typename Unit> 0244 Unit rndGauss(Unit sigma, Unit mean = Unit()) { 0245 return mean + sigma*rndGauss(); 0246 } 0247 0248 /** 0249 * Return two numbers distributed according to a Gaussian distribution 0250 * with a given standard deviation, \a sigma, and a given \a mean. 0251 */ 0252 template <typename Unit> 0253 void rndGaussTwoNumbers(Unit & randomNumberOne, Unit & randomNumberTwo, Unit sigma, Unit mean = Unit()) { 0254 double r1,r2; 0255 rndGaussTwoNumbers(r1,r2); 0256 randomNumberOne = mean + sigma * r1; 0257 randomNumberTwo = mean + sigma * r2; 0258 } 0259 0260 /** 0261 * Return a positive number distributed according to a 0262 * non-relativistic Breit-Wigner with a given width, \a gamma, and a 0263 * given \a mean. 0264 */ 0265 template <typename Unit> 0266 Unit rndBW(Unit mean, Unit gamma) { 0267 if ( gamma <= Unit() ) return mean; 0268 return mean + 0.5*gamma*tan(rnd(atan(-2.0*mean/gamma), Constants::pi/2)); 0269 } 0270 0271 /** 0272 * Return a positive number distributed according to a 0273 * non-relativistic Breit-Wigner with a given width, \a gamma, and a 0274 * given \a mean. The distribution is cut-off so that the number is 0275 * between \a mean - \a cut and \a mean + \a cut 0276 */ 0277 template <typename Unit> 0278 Unit rndBW(Unit mean, Unit gamma, Unit cut) { 0279 if ( gamma <= Unit() || cut <= Unit() ) return mean; 0280 return mean + 0.5*gamma*tan(rnd(atan(-2.0*min(mean,cut)/gamma), 0281 atan(2.0*cut/gamma))); 0282 } 0283 0284 /** 0285 * Return a positive number distributed according to a relativistic 0286 * Breit-Wigner with a given width, \a gamma, and a given \a mean. 0287 */ 0288 template <typename Unit> 0289 Unit rndRelBW(Unit mean, Unit gamma) { 0290 if ( gamma <= Unit() ) return mean; 0291 return sqrt(sqr(mean) + mean*gamma*tan(rnd(atan(-mean/gamma), 0292 Constants::pi/2))); 0293 } 0294 0295 /** 0296 * Return a positive number distributed according to a relativistic 0297 * Breit-Wigner with a given width, \a gamma, and a given \a 0298 * mean. The distribution is cut-off so that the number is between 0299 * \a mean - \a cut and \a mean + \a cut 0300 */ 0301 template <typename Unit> 0302 Unit rndRelBW(Unit mean, Unit gamma, Unit cut) { 0303 if ( gamma <= Unit() || cut <= Unit() ) return mean; 0304 double minarg = cut > mean? -mean/gamma: 0305 (sqr(mean - cut) - sqr(mean))/(gamma*mean); 0306 double maxarg = (sqr(mean + cut) - sqr(mean))/(mean*gamma); 0307 return sqrt(sqr(mean) + mean*gamma*tan(rnd(atan(minarg), atan(maxarg)))); 0308 } 0309 0310 /** 0311 * Return a non-negative number generated according to a Poissonian 0312 * distribution with a given \a mean. Warning: the method 0313 * implemented is very slow for large mean and large return 0314 * values. For this reason the maximum return value is given by \a 0315 * nmax. 0316 */ 0317 long rndPoisson(double mean); 0318 //@} 0319 0320 /** @name Access the cached random numbers from the underlying engine. */ 0321 //@{ 0322 /** 0323 * Give back a partly unused random number. This is typically used 0324 * when generating integral random numbers. In eg. rndbool(double p) 0325 * a random number <code>r</code> is drawn and if it is less than 0326 * <code>p</code> true is returned, but <code>r</code> is still a 0327 * good random number in the interval <code>]0,p[</code>. Hence 0328 * <code>r/p</code> is still a good random number in the interval 0329 * <code>]0,1[</code> and this is then pushed back into the cache 0330 * and is used by the next call to rnd(). Note that the resulting 0331 * random number is of lesser quality, and successive calls to 0332 * push_back() should be avoided. To ensure a highest quality random 0333 * number random number in the next call to rnd(), pop_back() should 0334 * be used. 0335 */ 0336 void push_back(double r) { 0337 if ( r > 0.0 && r < 1.0 && nextNumber != theNumbers.begin() ) 0338 *--nextNumber = r; 0339 } 0340 0341 /** 0342 * Discard the next random number in the cache. 0343 */ 0344 void pop_back() { 0345 if ( nextNumber != theNumbers.end() ) ++nextNumber; 0346 } 0347 0348 /** 0349 * Discard all random numbers in the cache. Typically used after the 0350 * internal random engine has been reinitialized for some reason. 0351 */ 0352 void flush() { 0353 nextNumber = theNumbers.end(); 0354 gaussSaved = false; 0355 } 0356 0357 /** 0358 * Generate n random numbers between 0 and 1 and put them in the 0359 * output iterator. 0360 */ 0361 template <typename OutputIterator> 0362 void rnd(OutputIterator o, size_type n) { 0363 while ( n-- ) *o++ = rnd(); 0364 } 0365 //@} 0366 0367 protected: 0368 0369 /** 0370 * Initializes this random generator. This should be done first of 0371 * all before the initialization of any other object associated with 0372 * an event generator. 0373 */ 0374 virtual void doinit(); 0375 0376 public: 0377 0378 0379 /** @name Functions used by the persistent I/O system. */ 0380 //@{ 0381 /** 0382 * Function used to write out object persistently. 0383 * @param os the persistent output stream written to. 0384 */ 0385 void persistentOutput(PersistentOStream & os) const; 0386 0387 /** 0388 * Function used to read in object persistently. 0389 * @param is the persistent input stream read from. 0390 * @param version the version number of the object when written. 0391 */ 0392 void persistentInput(PersistentIStream & is, int version); 0393 //@} 0394 0395 /** 0396 * Standard Init function used to initialize the interface. 0397 */ 0398 static void Init(); 0399 0400 /** 0401 * Return a gsl_rng interface to this random generator. 0402 */ 0403 gsl_rng * getGslInterface() { return gsl; } 0404 0405 protected: 0406 0407 /** 0408 * Utility function for the interface. 0409 */ 0410 void setSize(size_type newSize); 0411 0412 /** 0413 * Fill the cache with random numbers. 0414 */ 0415 virtual void fill() = 0; 0416 0417 /** 0418 * A vector of cached numbers. 0419 */ 0420 RndVector theNumbers; 0421 0422 /** 0423 * Iterator pointing to the next number to be extracted 0424 */ 0425 RndVector::iterator nextNumber; 0426 0427 /** 0428 * The size of the cache. 0429 */ 0430 size_type theSize; 0431 0432 /** 0433 * The seed to initialize the random generator with. 0434 */ 0435 long theSeed; 0436 0437 /** 0438 * A saved Gaussian random number. 0439 */ 0440 mutable double savedGauss; 0441 0442 /** 0443 * Indicate the precense of a saved Gaussian random number. 0444 */ 0445 mutable bool gaussSaved; 0446 0447 /** 0448 * A pinter to a gsl_rng interface to this generator. 0449 */ 0450 gsl_rng * gsl; 0451 0452 private: 0453 0454 /** 0455 * Describe a concrete class with persistent data. Note that the 0456 * class should in principle be abstract. 0457 */ 0458 static ClassDescription<RandomGenerator> initRandomGenerator; 0459 0460 /** 0461 * Private and non-existent assignment operator. 0462 */ 0463 RandomGenerator & operator=(const RandomGenerator &) = delete; 0464 0465 }; 0466 0467 /** @cond TRAITSPECIALIZATIONS */ 0468 0469 /** This template specialization informs ThePEG about the base classes 0470 * of RandomGenerator. */ 0471 template <> 0472 struct BaseClassTrait<RandomGenerator,1>: public ClassTraitsType { 0473 /** Typedef of the first base class of RandomGenerator. */ 0474 typedef Interfaced NthBase; 0475 }; 0476 0477 /** This template specialization informs ThePEG about the name of the 0478 * RandomGenerator class. */ 0479 template <> 0480 struct ClassTraits<RandomGenerator>: 0481 public ClassTraitsBase<RandomGenerator> { 0482 /** Return a platform-independent class name */ 0483 static string className() { return "ThePEG::RandomGenerator"; 0484 } 0485 /** This class should in principle be abstract, therefore the 0486 create() method will throw a std::logic_error if called. */ 0487 static TPtr create() { 0488 throw std::logic_error("Tried to instantiate abstract class" 0489 "'Pythis7::RandomGenerator'"); 0490 } 0491 }; 0492 0493 /** @endcond */ 0494 0495 } 0496 0497 #endif /* ThePEG_RandomGenerator_H */
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|