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 java.io.Serializable;
|
||||||
|
|
||||||
import org.apache.commons.math3.exception.NotStrictlyPositiveException;
|
import org.apache.commons.math3.exception.NotStrictlyPositiveException;
|
||||||
|
import org.apache.commons.math3.exception.OutOfRangeException;
|
||||||
import org.apache.commons.math3.util.FastMath;
|
import org.apache.commons.math3.util.FastMath;
|
||||||
|
|
||||||
/** Base class for random number generators that generates bits streams.
|
/** Base class for random number generators that generates bits streams.
|
||||||
|
@ -65,25 +66,6 @@ public abstract class BitsStreamGenerator
|
||||||
return next(1) != 0;
|
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} */
|
/** {@inheritDoc} */
|
||||||
public double nextDouble() {
|
public double nextDouble() {
|
||||||
final long high = ((long) next(26)) << 26;
|
final long high = ((long) next(26)) << 26;
|
||||||
|
@ -194,4 +176,96 @@ public abstract class BitsStreamGenerator
|
||||||
nextGaussian = Double.NaN;
|
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