Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RandomFunctions.h
Go to the documentation of this file.
1 // @(#)root/mathcore:$Id$
2 // Authors: L. Moneta 8/2015
3 
4 /**********************************************************************
5  * *
6  * Copyright (c) 2015 , ROOT MathLib Team *
7  * *
8  * *
9  **********************************************************************/
10 
11 // Header file for random class
12 //
13 //
14 // Created by: Lorenzo Moneta : Tue 4 Aug 2015
15 //
16 //
17 #ifndef ROOT_Math_RandomFunctions
18 #define ROOT_Math_RandomFunctions
19 
20 
21 #include <type_traits>
22 #include <cmath>
23 #include "Rtypes.h"
24 #include "TMath.h"
25 #include <cassert>
26 
27 #include "TRandomEngine.h"
28 
29 
30 namespace ROOT {
31 namespace Math {
32 
33 
34 //___________________________________________________________________________________
35 
36 
37  // class DefaultEngineType {};
38 
39 
40  /**
41  Documentation for the RandomFunction class
42 
43  @ingroup Random
44  */
45 
46 
47  typedef TRandomEngine DefaultEngineType;
48  //class DefaultEngineType {}; // for generic types
49 
50 
51 
52  /**
53  Definition of the generic impelmentation class for the RandomFunctions.
54  Needs to have specialized implementations on the different type of engines
55  */
56  template <class EngineBaseType>
57  class RandomFunctionsImpl {
58  public:
59  void SetEngine(void *) {}
60  };
61 
62  /**
63  Implementation class for the RandomFunction for all the engined that derives from
64  TRandomEngine class, which defines an interface which has TRandomEngine::Rndm()
65  In this way we can have a common implementation for the RandomFunctions
66  */
67 
68  template<>
69  class RandomFunctionsImpl<TRandomEngine> {
70 
71  public:
72 
73  /// class constructor
74  RandomFunctionsImpl() : fBaseEngine(0) {}
75 
76  void SetEngine(void *r) {
77  fBaseEngine = static_cast<TRandomEngine*>(r);
78  assert(fBaseEngine); // to be sure the static cast works
79  }
80 
81 
82  ///Generate binomial numbers
83  int Binomial(int ntot, double prob);
84 
85  /// Return a number distributed following a BreitWigner function with mean and gamma.
86  double BreitWigner(double mean, double gamma);
87 
88  /// Generates random vectors, uniformly distributed over a circle of given radius.
89  /// Input : r = circle radius
90  /// Output: x,y a random 2-d vector of length r
91  void Circle(double &x, double &y, double r);
92 
93  /// Returns an exponential deviate.
94  /// exp( -t/tau )
95  double Exp(double tau);
96 
97  /// generate Gaussian number using Box-Muller method
98  double GausBM( double mean, double sigma);
99 
100  /// generate random numbers according to the Accemptance-Complemet-Ratio method
101  double GausACR( double mean, double sigma);
102 
103  /// Generate a random number following a Landau distribution
104  /// with location parameter mu and scale parameter sigma:
105  /// Landau( (x-mu)/sigma )
106  double Landau(double mu, double sigma);
107 
108  /// Generates a random integer N according to a Poisson law.
109  /// Prob(N) = exp(-mean)*mean^N/Factorial(N)
110  int Poisson(double mean);
111  double PoissonD(double mean);
112 
113  /// Generate numbers distributed following a gaussian with mean=0 and sigma=1.
114  /// Using the Box-Muller method
115  void Rannor(double &a, double &b);
116 
117  /// Generates random vectors, uniformly distributed over the surface
118  /// of a sphere of given radius.
119  void Sphere(double &x, double &y, double &z, double r);
120 
121  /// generate random numbers following a Uniform distribution in the [a,b] interval
122  double Uniform(double a, double b);
123  double Uniform(double a);
124 
125  protected:
126  TRandomEngine* fBaseEngine;
127 
128  private:
129  // Internal method used by the functions
130  double Rndm() { return fBaseEngine->Rndm(); }
131  // for internal usage
132  double Gaus(double mean, double sigma) { return GausACR(mean,sigma); }
133 
134 
135  };
136 
137 
138  template < class Engine, class EngineBaseType>
139  class RandomFunctions { //: public RandomFunctionsImpl<EngineBaseType> {
140 
141 
142  public:
143 
144  //RandomFunctions() {}
145 
146  RandomFunctions(Engine & rng) : fEngine(&rng) {
147  fImpl.SetEngine(&rng);
148  }
149 
150  /// destructor (no op) we do not mantain the engine)
151  ~RandomFunctions() {}
152 
153 
154  /// non-virtual method
155  inline double operator() () { return (*fEngine)(); }
156 
157 
158  ///Generate binomial numbers
159  int Binomial(int ntot, double prob) {
160  return fImpl.Binomial(ntot,prob);
161  }
162 
163  /// Return a number distributed following a BreitWigner function with mean and gamma.
164  double BreitWigner(double mean, double gamma) {
165  return fImpl.BreitWigner(mean,gamma);
166  }
167 
168  /// Generates random vectors, uniformly distributed over a circle of given radius.
169  /// Input : r = circle radius
170  /// Output: x,y a random 2-d vector of length r
171  void Circle(double &x, double &y, double r) {
172  return fImpl.Circle(x,y,r);
173  }
174 
175  /// Returns an exponential deviate.
176  /// exp( -t/tau )
177  double Exp(double tau) {
178  return fImpl.Exp(tau);
179  }
180 
181  /// generate Gaussian number using Box-Muller method
182  double GausBM( double mean, double sigma) {
183  return fImpl.GausBM(mean,sigma);
184  }
185 
186  /// generate random numbers according to the Accemptance-Complemet-Ratio method
187  double GausACR( double mean, double sigma) {
188  return fImpl.GausACR(mean, sigma);
189  }
190 
191  /// Generate a random number following a Landau distribution
192  /// with location parameter mu and scale parameter sigma:
193  /// Landau( (x-mu)/sigma )
194  double Landau(double mu, double sigma) {
195  return fImpl.Landau(mu,sigma);
196  }
197 
198  /// Generates a random integer N according to a Poisson law.
199  /// Prob(N) = exp(-mean)*mean^N/Factorial(N)
200  int Poisson(double mean) { return fImpl.Poisson(mean); }
201  double PoissonD(double mean) { return fImpl.PoissonD(mean); }
202 
203  /// Generate numbers distributed following a gaussian with mean=0 and sigma=1.
204  /// Using the Box-Muller method
205  void Rannor(double &a, double &b) {
206  return fImpl.Rannor(a,b);
207  }
208 
209  /// Generates random vectors, uniformly distributed over the surface
210  /// of a sphere of given radius.
211  void Sphere(double &x, double &y, double &z, double r) {
212  return fImpl.Sphere(x,y,z,r);
213  }
214 
215  /// generate random numbers following a Uniform distribution in the [a,b] interval
216  double Uniform(double a, double b) {
217  return (b-a) * Rndm_impl() + a;
218  }
219 
220  /// generate random numbers following a Uniform distribution in the [0,a] interval
221  double Uniform(double a) {
222  return a * Rndm_impl() ;
223  }
224 
225 
226  /// generate Gaussian number using defqault method
227  inline double Gaus( double mean, double sigma) {
228  return fImpl.GausACR(mean,sigma);
229  }
230 
231 
232  // /// re-implement Gaussian
233  // double GausBM2(double mean, double sigma) {
234  // double y = Rndm_impl();
235  // double z = Rndm_impl();
236  // double x = z * 6.28318530717958623;
237  // double radius = std::sqrt(-2*std::log(y));
238  // double g = radius * std::sin(x);
239  // return mean + g * sigma;
240  // }
241 
242 
243  /// methods which are only for GSL random generators
244 
245 
246  /// Gamma functions (not implemented here, requires a GSL random engine)
247  double Gamma( double , double ) {
248  //r.Error("Error: Gamma() requires a GSL Engine type");
249  static_assert(std::is_fundamental<Engine>::value,"Error: Gamma() requires a GSL Engine type");
250  return 0;
251  }
252  double Beta( double , double ) {
253  static_assert(std::is_fundamental<Engine>::value,"Error: Beta() requires a GSL Engine type");
254  return 0;
255  }
256  double LogNormal(double, double) {
257  static_assert(std::is_fundamental<Engine>::value,"Error: LogNormal() requires a GSL Engine type");
258  return 0;
259  }
260  double ChiSquare(double) {
261  static_assert(std::is_fundamental<Engine>::value,"Error: ChiSquare() requires a GSL Engine type");
262  return 0;
263  }
264  double Rayleigh( double ) {
265  static_assert(std::is_fundamental<Engine>::value,"Error: Rayleigh() requires a GSL Engine type");
266  return 0;
267  }
268  double Logistic( double ) {
269  static_assert(std::is_fundamental<Engine>::value,"Error: Logistic() requires a GSL Engine type");
270  return 0;
271  }
272  double Pareto( double , double ) {
273  static_assert(std::is_fundamental<Engine>::value,"Error: Pareto() requires a GSL Engine type");
274  return 0;
275  }
276  double FDist(double, double) {
277  static_assert(std::is_fundamental<Engine>::value,"Error: FDist() requires a GSL Engine type");
278  return 0;
279  }
280  double tDist(double) {
281  static_assert(std::is_fundamental<Engine>::value,"Error: tDist() requires a GSL Engine type");
282  return 0;
283  }
284  unsigned int NegativeBinomial(double , double ) {
285  static_assert(std::is_fundamental<Engine>::value,"Error: NegativeBinomial() requires a GSL Engine type");
286  return 0;
287  }
288  std::vector<unsigned int> MultiNomial(unsigned int, const std::vector<double> &){
289  static_assert(std::is_fundamental<Engine>::value,"Error: MultiNomial() requires a GSL Engine type");
290  return std::vector<unsigned int>();
291  }
292 
293 
294  protected:
295 
296  Engine & Rng() { assert(fEngine); return *fEngine; }
297 
298  /// Internal impelmentation to return random number
299  /// Since this one is not a virtual function is faster than Rndm
300  inline double Rndm_impl() { return (*fEngine)(); }
301 
302 
303  private:
304 
305  Engine * fEngine; //! random number generator engine
306  RandomFunctionsImpl<EngineBaseType> fImpl; //! instance of the class implementing the functions
307 
308 
309  };
310 
311 
312 
313 
314 } // namespace Math
315 } // namespace ROOT
316 
317 #endif /* ROOT_Math_RandomFunctions */