in commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/MarsagliaTsangWangDiscreteSampler.java [1114:1145]
private static SharedStateDiscreteSampler createBinomialDistributionSamplerFromRange(
UniformRandomProvider rng, int trials, double p,
boolean useInversion, double p0, int begin, int end) {
// Assign probability values as 30-bit integers
final int size = end - begin + 1;
final int[] prob = new int[size];
double t = p0;
final double h = p / (1 - p);
for (int i = 1; i <= begin; i++) {
t *= (trials + 1 - i) * h / i;
}
int sum = toUnsignedInt30(t);
prob[0] = sum;
for (int i = begin + 1; i <= end; i++) {
t *= (trials + 1 - i) * h / i;
prob[i - begin] = toUnsignedInt30(t);
sum += prob[i - begin];
}
// If the sum is < 2^30 add the remaining sum to the mode (floor((n+1)p))).
// If above 2^30 then the effect is truncation of the long tail of the distribution.
final int mode = (int) ((trials + 1) * p) - begin;
prob[mode] += Math.max(0, INT_30 - sum);
final SharedStateDiscreteSampler sampler = createSampler(rng, BINOMIAL_NAME, prob, begin);
// Check if an inversion was made
return useInversion ?
new MarsagliaTsangWangInversionBinomialSampler(trials, sampler) :
sampler;
}