in commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/LargeMeanPoissonSampler.java [156:185]
private LargeMeanPoissonSampler(double mean,
UniformRandomProvider rng) {
this.rng = rng;
gaussian = ZigguratSampler.NormalizedGaussian.of(rng);
exponential = ZigguratSampler.Exponential.of(rng);
// Plain constructor uses the uncached function.
factorialLog = NO_CACHE_FACTORIAL_LOG;
// Cache values used in the algorithm
lambda = Math.floor(mean);
logLambda = Math.log(lambda);
logLambdaFactorial = getFactorialLog((int) lambda);
delta = Math.sqrt(lambda * Math.log(32 * lambda / Math.PI + 1));
halfDelta = delta / 2;
sqrtLambdaPlusHalfDelta = Math.sqrt(lambda + halfDelta);
twolpd = 2 * lambda + delta;
c1 = 1 / (8 * lambda);
final double a1 = Math.sqrt(Math.PI * twolpd) * Math.exp(c1);
final double a2 = (twolpd / delta) * Math.exp(-delta * (1 + delta) / twolpd);
final double aSum = a1 + a2 + 1;
p1 = a1 / aSum;
p2 = a2 / aSum;
// The algorithm requires a Poisson sample from the remaining lambda fraction.
final double lambdaFractional = mean - lambda;
smallMeanPoissonSampler = (lambdaFractional < Double.MIN_VALUE) ?
NO_SMALL_MEAN_POISSON_SAMPLER : // Not used.
KempSmallMeanPoissonSampler.of(rng, lambdaFractional);
}