Back to home page

EIC code displayed by LXR

 
 

    


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 */