Delegate to ArraySampler for shuffle
diff --git a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/ArraySampler.java b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/ArraySampler.java
index 9be2de4..8688670 100644
--- a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/ArraySampler.java
+++ b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/ArraySampler.java
@@ -16,6 +16,7 @@
*/
package org.apache.commons.rng.sampling;
+import java.util.List;
import org.apache.commons.rng.UniformRandomProvider;
/**
@@ -269,6 +270,34 @@
}
/**
+ * Shuffles the entries of the given list.
+ *
+ * <p>Note: This method is intentionally package-private.
+ *
+ * <p>This method exists to allow the shuffle performed by the {@link ListSampler} to
+ * match the {@link PermutationSampler} and {@link ArraySampler}.
+ *
+ * @param <T> Type of the items.
+ * @param rng Source of randomness.
+ * @param array Array whose entries will be shuffled (in-place).
+ */
+ static <T> void shuffle(UniformRandomProvider rng, List<T> array) {
+ int i = array.size();
+ for (; i > BATCH_2; --i) {
+ swap(array, i - 1, rng.nextInt(i));
+ }
+ // Batches of 2
+ final int[] productBound = {i * (i - 1)};
+ for (; i > 1; i -= 2) {
+ final int[] indices = randomBounded2(i, i - 1, productBound, rng);
+ final int index1 = indices[0];
+ final int index2 = indices[1];
+ swap(array, i - 1, index1);
+ swap(array, i - 2, index2);
+ }
+ }
+
+ /**
* Shuffles the entries of the given array in the range {@code [from, to)}.
*
* @param rng Source of randomness.
@@ -629,6 +658,19 @@
array[j] = tmp;
}
+ /**
+ * Swaps the two specified elements in the list.
+ *
+ * @param <T> Type of the list items.
+ * @param list List.
+ * @param i First index.
+ * @param j Second index.
+ */
+ private static <T> void swap(List<T> list, int i, int j) {
+ final T tmp = list.get(i);
+ list.set(i, list.get(j));
+ list.set(j, tmp);
+ }
/**
* Return two random values in {@code [0, range1)} and {@code [0, range2)}. The
diff --git a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/ListSampler.java b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/ListSampler.java
index 638b66d..9d7a860 100644
--- a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/ListSampler.java
+++ b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/ListSampler.java
@@ -98,15 +98,11 @@
List<T> list) {
if (list instanceof RandomAccess || list.size() < RANDOM_ACCESS_SIZE_THRESHOLD) {
// Shuffle list in-place
- for (int i = list.size(); i > 1; i--) {
- swap(list, i - 1, rng.nextInt(i));
- }
+ ArraySampler.shuffle(rng, list);
} else {
// Shuffle as an array
final Object[] array = list.toArray();
- for (int i = array.length; i > 1; i--) {
- swap(array, i - 1, rng.nextInt(i));
- }
+ ArraySampler.shuffle(rng, array);
// Copy back. Use raw types.
final ListIterator it = list.listIterator();
@@ -150,31 +146,4 @@
shuffle(rng, list.subList(start, list.size()));
}
}
-
- /**
- * Swaps the two specified elements in the list.
- *
- * @param <T> Type of the list items.
- * @param list List.
- * @param i First index.
- * @param j Second index.
- */
- private static <T> void swap(List<T> list, int i, int j) {
- final T tmp = list.get(i);
- list.set(i, list.get(j));
- list.set(j, tmp);
- }
-
- /**
- * Swaps the two specified elements in the array.
- *
- * @param array Array.
- * @param i First index.
- * @param j Second index.
- */
- private static void swap(Object[] array, int i, int j) {
- final Object tmp = array[i];
- array[i] = array[j];
- array[j] = tmp;
- }
}
diff --git a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/PermutationSampler.java b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/PermutationSampler.java
index 4fb8d1d..d715cf0 100644
--- a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/PermutationSampler.java
+++ b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/PermutationSampler.java
@@ -79,7 +79,6 @@
/**
* @return a random permutation.
- *
* @see #PermutationSampler(UniformRandomProvider,int,int)
*/
@Override
@@ -100,14 +99,13 @@
/**
* Shuffles the entries of the given array.
*
- * @see #shuffle(UniformRandomProvider,int[],int,boolean)
- *
* @param rng Random number generator.
* @param list Array whose entries will be shuffled (in-place).
+ * @see #shuffle(UniformRandomProvider,int[],int,boolean)
*/
public static void shuffle(UniformRandomProvider rng,
int[] list) {
- shuffle(rng, list, list.length - 1, true);
+ ArraySampler.shuffle(rng, list);
}
/**
@@ -117,7 +115,7 @@
* The {@code start} and {@code towardHead} parameters select which part
* of the array is randomized and which is left untouched.
*
- * <p>Sampling uses {@link UniformRandomProvider#nextInt(int)}.</p>
+ * <p>Sampling uses {@link UniformRandomProvider#nextInt()}.</p>
*
* @param rng Random number generator.
* @param list Array whose entries will be shuffled (in-place).
@@ -132,19 +130,10 @@
boolean towardHead) {
if (towardHead) {
// Visit all positions from start to 0.
- // Do not visit 0 to avoid a swap with itself.
- for (int i = start; i > 0; i--) {
- // Swap index with any position down to 0
- SubsetSamplerUtils.swap(list, i, rng.nextInt(i + 1));
- }
+ ArraySampler.shuffle(rng, list, 0, start + 1);
} else {
// Visit all positions from the end to start.
- // Start is not visited to avoid a swap with itself.
- for (int i = list.length - 1; i > start; i--) {
- // Swap index with any position down to start.
- // Note: i - start + 1 is the number of elements remaining.
- SubsetSamplerUtils.swap(list, i, rng.nextInt(i - start + 1) + start);
- }
+ ArraySampler.shuffle(rng, list, start, list.length);
}
}
diff --git a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/SubsetSamplerUtils.java b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/SubsetSamplerUtils.java
index efac8d1..9133ed6 100644
--- a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/SubsetSamplerUtils.java
+++ b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/SubsetSamplerUtils.java
@@ -93,7 +93,7 @@
* @param i the first index
* @param j the second index
*/
- static void swap(int[] array, int i, int j) {
+ private static void swap(int[] array, int i, int j) {
final int tmp = array[i];
array[i] = array[j];
array[j] = tmp;