Warning, file /DD4hep/DDDigi/src/DigiRandomGenerator.cpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #include <DDDigi/DigiRandomGenerator.h>
0028 #include <Math/ProbFuncMathCore.h>
0029 #include <Math/SpecFuncMathCore.h>
0030 #include <Math/QuantFuncMathCore.h>
0031 #include <cmath>
0032
0033
0034 using namespace dd4hep::digi;
0035
0036 static constexpr double PIOVER2 = M_PI / 2.0;
0037 static constexpr double TWOPI = M_PI * 2.0;
0038
0039 double DigiRandomGenerator::random() const {
0040 return engine();
0041 }
0042
0043 double DigiRandomGenerator::uniform(double x1) const {
0044 double ans = engine();
0045 return x1*ans;
0046 }
0047
0048 double DigiRandomGenerator::uniform(double x1, double x2) const {
0049 double ans= engine();
0050 return x1 + (x2-x1)*ans;
0051 }
0052
0053 int DigiRandomGenerator::binomial(int ntot, double prob) const {
0054 if (prob < 0 || prob > 1) return 0;
0055 int n = 0;
0056 for (int i=0;i<ntot;i++) {
0057 if (engine() > prob) continue;
0058 n++;
0059 }
0060 return n;
0061 }
0062
0063 double DigiRandomGenerator::exponential(double tau) const {
0064 double x = engine();
0065 double t = -tau * std::log( x );
0066 return t;
0067 }
0068
0069 double DigiRandomGenerator::gaussian(double mean, double sigma) const {
0070 const double kC1 = 1.448242853;
0071 const double kC2 = 3.307147487;
0072 const double kC3 = 1.46754004;
0073 const double kD1 = 1.036467755;
0074 const double kD2 = 5.295844968;
0075 const double kD3 = 3.631288474;
0076 const double kHm = 0.483941449;
0077 const double kZm = 0.107981933;
0078 const double kHp = 4.132731354;
0079 const double kZp = 18.52161694;
0080 const double kPhln = 0.4515827053;
0081 const double kHm1 = 0.516058551;
0082 const double kHp1 = 3.132731354;
0083 const double kHzm = 0.375959516;
0084 const double kHzmp = 0.591923442;
0085
0086
0087 const double kAs = 0.8853395638;
0088 const double kBs = 0.2452635696;
0089 const double kCs = 0.2770276848;
0090 const double kB = 0.5029324303;
0091 const double kX0 = 0.4571828819;
0092 const double kYm = 0.187308492 ;
0093 const double kS = 0.7270572718 ;
0094 const double kT = 0.03895759111;
0095
0096 double result;
0097 double rn,x,y,z;
0098
0099 do {
0100 y = engine();
0101
0102 if (y>kHm1) {
0103 result = kHp*y-kHp1; break; }
0104
0105 else if (y<kZm) {
0106 rn = kZp*y-1;
0107 result = (rn>0) ? (1+rn) : (-1+rn);
0108 break;
0109 }
0110
0111 else if (y<kHm) {
0112 rn = engine();
0113 rn = rn-1+rn;
0114 z = (rn>0) ? 2-rn : -2-rn;
0115 if ((kC1-y)*(kC3+std::abs(z))<kC2) {
0116 result = z; break; }
0117 else {
0118 x = rn*rn;
0119 if ((y+kD1)*(kD3+x)<kD2) {
0120 result = rn; break; }
0121 else if (kHzmp-y<exp(-(z*z+kPhln)/2)) {
0122 result = z; break; }
0123 else if (y+kHzm<exp(-(x+kPhln)/2)) {
0124 result = rn; break; }
0125 }
0126 }
0127
0128 while (1) {
0129 x = engine();
0130 y = kYm * engine();
0131 z = kX0 - kS*x - y;
0132 if (z>0)
0133 rn = 2+y/x;
0134 else {
0135 x = 1-x;
0136 y = kYm-y;
0137 rn = -(2+y/x);
0138 }
0139 if ((y-kAs+x)*(kCs+x)+kBs<0) {
0140 result = rn; break; }
0141 else if (y<x+kT)
0142 if (rn*rn<4*(kB-log(x))) {
0143 result = rn; break; }
0144 }
0145 } while(0);
0146
0147 return mean + sigma * result;
0148 }
0149
0150 double DigiRandomGenerator::landau (double mu, double sigma) const {
0151 if (sigma <= 0) return 0;
0152 double x = engine();
0153 double res = mu + ROOT::Math::landau_quantile(x, sigma);
0154 return res;
0155 }
0156
0157 double DigiRandomGenerator::breitWigner(double mean, double gamma) const {
0158 double rval = 2*engine() - 1;
0159 double displ = 0.5*gamma*std::tan(rval*PIOVER2);
0160 return (mean+displ);
0161 }
0162
0163 double DigiRandomGenerator::poisson(double mean) const {
0164 int n;
0165 if (mean <= 0) return 0;
0166 if (mean < 25) {
0167 double expmean = std::exp(-mean);
0168 double pir = 1;
0169 n = -1;
0170 while(1) {
0171 n++;
0172 pir *= engine();
0173 if (pir <= expmean) break;
0174 }
0175 return static_cast<double>(n);
0176 }
0177
0178 else if (mean < 1E9) {
0179 double em, t, y;
0180 double sq, alxm, g;
0181 double pi = M_PI;
0182
0183 sq = std::sqrt(2.0*mean);
0184 alxm = std::log(mean);
0185 g = mean*alxm - ::ROOT::Math::lgamma(mean + 1.0);
0186
0187 do {
0188 do {
0189 y = std::tan(pi*engine());
0190 em = sq*y + mean;
0191 } while( em < 0.0 );
0192
0193 em = std::floor(em);
0194 t = 0.9*(1.0 + y*y)* std::exp(em*alxm - ::ROOT::Math::lgamma(em + 1.0) - g);
0195 } while( engine() > t );
0196
0197 return em;
0198
0199 } else {
0200
0201 return gaussian(0,1)*std::sqrt(mean) + mean +0.5;
0202 }
0203 }
0204
0205 void DigiRandomGenerator::rannor(float& a, float& b) const {
0206 double r, x, y, z;
0207
0208 y = engine();
0209 z = engine();
0210 x = z * 6.28318530717958623;
0211 r = std::sqrt(-2*std::log(y));
0212 a = (float)(r * std::sin(x));
0213 b = (float)(r * std::cos(x));
0214 }
0215
0216 void DigiRandomGenerator::rannor(double& a, double& b) const {
0217 double r, x, y, z;
0218
0219 y = engine();
0220 z = engine();
0221 x = z * 6.28318530717958623;
0222 r = std::sqrt(-2*std::log(y));
0223 a = (float)(r * std::sin(x));
0224 b = (float)(r * std::cos(x));
0225 }
0226
0227 void DigiRandomGenerator::sphere(double& x, double& y, double& z, double r) const {
0228 double a=0,b=0,r2=1;
0229 while (r2 > 0.25) {
0230 a = engine() - 0.5;
0231 b = engine() - 0.5;
0232 r2 = a*a + b*b;
0233 }
0234 z = r* ( -1. + 8.0 * r2 );
0235
0236 double scale = 8.0 * r * std::sqrt(0.25 - r2);
0237 x = a*scale;
0238 y = b*scale;
0239 }
0240
0241 void DigiRandomGenerator::circle(double &x, double &y, double r) const {
0242 double phi = uniform(0,TWOPI);
0243 x = r*std::cos(phi);
0244 y = r*std::sin(phi);
0245 }