in commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/FastLoadedDiceRollerDiscreteSampler.java [723:771]
private static FastLoadedDiceRollerDiscreteSampler createSampler(UniformRandomProvider rng,
long[] frequencies,
int[] offsets,
int[] indices,
BigInteger m) {
// Repeat the logic from createSampler(...) using extended arithmetic to test the bits
// ALGORITHM 5: PREPROCESS
// a == frequencies
// m = sum(a)
// h = leaf node count
// H = leaf node label (lH)
final int n = frequencies.length;
// k = ceil(log2(m))
final int k = m.subtract(BigInteger.ONE).bitLength();
// r = a(n+1) = 2^k - m
final BigInteger r = BigInteger.ONE.shiftLeft(k).subtract(m);
final int[] h = new int[k];
final int[] lH = new int[checkArraySize((n + 1L) * k)];
Arrays.fill(lH, NO_LABEL);
int d;
for (int j = 0; j < k; j++) {
final int shift = (k - 1) - j;
d = 0;
for (final int i : indices) {
// bool w ← (a[i] >> (k − 1) − j)) & 1
// h[j] = h[j] + w
// if w then:
if (testBit(frequencies[i], offsets[i], shift)) {
h[j]++;
// H[d][j] = i
lH[d * k + j] = i;
d++;
}
}
// process a(n+1) without extending the input frequencies array by 1
if (r.testBit(shift)) {
h[j]++;
lH[d * k + j] = n;
}
}
return new FLDRSampler(rng, n, k, h, lH);
}