in commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/SeedFactory.java [354:400]
static void ensureNonZero(byte[] seed, int from, int to, UniformRandomProvider source) {
if (from >= to) {
return;
}
// No check on the range so an IndexOutOfBoundsException will occur if invalid
for (int i = from; i < to; i++) {
if (seed[i] != 0) {
return;
}
}
// Defend against a faulty source of randomness (which supplied all zero bytes)
// by filling with non-zero values using a SplitMix-style PRNG seeded from the source.
// The range is at least 1.
// To ensure the first value is not zero requires the input to the mix function
// to be non-zero. This is ensured if the start is even since the increment is odd.
long x = source.nextLong() << 1;
// Process in blocks of 8.
// Get the length without the final 3 bits set for a multiple of 8.
final int len = (to - from) & ~0x7;
final int end = from + len;
int i = from;
while (i < end) {
long v = MixFunctions.stafford13(x += MixFunctions.GOLDEN_RATIO_64);
for (int j = 0; j < 8; j++) {
seed[i++] = (byte) v;
v >>>= 8;
}
}
if (i < to) {
// The final bytes.
long v = MixFunctions.stafford13(x + MixFunctions.GOLDEN_RATIO_64);
// Note the special case where no blocks have been processed requires these
// bytes to be non-zero, i.e. (to - from) < 8. In this case the value 'v' will
// be non-zero due to the initialisation of 'x' as even.
// Rotate the value so the least significant byte is non-zero. The rotation
// in bits is rounded down to the nearest 8-bit block to ensure a byte rotation.
if (len == 0) {
v = Long.rotateRight(v, Long.numberOfTrailingZeros(v) & ~0x7);
}
while (i < to) {
seed[i++] = (byte) v;
v >>>= 8;
}
}
}