MATH-1300
Backport of changes originally introduced in "master" branch.
This commit is contained in:
parent
2983ff81b1
commit
c9c252bf26
|
@ -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.
|
||||
|
@ -65,25 +66,6 @@ public abstract class BitsStreamGenerator
|
|||
return next(1) != 0;
|
||||
}
|
||||
|
||||
/** {@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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue