Garfield 0.3
Toolkit for the detailed simulation of particle detectors based on ionization measurement in gases and semiconductors
Loading...
Searching...
No Matches
Random.hh
Go to the documentation of this file.
1#ifndef G_RANDOM_H
2#define G_RANDOM_H
3
4#include <cmath>
5#include <functional>
6#include <utility>
7
9
10namespace Garfield {
11
12class Random {
13 public:
14 Random() = default;
15 template <typename T>
16 static inline void SetEngine(T engine) {
17 draw = std::bind(&T::Draw, engine);
18 }
19 inline double static Draw() noexcept { return draw(); };
20
21 private:
22 static std::function<double(void)> draw;
23};
24
26inline double RndmUniform() { return Random::Draw(); }
27
29inline double RndmUniformPos() {
30 double r = RndmUniform();
31 while (r <= 0.) r = RndmUniform();
32 return r;
33}
34
36inline std::pair<double, double> RndmGaussians() {
37 // Box-Muller algorithm
38 double u = 2. * RndmUniform() - 1.;
39 double v = 2. * RndmUniform() - 1.;
40 double r2 = u * u + v * v;
41 while (r2 > 1.) {
42 u = 2. * RndmUniform() - 1.;
43 v = 2. * RndmUniform() - 1.;
44 r2 = u * u + v * v;
45 }
46 const double p = sqrt(-2. * log(r2) / r2);
47 return std::make_pair(u * p, v * p);
48}
49
51inline double RndmGaussian() {
52 const auto r = RndmGaussians();
53 return r.first;
54}
55
57inline std::pair<double, double> RndmGaussians(const double mu,
58 const double sigma) {
59 auto r = RndmGaussians();
60 r.first = mu + sigma * r.first;
61 r.second = mu + sigma * r.second;
62 return r;
63}
64
66inline double RndmGaussian(const double mu, const double sigma) {
67 return mu + sigma * RndmGaussian();
68}
69
72inline double RndmLorentzian(const double mu, const double gamma) {
73 return mu + gamma * tan(Pi * (RndmUniform() - 0.5));
74}
75
80inline double RndmVoigt(const double mu, const double sigma,
81 const double gamma) {
82 if (sigma <= 0.) return RndmLorentzian(mu, gamma);
83 const double a = gamma / (Sqrt2 * sigma);
84 const double x = RndmLorentzian(0., a) + RndmGaussian(0., 1. / Sqrt2);
85 return mu + x * Sqrt2 * sigma;
86}
87
89inline unsigned int RndmYuleFurry(const double mean) {
90 if (mean <= 0.) return 0;
91 return 1 + static_cast<unsigned int>(std::log(RndmUniformPos()) /
92 std::log1p(-1. / mean));
93 /*
94 const double u = RndmUniform();
95 double p = 1. / mean;
96 const double q = 1. - p;
97 double sum = p;
98 unsigned int k = 1;
99 while (sum < u) {
100 ++k;
101 p *= q;
102 sum += p;
103 }
104 return k;
105 */
106}
107
109inline double RndmPolya(const double theta) {
110 // Algorithm from Review of Particle Physics
111 // C. Amsler et al, Phys. Lett. B 667 (2008)
112 if (theta <= 0.) return -log(RndmUniformPos());
113 const double c = 3 * (theta + 1.) - 0.75;
114 double u1, u2, v1, v2, v3;
115 double x;
116 while (1) {
117 u1 = RndmUniformPos();
118 v1 = u1 * (1. - u1);
119 if (v1 == 0.) continue;
120 v2 = (u1 - 0.5) * sqrt(c / v1);
121 x = theta + v2;
122 if (x <= 0.) continue;
123 u2 = RndmUniformPos();
124 v3 = 64 * u2 * u2 * pow(v1, 3);
125 if (v3 <= 1. - 2 * v2 * v2 / x ||
126 log(v3) <= 2 * (theta * log(x / theta) - v2)) {
127 return x / (theta + 1.);
128 }
129 }
130}
131
133double RndmLandau();
135double RndmVavilov(const double rkappa, const double beta2);
136
138int RndmPoisson(const double mean);
139
143double RndmHeedWF(const double w, const double f);
144
146inline void RndmDirection(double& dx, double& dy, double& dz,
147 const double length = 1.) {
148 const double phi = TwoPi * RndmUniform();
149 const double ctheta = 2 * RndmUniform() - 1.;
150 const double stheta = sqrt(1. - ctheta * ctheta);
151 dx = length * cos(phi) * stheta;
152 dy = length * sin(phi) * stheta;
153 dz = length * ctheta;
154}
155} // namespace Garfield
156
157#endif
Random()=default
static std::function< double(void)> draw
Definition Random.hh:22
static void SetEngine(T engine)
Definition Random.hh:16
static double Draw() noexcept
Definition Random.hh:19
double RndmLorentzian(const double mu, const double gamma)
Draw a Lorentzian random variate with mean mu and half-width at half maximum gamma.
Definition Random.hh:72
unsigned int RndmYuleFurry(const double mean)
Draw a random number from a geometric distribution.
Definition Random.hh:89
double RndmHeedWF(const double w, const double f)
Draw a random energy needed to create a single electron in a material asymptotic work function W and ...
double RndmUniform()
Draw a random number uniformly distributed in the range [0, 1).
Definition Random.hh:26
double RndmVavilov(const double rkappa, const double beta2)
Draw a random number from a Vavilov distribution.
double RndmPolya(const double theta)
Draw a Polya distributed random number.
Definition Random.hh:109
void RndmDirection(double &dx, double &dy, double &dz, const double length=1.)
Draw a random (isotropic) direction vector.
Definition Random.hh:146
double RndmVoigt(const double mu, const double sigma, const double gamma)
Draw a random number according to a Voigt function with mean mu.
Definition Random.hh:80
double RndmUniformPos()
Draw a random number uniformly distributed in the range (0, 1).
Definition Random.hh:29
std::pair< double, double > RndmGaussians()
Draw two Gaussian random variates with mean zero and standard deviation one.
Definition Random.hh:36
double RndmGaussian()
Draw a Gaussian random variate with mean zero and standard deviation one.
Definition Random.hh:51
double RndmLandau()
Draw a random number from a Landau distribution.
int RndmPoisson(const double mean)
Draw a random number from a Poisson distribution.