/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
FastSimulation/Utilities/src/GammaFunctionGenerator.cc
126 строк
4 KB
Cms Build
Clang-Format
24 май 2019, 00:14
24 май 2019, 00:14
740c44a
Код
Авторство
О чём код?
//FAMOS headers #include "FastSimulation/Utilities/interface/GammaFunctionGenerator.h" #include "FastSimulation/Utilities/interface/RandomEngineAndDistribution.h" GammaFunctionGenerator::GammaFunctionGenerator() { xmax = 30.; for (unsigned i = 1; i <= 12; ++i) { // For all let's put the limit at 2.*(alpha-1) (alpha-1 is the max of the dist) approxLimit.push_back(2 * ((double)i)); myIncompleteGamma.a().setValue((double)i); integralToApproxLimit.push_back(myIncompleteGamma(approxLimit[i - 1])); theGammas.push_back(GammaNumericalGenerator((double)i, 1., 0, approxLimit[i - 1] + 1.)); } coreCoeff.push_back(0.); // alpha=1 not used coreCoeff.push_back(1. / 8.24659e-01); coreCoeff.push_back(1. / 7.55976e-01); coreCoeff.push_back(1. / 7.12570e-01); coreCoeff.push_back(1. / 6.79062e-01); coreCoeff.push_back(1. / 6.65496e-01); coreCoeff.push_back(1. / 6.48736e-01); coreCoeff.push_back(1. / 6.25185e-01); coreCoeff.push_back(1. / 6.09188e-01); coreCoeff.push_back(1. / 6.06221e-01); coreCoeff.push_back(1. / 6.05057e-01); } GammaFunctionGenerator::~GammaFunctionGenerator() {} double GammaFunctionGenerator::shoot(RandomEngineAndDistribution const* random) const { if (alpha < 0.) return -1.; if (badRange) return xmin / beta; if (alpha < 12) { if (alpha == na) { return gammaInt(random) / beta; } else if (na == 0) { return gammaFrac(random) / beta; } else { double gi = gammaInt(random); double gf = gammaFrac(random); return (gi + gf) / beta; } } else { // an other generator has to be used in such a case return -1.; } } double GammaFunctionGenerator::gammaFrac(RandomEngineAndDistribution const* random) const { /* This is exercise 16 from Knuth; see page 135, and the solution is on page 551. */ double p, q, x, u, v; p = M_E / (frac + M_E); do { u = random->flatShoot(); v = random->flatShoot(); if (u < p) { x = exp((1 / frac) * log(v)); q = exp(-x); } else { x = 1 - log(v); q = exp((frac - 1) * log(x)); } } while (random->flatShoot() >= q); return x; } double GammaFunctionGenerator::gammaInt(RandomEngineAndDistribution const* random) const { // Exponential distribution : no approximation if (na == 1) { return xmin - log(random->flatShoot()); } unsigned gn = na - 1; // are we sure to be in the tail if (coreProba == 0.) return xmin - coreCoeff[gn] * log(random->flatShoot()); // core-tail interval if (random->flatShoot() < coreProba) { return theGammas[gn].gamma_lin(random); } // std::cout << " Tail called " << std::endl; return approxLimit[gn] - coreCoeff[gn] * log(random->flatShoot()); } void GammaFunctionGenerator::setParameters(double a, double b, double xm) { // std::cout << "Setting parameters " << std::endl; alpha = a; beta = b; xmin = xm * beta; if (xm > xmax) { badRange = true; return; } badRange = false; na = 0; if (alpha > 0. && alpha < 12) na = (unsigned)floor(alpha); frac = alpha - na; // Now calculate the probability to shoot between approxLimit and xmax // The Incomplete gamma is normalized to 1 if (na <= 1) return; myIncompleteGamma.a().setValue((double)na); unsigned gn = na - 1; // std::cout << " na " << na << " xm " << xm << " beta " << beta << " xmin " << xmin << " approxLimit " << approxLimit[gn] << std::endl; if (xmin > approxLimit[gn]) { coreProba = 0.; } else { double tmp = (xmin != 0.) ? myIncompleteGamma(xmin) : 0.; coreProba = (integralToApproxLimit[gn] - tmp) / (1. - tmp); theGammas[gn].setSubInterval(xmin, approxLimit[gn]); } // std::cout << " Proba " << coreProba << std::endl; }