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

Reply via email to