in commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/MarsagliaTsangWangDiscreteSampler.java [777:808]
private static SharedStateDiscreteSampler createPoissonDistributionFromX0(
UniformRandomProvider rng, double mean) {
final double p0 = Math.exp(-mean);
// Recursive update of Poisson probability until the value is too small
// p(x + 1) = p(x) * mean / (x + 1)
double p = p0;
int i = 1;
while (p * DOUBLE_31 >= 1) {
p *= mean / i++;
}
// Probabilities are 30-bit integers, assumed denominator 2^30
final int size = i - 1;
final int[] prob = new int[size];
p = p0;
prob[0] = toUnsignedInt30(p);
// The sum must exceed 2^30. In edges cases this is false due to round-off.
int sum = prob[0];
for (i = 1; i < prob.length; i++) {
p *= mean / i;
prob[i] = toUnsignedInt30(p);
sum += prob[i];
}
// If the sum is < 2^30 add the remaining sum to the mode (floor(mean)).
prob[(int) mean] += Math.max(0, INT_30 - sum);
// Note: offset = 0
return createSampler(rng, POISSON_NAME, prob, 0);
}