16 namespace RandomGenerators {
26 if (mean <= 0)
return 0;
28 double expmean = exp(-mean);
33 pir *= randgenMT.rand();
34 if (pir <= expmean)
break;
50 y = tan(pi*randgenMT.rand());
55 t = 0.9*(1.0 + y * y)* exp(em*alxm - xMath::LogGamma(em + 1.0) - g);
56 }
while (randgenMT.rand() > t);
58 return static_cast<int> (em);
71 if (mean <= 0)
return 0;
73 double expmean = exp(-mean);
79 if (pir <= expmean)
break;
95 y = tan(pi*rangen.rand());
100 t = 0.9*(1.0 + y * y)* exp(em*alxm - xMath::LogGamma(em + 1.0) - g);
101 }
while (rangen.rand() > t);
103 return static_cast<int> (em);
115 return exp(-(mu1 + mu2)) * pow(sqrt(mu1 / mu2), k) *
xMath::BesselI(k, 2. * sqrt(mu1 * mu2));
119 double SiemensRasmussenMomentumGenerator::g(
double x,
double mass)
const {
123 double talpha = alpha(tp);
125 double en = sqrt(tp * tp + mass * mass);
126 double sh = sinh(talpha);
127 double shtalpha = 1.;
129 shtalpha = sh / talpha;
130 double ch = sqrt(1. + sh * sh);
131 return tp * tp * exp(-m_Gamma * en / m_T) * ((1. + m_T / m_Gamma / en)*shtalpha - m_T / m_Gamma / en * ch) / x;
134 double SiemensRasmussenMomentumGenerator::g2(
double x,
double tp,
double mass)
const {
137 double talpha = alpha(tp);
139 double en = sqrt(tp * tp + mass * mass);
140 double sh = sinh(talpha);
141 double shtalpha = 1.;
143 shtalpha = sh / talpha;
144 double ch = sqrt(1. + sh * sh);
145 return tp * tp * exp(-m_Gamma * en / m_T) * ((1. + m_T / m_Gamma / en)*shtalpha - m_T / m_Gamma / en * ch) / x;
148 void SiemensRasmussenMomentumGenerator::FixParameters() {
150 double l = 0., r = 1.;
151 double m1 = l + (r - l) / 3.;
152 double m2 = r - (r - l) / 3.;
155 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
162 m1 = l + (r - l) / 3.;
163 m2 = r - (r - l) / 3.;
166 m_Max = g((m1 + m2) / 2.);
169 double SiemensRasmussenMomentumGenerator::GetRandom(
double mass)
const {
173 double x0 = randgenMT.randDblExc();
174 double y0 = m_Max * randgenMT.randDblExc();
178 if (y0 < mn * g(x0))
return -log(x0);
184 std::vector<double> ret(0);
185 double tp = GetRandom(mass);
186 double tphi = 2. *
xMath::Pi() * randgenMT.rand();
187 double cthe = 2. * randgenMT.rand() - 1.;
188 double sthe = sqrt(1. - cthe * cthe);
189 ret.push_back(tp*cos(tphi)*sthe);
190 ret.push_back(tp*sin(tphi)*sthe);
191 ret.push_back(tp*cthe);
196 double ThermalMomentumGenerator::g(
double x,
double mass)
const 201 double texp = exp((sqrt(mass * mass + tp * tp) - m_Mu) / m_T);
202 return tp * tp / (texp + m_Statistics) / x;
205 void ThermalMomentumGenerator::FixParameters()
208 double l = 0., r = 1.;
209 double m1 = l + (r - l) / 3.;
210 double m2 = r - (r - l) / 3.;
213 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
220 m1 = l + (r - l) / 3.;
221 m2 = r - (r - l) / 3.;
224 m_Max = g((m1 + m2) / 2.);
227 double ThermalMomentumGenerator::ComputeMaximum(
double mass)
const 230 double l = 0., r = 1.;
231 double m1 = l + (r - l) / 3.;
232 double m2 = r - (r - l) / 3.;
235 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
236 if (g(m1, mass) < g(m2, mass)) {
242 m1 = l + (r - l) / 3.;
243 m2 = r - (r - l) / 3.;
246 return g((m1 + m2) / 2., mass);
254 double x0 = randgenMT.randDblExc();
256 if (mass < m_Mu && m_Statistics == -1)
257 printf(
"**WARNING** ThermalMomentumGenerator::GetP: Bose-condensation mu %lf > mass %lf\n", m_Mu, mass);
261 M = ComputeMaximum(mass);
263 double prob = g(x0, mass) / M;
266 printf(
"**WARNING** ThermalMomentumGenerator::GetP: Probability exceeds unity by %E\n", prob - 1.);
268 if (randgenMT.randDblExc() < prob)
return -log(x0);
275 double Tkin,
double etamax,
double mass,
int statistics,
double mu) :
276 m_FreezeoutModel(FreezeoutModel),
277 m_Tkin(Tkin), m_EtaMax(etamax), m_Mass(mass),
278 m_Generator(mass, statistics, Tkin, mu)
280 if (m_FreezeoutModel == NULL) {
287 if (m_FreezeoutModel != NULL)
288 delete m_FreezeoutModel;
296 std::vector<double> ret(3, 0.);
302 double betar = m_FreezeoutModel->
tanhetaperp(zetacand);
303 double cosheta = cosh(eta);
304 double sinheta = sinh(eta);
306 double cosphi = cos(ph);
307 double sinphi = sin(ph);
309 double vx = betar * cosphi / cosheta;
310 double vy = betar * sinphi / cosheta;
311 double vz = tanh(eta);
315 double tp = m_Generator.
GetP(mass);
318 double sthe = sqrt(1. - cthe * cthe);
319 part.
px = tp * cos(tphi) * sthe;
320 part.
py = tp * sin(tphi) * sthe;
322 part.
p0 = sqrt(mass * mass + tp * tp);
324 double p0LRF = part.
p0;
331 double dRdZeta = m_FreezeoutModel->
dRdZeta(zetacand);
332 double dtaudZeta = m_FreezeoutModel->
dtaudZeta(zetacand);
334 double coshetaperp = m_FreezeoutModel->
coshetaperp(zetacand);
335 double sinhetaperp = m_FreezeoutModel->
sinhetaperp(zetacand);
337 double prob = (dRdZeta * (cosheta * part.
p0 - sinheta * part.
pz)
338 - dtaudZeta * (cosphi * part.
px + sinphi * part.
py)) /
339 (coshetaperp * dRdZeta - sinhetaperp * dtaudZeta) / p0LRF
358 double zetacand = rangen.rand();
362 if (rangen.rand() < prob)
369 double BreitWignerGenerator::f(
double x)
const {
370 return x / ((x*x - m_M * m_M)*(x*x - m_M * m_M) + m_M * m_M*m_Gamma*m_Gamma);
373 void BreitWignerGenerator::FixParameters() {
375 double l = m_Mthr, r = m_M + 2.*m_Gamma;
376 double m1 = l + (r - l) / 3.;
377 double m2 = r - (r - l) / 3.;
380 while (fabs(m2 - m1) < eps && iter < MAXITERS) {
387 m1 = l + (r - l) / 3.;
388 m2 = r - (r - l) / 3.;
391 m_Max = f((m1 + m2) / 2.);
396 if (m_Gamma < 1e-7)
return m_M;
398 double x0 = m_Mthr + (m_M + 2.*m_Gamma - m_Mthr) * randgenMT.rand();
399 double y0 = m_Max * randgenMT.rand();
400 if (y0 < f(x0))
return x0;
422 double Threshold = m_part->DecayThresholdMass();
423 double Width = m_part->ResonanceWidth();
424 double Mass = m_part->Mass();
426 double a = std::max(Threshold, Mass - 2.*Width);
427 double b = Mass + 2.*Width;
430 m_Xmax = b + (b - a)*0.2;
435 double dM = (m_Xmax - m_Xmin) / (iters - 1.);
436 for (
int i = 0; i < iters; ++i) {
437 double tM = m_Xmin + dM * i;
438 m_Max = std::max(m_Max, f(tM));
445 return m_part->ThermalMassDistribution(M, m_T, m_Mu, m_part->ResonanceWidth());
450 if (m_part->ResonanceWidth() / m_part->Mass() < 1.e-2)
451 return m_part->Mass();
453 double x0 = m_Xmin + (m_Xmax - m_Xmin) * randgenMT.rand();
454 double y0 = m_Max * randgenMT.rand();
455 if (y0 < f(x0))
return x0;
462 double Threshold = m_part->DecayThresholdMass();
463 double Width = m_part->ResonanceWidth();
464 double Mass = m_part->Mass();
466 double a = std::max(Threshold, Mass - 2.*Width);
467 double b = Mass + 2.*Width;
469 if (m_part->Decays().size() == 0)
470 a = Mass - 2.*Width + 1.e-6;
472 a = m_part->DecayThresholdMassDynamical();
477 m_Xmax = b + 0.2 * (b - a);
485 double dM = (m_Xmax - m_Xmin) / (iters - 1.);
486 for (
int i = 0; i < iters; ++i) {
487 double tM = m_Xmin + dM * i;
488 m_Max = std::max(m_Max, f(tM));
495 return m_part->ThermalMassDistribution(M, m_T, m_Mu, m_part->TotalWidtheBW(M));
514 if (nu < 0 || n < 0)
return 0.0;
516 double logret = (2. * n + nu) * log(a/2.) - a;
517 for (
int i = 1; i <= n; ++i)
518 logret -= 2. * log(i);
519 for (
int i = n + 1; i <= n + nu; ++i)
527 double hn2 = 1., hn1 = 0., hn = 0.;
528 double kn2 = 0., kn1 = 1., kn = 0.;
530 for (
int n = 1; n <= nmax; ++n) {
531 double an = 2. * (nu + n) / x;
541 if (n == nmax && nmax <= 1000 && abs(hn2 / kn2 - hn1 / kn1) > 1.e-9)
545 printf(
"**WARNING** BesselDistributionGenerator::R(x,nu): Reached maximum iterations...\n");
553 return mu(a, nu) + (1. / 4.) * a * a * R(a, nu) * (R(a,nu+1) - R(a,nu));
558 double tmp = m(a, nu) - mu(a, nu);
559 return chi2(a, nu) + tmp * tmp;
564 double A = sqrt(a*a + nu*nu);
565 double B = sqrt(a*a + (nu+1.)*(nu+1.));
566 double tmp = 1. + a * a * (1. + B - A) / 2. / (nu + A) / (nu + 1. + B);
567 return a*a / 2. / (nu + A) + tmp * tmp;
572 if (nu < 0 || a <= 0.)
return 0;
607 for (
int i = 1; i <= X; ++i) {
608 ret *= (a / 2.)/(tm + i);
609 ret *= (a / 2.)/(tm + nu + i);
613 for (
int i = 1; i <= -X; ++i) {
614 ret *= (tm + X + i) / (a / 2.);
615 ret *= (tm + nu + X + i) / (a / 2.);
625 double pm = pn(tm, a, nu);
626 double w = 1. + pm / 2.;
628 double U = rangen.rand();
629 double W = rangen.rand();
631 if (rangen.rand() < 0.5)
635 if (U <= w / (1. + w)) {
636 double V = rangen.rand();
640 double E = -log(rangen.randDblExc());
643 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) 644 int X = S * std::lround(Y);
646 int X = S * ((Y > 0.0) ? std::floor(Y + 0.5) : std::ceil(Y - 0.5));
652 double pratio = pmXmOverpm(X, tm, a, nu);
654 if (pratio != pratio) {
655 printf(
"**WARNING** BesselDistributionGenerator::RandomBesselDevroye1: Float problem!");
659 if (W * std::min(1., exp(w - pm * Y)) <= pratio)
668 double tsig = sqrt(sig2(a, nu));
669 double q = std::min(1. / tsig / sqrt(648.), 1. / 3.);
671 double U = rangen.rand();
672 double W = rangen.rand();
674 if (rangen.rand() < 0.5)
678 if (U <= (1. + 2. / q) / (1. + 4. / q)) {
679 double V = rangen.rand();
680 Y = V * (1. / 2. + 1. / q);
683 double E = -log(rangen.randDblExc());
684 Y = 1. / 2. + 1. / q + E / q;
686 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) 687 int X = S * std::lround(Y);
689 int X = S * ((Y > 0.0) ? std::floor(Y + 0.5) : std::ceil(Y - 0.5));
695 double pratio = pmXmOverpm(X, tm, a, nu);
697 if (pratio != pratio) {
698 printf(
"**WARNING** BesselDistributionGenerator::RandomBesselDevroye2: Float problem!");
702 if (W * std::min(1., exp(1. + q/2. - q*Y)) <= pratio)
711 double tQ = sqrt(Q2(a, nu));
712 double q = std::min(1. / tQ / sqrt(648.), 1. / 3.);
714 double U = rangen.rand();
715 double W = rangen.rand();
717 if (rangen.rand() < 0.5)
721 if (U <= (1. + 2. / q) / (1. + 4. / q)) {
722 double V = rangen.rand();
723 Y = V * (1. / 2. + 1. / q);
726 double E = -log(rangen.randDblExc());
727 Y = 1. / 2. + 1. / q + E / q;
729 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) 730 int X = S * std::lround(Y);
732 int X = S * ((Y > 0.0) ? std::floor(Y + 0.5) : std::ceil(Y - 0.5));
738 double pratio = pmXmOverpm(X, tm, a, nu);
740 if (pratio != pratio) {
741 printf(
"**WARNING** BesselDistributionGenerator::RandomBesselDevroye3: Float problem!");
746 if (W * std::min(1., exp(1. + q/2. - q*Y)) <= pratio)
755 while (ret <= -0.5) {
756 ret = rangen.randNorm(mu(a,nu), sqrt(
chi2(a,nu)));
758 return static_cast<int>(ret + 0.5);
766 return RandomBesselPoisson(a, nu, rangen);
768 return RandomBesselDevroye3(a, nu, rangen);
771 return RandomBesselNormal(a, nu, rangen);
781 double sinth = sqrt(1. - costh * costh);
783 double vx = GetBeta() * sinth * cos(ph);
784 double vy = GetBeta() * sinth * sin(ph);
785 double vz = GetBeta() * costh;
789 double tp = m_Generator.
GetP(mass);
792 double sthe = sqrt(1. - cthe * cthe);
793 part.
px = tp * cos(tphi) * sthe;
794 part.
py = tp * sin(tphi) * sthe;
796 part.
p0 = sqrt(mass * mass + tp * tp);
800 std::vector<double> ret(3);
818 namespace RandomGenerators {
820 void SSHMomentumGenerator::FixParameters() {
823 double l = 0., r = 1.;
824 double m1 = l + (r - l) / 3.;
825 double m2 = r - (r - l) / 3.;
828 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
835 m1 = l + (r - l) / 3.;
836 m2 = r - (r - l) / 3.;
839 m_MaxPt = g((m1 + m2) / 2.);
843 for (
double x = 0.5 * dx; x <= 1.; x += dx) {
844 m_dndpt.add_val(x, g(x));
852 for (
double x = 0.5 * dx; x <= 1.; x += dx) {
857 double l = -4. - m_EtaMax, r = 4. + m_EtaMax;
858 double m1 = l + (r - l) / 3.;
859 double m2 = r - (r - l) / 3.;
862 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
863 if (m_distr.dndy(m1, pt) < m_distr.dndy(m2, pt)) {
869 m1 = l + (r - l) / 3.;
870 m2 = r - (r - l) / 3.;
873 m_MaxYs.push_back(m_distr.dndy((m1 + m2) / 2., pt));
877 for (
double ty = -4. - m_EtaMax + 0.5 * dy; ty <= 4. + m_EtaMax; ty += dy) {
878 m_dndy[m_dndy.size() - 1].add_val(ty, m_distr.dndy(ty, pt));
884 void SSHMomentumGenerator::FixParameters2() {
887 double l = 0., r = 1.;
888 double m1 = l + (r - l) / 3.;
889 double m2 = r - (r - l) / 3.;
892 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
899 m1 = l + (r - l) / 3.;
900 m2 = r - (r - l) / 3.;
903 m_MaxPt = g((m1 + m2) / 2.);
907 for (
double x = 0.5 * dx; x <= 1.; x += dx) {
908 m_dndpt.add_val(x, g(x));
916 for (
double x = 0.5 * dx; x <= 1.; x += dx) {
921 double l = -4. - m_EtaMax, r = 4. + m_EtaMax;
922 double m1 = l + (r - l) / 3.;
923 double m2 = r - (r - l) / 3.;
926 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
927 if (m_distr.dndysingle(m1, pt) < m_distr.dndysingle(m2, pt)) {
933 m1 = l + (r - l) / 3.;
934 m2 = r - (r - l) / 3.;
937 m_MaxYs.push_back(m_distr.dndysingle((m1 + m2) / 2., pt));
941 for (
double ty = -4. + 0.5 * dy; ty <= 4.; ty += dy) {
942 m_dndy[m_dndy.size() - 1].add_val(ty, m_distr.dndysingle(ty, pt));
949 void SSHMomentumGenerator::FindMaximumPt() {
952 double l = 0., r = 1.;
953 double m1 = l + (r - l) / 3.;
954 double m2 = r - (r - l) / 3.;
957 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
964 m1 = l + (r - l) / 3.;
965 m2 = r - (r - l) / 3.;
968 m_MaxPt = g((m1 + m2) / 2.);
972 for (
double x = 0.5 * dx; x <= 1.; x += dx) {
973 m_dndpt.add_val(x, g(x));
977 void SSHMomentumGenerator::FindMaximumY(
double pt) {
979 double l = -4. - m_EtaMax, r = 4. + m_EtaMax;
980 double m1 = l + (r - l) / 3.;
981 double m2 = r - (r - l) / 3.;
984 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
985 if (m_distr.dndy(m1, pt) < m_distr.dndy(m2, pt)) {
991 m1 = l + (r - l) / 3.;
992 m2 = r - (r - l) / 3.;
995 m_MaxY = m_distr.dndy((m1 + m2) / 2., pt);
998 void SSHMomentumGenerator::FindMaximumY2(
double pt) {
1000 double l = -4. - m_EtaMax, r = 4. + m_EtaMax;
1001 double m1 = l + (r - l) / 3.;
1002 double m2 = r - (r - l) / 3.;
1005 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
1006 if (m_distr.dndysingle(m1, pt) < m_distr.dndysingle(m2, pt)) {
1012 m1 = l + (r - l) / 3.;
1013 m2 = r - (r - l) / 3.;
1016 m_MaxY = m_distr.dndysingle((m1 + m2) / 2., pt);
1019 std::pair<double, double> SSHMomentumGenerator::GetRandom(
double mass) {
1020 double tpt = 0., ty = 0.;
1023 double y0 = m_MaxPt *
randgenMT.randDblExc();
1030 int ind = (int)(exp(-tpt) / m_dPt);
1031 if (ind < 0) ind = 0;
1032 if (ind >= static_cast<int>(m_dndy.size())) ind = m_dndy.size() - 1;
1033 double x0 = -4. - m_EtaMax + (8. + 2. * m_EtaMax) *
randgenMT.randDblExc();
1034 double y0 = m_MaxYs[ind] *
randgenMT.randDblExc();
1035 if (y0 < m_dndy[ind].f(x0)) {
1040 return std::make_pair(tpt, ty);
1043 std::pair<double, double> SSHMomentumGenerator::GetRandom2(
double mass)
const {
1044 double tpt = 0., ty = 0., teta = 0.;
1047 double y0 = m_MaxPt *
randgenMT.randDblExc();
1054 int ind = (int)(exp(-tpt) / m_dPt);
1055 if (ind < 0) ind = 0;
1056 if (ind >= static_cast<int>(m_dndy.size())) ind = m_dndy.size() - 1;
1057 double x0 = -4. + (8.) *
randgenMT.randDblExc();
1058 double y0 = m_MaxYs[ind] *
randgenMT.randDblExc();
1060 if (y0 < m_dndy[ind].f(x0)) {
1062 teta = -m_EtaMax + 2. * m_EtaMax *
randgenMT.randDblExc();
1066 return std::make_pair(tpt, ty - teta);
1070 std::vector<double> ret(0);
1071 std::pair<double, double> pty = GetRandom2(mass);
1072 double tpt = pty.first;
1073 double ty = pty.second;
1075 ret.push_back(tpt * cos(tphi));
1076 ret.push_back(tpt * sin(tphi));
1077 ret.push_back(sqrt(tpt * tpt + m_Mass * m_Mass) * sinh(ty));
int RandomPoisson(double mean)
Generates random integer distributed by Poisson with specified mean Uses randgenMT.
virtual void FixParameters()
Computes some auxiliary stuff needed for sampling.
virtual double tanhetaperp(double zeta) const
static int RandomBesselCombined(double a, int nu, MTRand &rangen)
static double sig2(double a, int nu)
static double R(double x, int nu)
Class implementing a simple linear spline.
virtual double f(double M) const
Unnormalized resonance mass probability density.
static double Q2(double a, int nu)
static int RandomBesselDevroye2(double a, int nu, MTRand &rangen)
virtual double ZetaProbability(double zeta) const
Proportional to probability of having given value.
static int RandomBesselDevroye1(double a, int nu, MTRand &rangen)
void SetParameters(ThermalParticle *part, double T, double Mu)
Sets the parameters of the distribution.
virtual double dtaudZeta(double zeta) const
d/d
double BesselIexp(int n, double x)
Contains some extra mathematical functions used in the code.
void SetSeed(const unsigned int seed)
Set the seed of the random number generator randgenMT.
double BesselI(int n, double x)
integer order modified Bessel function I_n(x)
virtual double InverseZetaDistribution(double xi) const
Inverse function of variable distribution used in random number generation.
virtual double f(double M) const
Unnormalized resonance mass probability density.
MTRand randgenMT
The Mersenne Twister random number generator.
virtual double ProbabilityMaximum()
Class containing all information about a particle specie.
static int RandomBesselNormal(double a, int nu, MTRand &rangen)
virtual std::vector< double > GetMomentum(double mass=-1.) const
static double pn(int n, double a, int nu)
Structure holding information about a single particle in the event generator.
virtual void FixParameters()
Computes some auxiliary stuff needed for sampling.
virtual ~BoostInvariantMomentumGenerator()
BoostInvariantMomentumGenerator desctructor.
double SkellamProbability(int k, double mu1, double mu2)
Probability of a Skellam distributed random variable with Poisson means mu1 and mu2 to have the value...
virtual std::vector< double > GetMomentum(double mass=-1.) const
BoostInvariantMomentumGenerator(BoostInvariantFreezeoutParametrization *FreezeoutModel=NULL, double Tkin=0.100, double etamax=3.0, double mass=0.938, int statistics=0, double mu=0)
Construct a new BoostInvariantMomentumGenerator object.
std::vector< double > GetMomentum(double mass=-1.) const
virtual std::vector< double > GetMomentum(double mass=-1.) const
virtual double dRdZeta(double zeta) const
dR/d
static double chi2(double a, int nu)
double GetRandom() const
Samples the resonance mass from a relativistic Breit-Wigner distribution with a constant width...
Base class implementing a longitudinally boost-invariant azimuthally symmetric freeze-out parametriza...
double pz
3-momentum components (in GeV)
double GetRandom() const
Samples the mass.
virtual bool InverseZetaDistributionIsExplicit() const
Samples zeta for use in Monte Carlo event generator.
virtual double GetRandomZeta(MTRand &rangen=RandomGenerators::randgenMT) const
Samples zeta for use in Monte Carlo event generator.
virtual double sinhetaperp(double zeta) const
static double pmXmOverpm(int X, int tm, double a, int nu)
static int RandomBesselPoisson(double a, int nu, MTRand &rangen)
double GetP(double mass=-1.) const
Samples the momentum of a particle.
virtual double coshetaperp(double zeta) const
SimpleParticle LorentzBoost(const SimpleParticle &part, double vx, double vy, double vz)
Lorentz boost of the 4-momentum of a particle.
The main namespace where all classes and functions of the Thermal-FIST library reside.
static int RandomBesselDevroye3(double a, int nu, MTRand &rangen)
void SetParameters(double M, double gamma, double mthr)
Set the Breit-Wigner spectral function parameters.