1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
#include "FastSimulation/Utilities/interface/BaseNumericalRandomGenerator.h"
#include "FastSimulation/Utilities/interface/RandomEngineAndDistribution.h"
#include <cmath>
// #include <iostream>
BaseNumericalRandomGenerator::BaseNumericalRandomGenerator(double xmin, double xmax, int n, int iter)
: xmin(xmin), xmax(xmax), n(n), iter(iter) {
f.resize(n);
sampling.resize(n);
}
void BaseNumericalRandomGenerator::initialize() {
m = n - 1;
rmin = 0.;
deltar = (double)m - rmin;
std::vector<double> a, y, z, xnew;
a.resize(n);
y.resize(n);
z.resize(n);
xnew.resize(n);
double sig1 = 0.;
// Initialize sampling
double du = (xmax - xmin) / (float)m;
sampling[0] = xmin;
for (int i = 1; i < n; ++i)
sampling[i] = sampling[i - 1] + du;
// Starting point for iterations
for (int it = 0; it < iter; ++it) {
// Calculate function values
for (int i = 0; i < n; ++i)
f[i] = function(sampling[i]);
// Calculate bin areas
for (int i = 0; i < m; ++i)
a[i] = (sampling[i + 1] - sampling[i]) * (f[i + 1] + f[i]) / 2.;
// Calculate cumulative spectrum Y values
y[0] = 0.;
for (int i = 1; i < n; ++i)
y[i] = y[i - 1] + a[i - 1];
// Put equidistant points on y scale
double dz = y[n - 1] / (float)m;
z[0] = 0;
for (int i = 1; i < n; ++i)
z[i] = z[i - 1] + dz;
// Determine spacinf of Z points in between Y points
// From this, determine new X values and finally replace old values
xnew[0] = sampling[0];
xnew[n - 1] = sampling[n - 1];
int k = 0;
for (int i = 1; i < m; ++i) {
while (y[k + 1] < z[i])
++k;
double r = (z[i] - y[k]) / (y[k + 1] - y[k]);
xnew[i] = sampling[k] + (sampling[k + 1] - sampling[k]) * r;
}
for (int i = 0; i < n; ++i)
sampling[i] = xnew[i];
sig1 = sig1 + y[m];
// std::cout << "BaseNumericalRandomGenerator::Iteration # " << it+1
// << " Integral = " << sig1/(float)(it+1)
// << std::endl;
}
}
double BaseNumericalRandomGenerator::generate(RandomEngineAndDistribution const* random) const {
double r = rmin + deltar * random->flatShoot();
int i = (int)r;
double s = r - (double)i;
// cout << " i,r,s = " << i << " " << r << " " << s << endl;
return sampling[i] + s * (sampling[i + 1] - sampling[i]);
}
double BaseNumericalRandomGenerator::generateExp(RandomEngineAndDistribution const* random) const {
double r = rmin + deltar * random->flatShoot();
int i = (int)r;
// double s=r-(double)i;
// cout << " i,r,s = " << i << " " << r << " " << s << endl;
double b = -std::log(f[i + 1] / f[i]) / (sampling[i + 1] - sampling[i]);
double a = f[i] * std::exp(b * sampling[i]);
double umin = -a / b * std::exp(-b * sampling[i]);
double umax = -a / b * std::exp(-b * sampling[i + 1]);
double u = (umax - umin) * random->flatShoot() + umin;
return -std::log(-b / a * u) / b;
}
double BaseNumericalRandomGenerator::generateLin(RandomEngineAndDistribution const* random) const {
double r = rmin + deltar * random->flatShoot();
int i = (int)r;
// double s=r-(double)i;
// cout << " i,r,s = " << i << " " << r << " " << s << endl;
double a = (f[i + 1] - f[i]) / (sampling[i + 1] - sampling[i]);
double b = f[i] - a * sampling[i];
double umin = a * sampling[i] * sampling[i] / 2. + b * sampling[i];
double umax = a * sampling[i + 1] * sampling[i + 1] / 2. + b * sampling[i + 1];
double u = (umax - umin) * random->flatShoot() + umin;
return (-b + std::sqrt(b * b + 2. * a * u)) / a;
}
bool BaseNumericalRandomGenerator::setSubInterval(double x1, double x2) {
if (x1 < xmin || x2 > xmax)
return false;
if (x1 > x2) {
double tmp = x1;
x1 = x2;
x2 = tmp;
}
unsigned ibin = 1;
for (; ibin < (unsigned)n && x1 > sampling[ibin]; ++ibin)
;
unsigned ibin1 = ibin;
for (; ibin < (unsigned)n && x2 > sampling[ibin]; ++ibin)
;
unsigned ibin2 = ibin;
// cout << sampling[ibin1-1] << " " << x1 << " " << sampling[ibin1] << endl;
// cout << sampling[ibin2-1] << " " << x2 << " " << sampling[ibin2] << endl;
rmin = ibin1 + (x1 - sampling[ibin1]) / (sampling[ibin1] - sampling[ibin1 - 1]);
deltar = ibin2 + (x2 - sampling[ibin2]) / (sampling[ibin2] - sampling[ibin2 - 1]) - rmin;
// cout << rmin << " " << deltar << endl;
return true;
}
|