static void ensureNonZero()

in commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/SeedFactory.java [350:396]


    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;
            }
        }
    }