in commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/LargeMeanPoissonSampler.java [126:162]
public LargeMeanPoissonSampler(UniformRandomProvider rng,
double mean) {
if (mean < 1) {
throw new IllegalArgumentException("mean is not >= 1: " + mean);
}
// The algorithm is not valid if Math.floor(mean) is not an integer.
if (mean > MAX_MEAN) {
throw new IllegalArgumentException("mean " + mean + " > " + MAX_MEAN);
}
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);
}