Repository: commons-math Updated Branches: refs/heads/MATH_3_X 2983ff81b -> c9c252bf2
MATH-1300 Backport of changes originally introduced in "master" branch. Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/c9c252bf Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/c9c252bf Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/c9c252bf Branch: refs/heads/MATH_3_X Commit: c9c252bf26165e7fafd093cd892af35b23aa8f3f Parents: 2983ff8 Author: Gilles <er...@apache.org> Authored: Fri Jan 1 00:18:12 2016 +0100 Committer: Gilles <er...@apache.org> Committed: Fri Jan 1 00:18:12 2016 +0100 ---------------------------------------------------------------------- .../math3/random/BitsStreamGenerator.java | 112 +++++++++++++++---- 1 file changed, 93 insertions(+), 19 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-math/blob/c9c252bf/src/main/java/org/apache/commons/math3/random/BitsStreamGenerator.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/random/BitsStreamGenerator.java b/src/main/java/org/apache/commons/math3/random/BitsStreamGenerator.java index dcb000f..9f7cb56 100644 --- a/src/main/java/org/apache/commons/math3/random/BitsStreamGenerator.java +++ b/src/main/java/org/apache/commons/math3/random/BitsStreamGenerator.java @@ -19,6 +19,7 @@ package org.apache.commons.math3.random; import java.io.Serializable; import org.apache.commons.math3.exception.NotStrictlyPositiveException; +import org.apache.commons.math3.exception.OutOfRangeException; import org.apache.commons.math3.util.FastMath; /** Base class for random number generators that generates bits streams. @@ -66,25 +67,6 @@ public abstract class BitsStreamGenerator } /** {@inheritDoc} */ - public void nextBytes(byte[] bytes) { - int i = 0; - final int iEnd = bytes.length - 3; - while (i < iEnd) { - final int random = next(32); - bytes[i] = (byte) (random & 0xff); - bytes[i + 1] = (byte) ((random >> 8) & 0xff); - bytes[i + 2] = (byte) ((random >> 16) & 0xff); - bytes[i + 3] = (byte) ((random >> 24) & 0xff); - i += 4; - } - int random = next(32); - while (i < bytes.length) { - bytes[i++] = (byte) (random & 0xff); - random >>= 8; - } - } - - /** {@inheritDoc} */ public double nextDouble() { final long high = ((long) next(26)) << 26; final int low = next(26); @@ -194,4 +176,96 @@ public abstract class BitsStreamGenerator nextGaussian = Double.NaN; } + /** + * Generates random bytes and places them into a user-supplied array. + * + * <p> + * The array is filled with bytes extracted from random integers. + * This implies that the number of random bytes generated may be larger than + * the length of the byte array. + * </p> + * + * @param bytes Array in which to put the generated bytes. Cannot be {@code null}. + */ + @Override + public void nextBytes(byte[] bytes) { + nextBytesFill(bytes, 0, bytes.length); + } + + /** + * Generates random bytes and places them into a user-supplied array. + * + * <p> + * The array is filled with bytes extracted from random integers. + * This implies that the number of random bytes generated may be larger than + * the length of the byte array. + * </p> + * + * @param bytes Array in which to put the generated bytes. Cannot be {@code null}. + * @param start Index at which to start inserting the generated bytes. + * @param len Number of bytes to insert. + * @throws OutOfRangeException if {@code start < 0} or {@code start >= bytes.length}. + * @throws OutOfRangeException if {@code len < 0} or {@code len > bytes.length - start}. + */ + public void nextBytes(byte[] bytes, + int start, + int len) { + if (start < 0 || + start >= bytes.length) { + throw new OutOfRangeException(start, 0, bytes.length); + } + if (len < 0 || + len > bytes.length - start) { + throw new OutOfRangeException(len, 0, bytes.length - start); + } + + nextBytesFill(bytes, start, len); + } + + /** + * Generates random bytes and places them into a user-supplied array. + * + * <p> + * The array is filled with bytes extracted from random integers. + * This implies that the number of random bytes generated may be larger than + * the length of the byte array. + * </p> + * + * @param bytes Array in which to put the generated bytes. Cannot be {@code null}. + * @param start Index at which to start inserting the generated bytes. + * @param len Number of bytes to insert. + */ + private void nextBytesFill(byte[] bytes, + int start, + int len) { + int index = start; // Index of first insertion. + + // Index of first insertion plus multiple 4 part of length (i.e. length + // with two least significant bits unset). + final int indexLoopLimit = index + (len & 0x7ffffffc); + + // Start filling in the byte array, 4 bytes at a time. + while (index < indexLoopLimit) { + final int random = next(32); + bytes[index++] = (byte) random; + bytes[index++] = (byte) (random >>> 8); + bytes[index++] = (byte) (random >>> 16); + bytes[index++] = (byte) (random >>> 24); + } + + final int indexLimit = start + len; // Index of last insertion + 1. + + // Fill in the remaining bytes. + if (index < indexLimit) { + int random = next(32); + while (true) { + bytes[index++] = (byte) random; + if (index < indexLimit) { + random >>>= 8; + } else { + break; + } + } + } + } }