This is an automated email from the ASF dual-hosted git repository.

aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-rng.git

commit c10923949f78855c1bb567e05de034f43ef2cbb9
Author: Alex Herbert <[email protected]>
AuthorDate: Thu Mar 17 21:48:56 2022 +0000

    RNG-169: Move all conversions to the Conversions class
    
    Remove use of instances of SeedConverter as the conversion is stateless.
---
 .../rng/simple/internal/ByteArray2IntArray.java    |  29 +--
 .../rng/simple/internal/ByteArray2LongArray.java   |  29 +--
 .../commons/rng/simple/internal/Conversions.java   | 187 +++++++++++++++--
 .../commons/rng/simple/internal/Int2Long.java      |   2 +-
 .../commons/rng/simple/internal/IntArray2Int.java  |   7 +-
 .../rng/simple/internal/IntArray2LongArray.java    |  29 +--
 .../commons/rng/simple/internal/Long2IntArray.java |   4 +-
 .../rng/simple/internal/Long2LongArray.java        |   4 +-
 .../rng/simple/internal/LongArray2IntArray.java    |  30 +--
 .../rng/simple/internal/LongArray2Long.java        |   7 +-
 .../rng/simple/internal/NativeSeedType.java        |  40 ++--
 .../rng/simple/internal/ConversionsTest.java       | 225 +++++++++++++++++----
 .../rng/simple/internal/NativeSeedTypeTest.java    |  53 +++--
 13 files changed, 417 insertions(+), 229 deletions(-)

diff --git 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/ByteArray2IntArray.java
 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/ByteArray2IntArray.java
index 832c08c..68f1bdf 100644
--- 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/ByteArray2IntArray.java
+++ 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/ByteArray2IntArray.java
@@ -26,7 +26,7 @@ public class ByteArray2IntArray implements 
Seed2ArrayConverter<byte[], int[]> {
     @Override
     public int[] convert(byte[] seed) {
         // Full length conversion
-        return convertSeed(seed, SeedUtils.intSizeFromByteSize(seed.length));
+        return Conversions.byteArray2IntArray(seed, 
SeedUtils.intSizeFromByteSize(seed.length));
     }
 
     /**
@@ -36,31 +36,6 @@ public class ByteArray2IntArray implements 
Seed2ArrayConverter<byte[], int[]> {
      */
     @Override
     public int[] convert(byte[] seed, int outputSize) {
-        return convertSeed(seed, outputSize);
-    }
-
-    /**
-     * Creates an array of {@code int} values from a sequence of bytes. The 
integers are
-     * filled in little-endian order (least significant byte first).
-     *
-     * @param input Input bytes
-     * @param length Output length
-     * @return an array of {@code int}.
-     */
-    private static int[] convertSeed(byte[] input, int length) {
-        final int[] output = new int[length];
-
-        // Overflow-safe minimum using long
-        final int n = (int) Math.min(input.length, length * (long) 
Integer.BYTES);
-        // Little-endian fill
-        for (int i = 0; i < n; i++) {
-            // i              = byte index
-            // i >> 2         = integer index
-            // i & 0x3        = byte number in the integer  [0, 3]
-            // (i & 0x3) << 3 = little-endian byte shift to the integer {0, 8, 
16, 24}
-            output[i >> 2] |= (input[i] & 0xff) << ((i & 0x3) << 3);
-        }
-
-        return output;
+        return Conversions.byteArray2IntArray(seed, outputSize);
     }
 }
diff --git 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/ByteArray2LongArray.java
 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/ByteArray2LongArray.java
index 6369f00..4f2957d 100644
--- 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/ByteArray2LongArray.java
+++ 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/ByteArray2LongArray.java
@@ -26,7 +26,7 @@ public class ByteArray2LongArray implements 
Seed2ArrayConverter<byte[], long[]>
     @Override
     public long[] convert(byte[] seed) {
         // Full length conversion
-        return convertSeed(seed, SeedUtils.longSizeFromByteSize(seed.length));
+        return Conversions.byteArray2LongArray(seed, 
SeedUtils.longSizeFromByteSize(seed.length));
     }
 
     /**
@@ -36,31 +36,6 @@ public class ByteArray2LongArray implements 
Seed2ArrayConverter<byte[], long[]>
      */
     @Override
     public long[] convert(byte[] seed, int outputSize) {
-        return convertSeed(seed, outputSize);
-    }
-
-    /**
-     * Creates an array of {@code long} values from a sequence of bytes. The 
longs are
-     * filled in little-endian order (least significant byte first).
-     *
-     * @param input Input bytes
-     * @param length Output length
-     * @return an array of {@code long}.
-     */
-    private static long[] convertSeed(byte[] input, int length) {
-        final long[] output = new long[length];
-
-        // Overflow-safe minimum using long
-        final int n = (int) Math.min(input.length, length * (long) Long.BYTES);
-        // Little-endian fill
-        for (int i = 0; i < n; i++) {
-            // i              = byte index
-            // i >> 3         = long index
-            // i & 0x7        = byte number in the long  [0, 7]
-            // (i & 0x7) << 3 = little-endian byte shift to the long {0, 8, 
16, 24, 32, 36, 40, 48, 56}
-            output[i >> 3] |= (input[i] & 0xffL) << ((i & 0x7) << 3);
-        }
-
-        return output;
+        return Conversions.byteArray2LongArray(seed, outputSize);
     }
 }
diff --git 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/Conversions.java
 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/Conversions.java
index 140f59d..6a82627 100644
--- 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/Conversions.java
+++ 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/Conversions.java
@@ -63,7 +63,7 @@ final class Conversions {
      * @param input Input
      * @return a {@code long}.
      */
-    static long int2long(int input) {
+    static long int2Long(int input) {
         return stafford13(input + GOLDEN_RATIO);
     }
 
@@ -77,8 +77,8 @@ final class Conversions {
      * @param length Array length
      * @return an {@code int[]}.
      */
-    static int[] int2intArray(int input, int length) {
-        return long2intArray(input, length);
+    static int[] int2IntArray(int input, int length) {
+        return long2IntArray(input, length);
     }
 
     /**
@@ -90,8 +90,8 @@ final class Conversions {
      * @param length Array length
      * @return a {@code long[]}.
      */
-    static long[] int2longArray(int input, int length) {
-        return long2longArray(input, length);
+    static long[] int2LongArray(int input, int length) {
+        return long2LongArray(input, length);
     }
 
     /**
@@ -101,7 +101,7 @@ final class Conversions {
      * @param input Input
      * @return an {@code int}.
      */
-    static int long2int(long input) {
+    static int long2Int(long input) {
         return (int) input ^ (int) (input >>> 32);
     }
 
@@ -115,7 +115,7 @@ final class Conversions {
      * @param length Array length
      * @return an {@code int[]}.
      */
-    static int[] long2intArray(long input, int length) {
+    static int[] long2IntArray(long input, int length) {
         long v = input;
         final int[] output = new int[length];
         // Process pairs
@@ -141,7 +141,7 @@ final class Conversions {
      * @param length Array length
      * @return a {@code long}.
      */
-    static long[] long2longArray(long input, int length) {
+    static long[] long2LongArray(long input, int length) {
         long v = input;
         final long[] output = new long[length];
         for (int i = 0; i < length; i++) {
@@ -151,6 +151,124 @@ final class Conversions {
     }
 
     /**
+     * Creates an {@code int} value from a sequence of ints. The conversion
+     * is made by combining all the longs with a xor operation.
+     *
+     * @param input Input bytes
+     * @return an {@code int}.
+     */
+    static int intArray2Int(int[] input) {
+        int output = 0;
+        for (final int i : input) {
+            output ^= i;
+        }
+        return output;
+    }
+
+    /**
+     * Creates a {@code long} value from a sequence of ints. The conversion
+     * is made as if converting to a {@code long[]} array by filling the longs
+     * in little-endian order (least significant byte first), then combining
+     * all the longs with a xor operation.
+     *
+     * @param input Input bytes
+     * @return a {@code long}.
+     */
+    static long intArray2Long(int[] input) {
+        long output = 0;
+
+        final int n = input.length;
+        // xor in the bits to a long in little-endian order
+        for (int i = 0; i < n; i++) {
+            // i              = int index
+            // i >> 1         = long index
+            // i & 0x1        = int number in the long  [0, 1]
+            // (i & 0x1) << 5 = little-endian byte shift to the long {0, 32}
+            output ^= (input[i] & 0xffffffffL) << ((i & 0x1) << 5);
+        }
+
+        return output;
+    }
+
+    /**
+     * Creates a {@code long[]} value from a sequence of ints. The longs are
+     * filled in little-endian order (least significant byte first).
+     *
+     * @param input Input ints
+     * @param length Output array length
+     * @return a {@code long[]}.
+     */
+    static long[] intArray2LongArray(int[] input, int length) {
+        final long[] output = new long[length];
+
+        // Overflow-safe minimum using long
+        final int n = (int) Math.min(input.length, length * 2L);
+        // Little-endian fill
+        for (int i = 0; i < n; i++) {
+            // i              = int index
+            // i >> 1         = long index
+            // i & 0x1        = int number in the long  [0, 1]
+            // (i & 0x1) << 5 = little-endian byte shift to the long {0, 32}
+            output[i >> 1] |= (input[i] & 0xffffffffL) << ((i & 0x1) << 5);
+        }
+
+        return output;
+    }
+
+    /**
+     * Creates an {@code int} value from a sequence of longs. The conversion
+     * is made as if combining all the longs with a xor operation, then folding
+     * the long high and low parts using a xor operation.
+     *
+     * @param input Input longs
+     * @return an {@code int}.
+     */
+    static int longArray2Int(long[] input) {
+        return Conversions.long2Int(longArray2Long(input));
+    }
+
+    /**
+     * Creates a {@code long} value from a sequence of longs. The conversion
+     * is made by combining all the longs with a xor operation.
+     *
+     * @param input Input longs
+     * @return a {@code long}.
+     */
+    static long longArray2Long(long[] input) {
+        long output = 0;
+        for (final long i : input) {
+            output ^= i;
+        }
+        return output;
+    }
+
+    /**
+     * Creates a {@code int[]} value from a sequence of longs. The ints are
+     * filled in little-endian order (least significant byte first).
+     *
+     * @param input Input longs
+     * @param length Output array length
+     * @return an {@code int[]}.
+     */
+    static int[] longArray2IntArray(long[] input, int length) {
+        final int[] output = new int[length];
+
+        // Overflow-safe minimum using long
+        final int n = (int) Math.min(input.length * 2L, length);
+        // Little-endian fill
+        // Alternate low/high 32-bits from each long
+        for (int i = 0; i < n; i++) {
+            // i              = int index
+            // i >> 1         = long index
+            // i & 0x1        = int number in the long  [0, 1]
+            // (i & 0x1) << 5 = little-endian long shift to the int {0, 32}
+            output[i] = (int)((input[i >> 1]) >>> ((i & 0x1) << 5));
+        }
+
+        return output;
+    }
+
+    /**
      * Creates an {@code int} value from a sequence of bytes. The conversion
      * is made as if converting to a {@code int[]} array by filling the ints
      * in little-endian order (least significant byte first), then combining
@@ -176,6 +294,31 @@ final class Conversions {
     }
 
     /**
+     * Creates an {@code int[]} value from a sequence of bytes. The ints are
+     * filled in little-endian order (least significant byte first).
+     *
+     * @param input Input bytes
+     * @param length Output array length
+     * @return a {@code int[]}.
+     */
+    static int[] byteArray2IntArray(byte[] input, int length) {
+        final int[] output = new int[length];
+
+        // Overflow-safe minimum using long
+        final int n = (int) Math.min(input.length, length * (long) 
Integer.BYTES);
+        // Little-endian fill
+        for (int i = 0; i < n; i++) {
+            // i              = byte index
+            // i >> 2         = integer index
+            // i & 0x3        = byte number in the integer  [0, 3]
+            // (i & 0x3) << 3 = little-endian byte shift to the integer {0, 8, 
16, 24}
+            output[i >> 2] |= (input[i] & 0xff) << ((i & 0x3) << 3);
+        }
+
+        return output;
+    }
+
+    /**
      * Creates a {@code long} value from a sequence of bytes. The conversion
      * is made as if converting to a {@code long[]} array by filling the longs
      * in little-endian order (least significant byte first), then combining
@@ -201,25 +344,25 @@ final class Conversions {
     }
 
     /**
-     * Creates a {@code long} value from a sequence of ints. The conversion
-     * is made as if converting to a {@code long[]} array by filling the longs
-     * in little-endian order (least significant byte first), then combining
-     * all the longs with a xor operation.
+     * Creates a {@code long[]} value from a sequence of bytes. The longs are
+     * filled in little-endian order (least significant byte first).
      *
      * @param input Input bytes
-     * @return a {@code long}.
+     * @param length Output array length
+     * @return a {@code long[]}.
      */
-    static long intArray2Long(int[] input) {
-        long output = 0;
+    static long[] byteArray2LongArray(byte[] input, int length) {
+        final long[] output = new long[length];
 
-        final int n = input.length;
-        // xor in the bits to a long in little-endian order
+        // Overflow-safe minimum using long
+        final int n = (int) Math.min(input.length, length * (long) Long.BYTES);
+        // Little-endian fill
         for (int i = 0; i < n; i++) {
-            // i              = int index
-            // i >> 1         = long index
-            // i & 0x1        = int number in the long  [0, 1]
-            // (i & 0x1) << 5 = little-endian byte shift to the long {0, 32}
-            output ^= (input[i] & 0xffffffffL) << ((i & 0x1) << 5);
+            // i              = byte index
+            // i >> 3         = long index
+            // i & 0x7        = byte number in the long  [0, 7]
+            // (i & 0x7) << 3 = little-endian byte shift to the long {0, 8, 
16, 24, 32, 36, 40, 48, 56}
+            output[i >> 3] |= (input[i] & 0xffL) << ((i & 0x7) << 3);
         }
 
         return output;
diff --git 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/Int2Long.java
 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/Int2Long.java
index cd1c207..9f23a64 100644
--- 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/Int2Long.java
+++ 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/Int2Long.java
@@ -25,6 +25,6 @@ public class Int2Long implements SeedConverter<Integer, Long> 
{
     /** {@inheritDoc} */
     @Override
     public Long convert(Integer seed) {
-        return Conversions.int2long(seed);
+        return Conversions.int2Long(seed);
     }
 }
diff --git 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/IntArray2Int.java
 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/IntArray2Int.java
index 4899258..af742d0 100644
--- 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/IntArray2Int.java
+++ 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/IntArray2Int.java
@@ -25,11 +25,6 @@ public class IntArray2Int implements SeedConverter<int[], 
Integer> {
     /** {@inheritDoc} */
     @Override
     public Integer convert(int[] seed) {
-        int out = 0;
-        for (final int s : seed) {
-            out ^= s;
-        }
-
-        return out;
+        return Conversions.intArray2Int(seed);
     }
 }
diff --git 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/IntArray2LongArray.java
 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/IntArray2LongArray.java
index c557235..46fbe6e 100644
--- 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/IntArray2LongArray.java
+++ 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/IntArray2LongArray.java
@@ -30,7 +30,7 @@ public class IntArray2LongArray implements 
Seed2ArrayConverter<int[], long[]> {
     @Override
     public long[] convert(int[] seed) {
         // Full length conversion
-        return convertSeed(seed, SeedUtils.longSizeFromIntSize(seed.length));
+        return Conversions.intArray2LongArray(seed, 
SeedUtils.longSizeFromIntSize(seed.length));
     }
 
     /**
@@ -40,31 +40,6 @@ public class IntArray2LongArray implements 
Seed2ArrayConverter<int[], long[]> {
      */
     @Override
     public long[] convert(int[] seed, int outputSize) {
-        return convertSeed(seed, outputSize);
-    }
-
-    /**
-     * Creates an array of {@code long} values from a sequence of ints. The 
longs are
-     * filled in little-endian order (least significant byte first).
-     *
-     * @param input Input bytes
-     * @param length Output length
-     * @return an array of {@code long}.
-     */
-    private static long[] convertSeed(int[] input, int length) {
-        final long[] output = new long[length];
-
-        // Overflow-safe minimum using long
-        final int n = (int) Math.min(input.length, length * 2L);
-        // Little-endian fill
-        for (int i = 0; i < n; i++) {
-            // i              = int index
-            // i >> 1         = long index
-            // i & 0x1        = int number in the long  [0, 1]
-            // (i & 0x1) << 5 = little-endian byte shift to the long {0, 32}
-            output[i >> 1] |= (input[i] & 0xffffffffL) << ((i & 0x1) << 5);
-        }
-
-        return output;
+        return Conversions.intArray2LongArray(seed, outputSize);
     }
 }
diff --git 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/Long2IntArray.java
 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/Long2IntArray.java
index 352ca50..4b78632 100644
--- 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/Long2IntArray.java
+++ 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/Long2IntArray.java
@@ -38,7 +38,7 @@ public class Long2IntArray implements 
Seed2ArrayConverter<Long, int[]> {
     /** {@inheritDoc} */
     @Override
     public int[] convert(Long seed) {
-        return Conversions.long2intArray(seed, size);
+        return Conversions.long2IntArray(seed, size);
     }
 
     /**
@@ -48,6 +48,6 @@ public class Long2IntArray implements 
Seed2ArrayConverter<Long, int[]> {
      */
     @Override
     public int[] convert(Long seed, int outputSize) {
-        return Conversions.long2intArray(seed, outputSize);
+        return Conversions.long2IntArray(seed, outputSize);
     }
 }
diff --git 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/Long2LongArray.java
 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/Long2LongArray.java
index 1806ca9..652e08c 100644
--- 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/Long2LongArray.java
+++ 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/Long2LongArray.java
@@ -39,7 +39,7 @@ public class Long2LongArray implements 
Seed2ArrayConverter<Long, long[]> {
     /** {@inheritDoc} */
     @Override
     public long[] convert(Long seed) {
-        return Conversions.long2longArray(seed, size);
+        return Conversions.long2LongArray(seed, size);
     }
 
     /**
@@ -49,6 +49,6 @@ public class Long2LongArray implements 
Seed2ArrayConverter<Long, long[]> {
      */
     @Override
     public long[] convert(Long seed, int outputSize) {
-        return Conversions.long2longArray(seed, outputSize);
+        return Conversions.long2LongArray(seed, outputSize);
     }
 }
diff --git 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/LongArray2IntArray.java
 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/LongArray2IntArray.java
index d33f4ea..c35e10b 100644
--- 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/LongArray2IntArray.java
+++ 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/LongArray2IntArray.java
@@ -29,7 +29,7 @@ public class LongArray2IntArray implements 
Seed2ArrayConverter<long[], int[]> {
     @Override
     public int[] convert(long[] seed) {
         // Full length conversion
-        return convertSeed(seed, SeedUtils.intSizeFromLongSize(seed.length));
+        return Conversions.longArray2IntArray(seed, 
SeedUtils.intSizeFromLongSize(seed.length));
     }
 
     /**
@@ -39,32 +39,6 @@ public class LongArray2IntArray implements 
Seed2ArrayConverter<long[], int[]> {
      */
     @Override
     public int[] convert(long[] seed, int outputSize) {
-        return convertSeed(seed, outputSize);
-    }
-
-    /**
-     * Creates an array of {@code int} values from a sequence of bytes. The 
integers are
-     * filled in little-endian order (least significant byte first).
-     *
-     * @param input Input bytes
-     * @param length Output length
-     * @return an array of {@code int}.
-     */
-    private static int[] convertSeed(long[] input, int length) {
-        final int[] output = new int[length];
-
-        // Overflow-safe minimum using long
-        final int n = (int) Math.min(input.length * 2L, length);
-        // Little-endian fill
-        // Alternate low/high 32-bits from each long
-        for (int i = 0; i < n; i++) {
-            // i              = int index
-            // i >> 1         = long index
-            // i & 0x1        = int number in the long  [0, 1]
-            // (i & 0x1) << 5 = little-endian long shift to the int {0, 32}
-            output[i] = (int)((input[i >> 1]) >>> ((i & 0x1) << 5));
-        }
-
-        return output;
+        return Conversions.longArray2IntArray(seed, outputSize);
     }
 }
diff --git 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/LongArray2Long.java
 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/LongArray2Long.java
index 67abb1a..39257a3 100644
--- 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/LongArray2Long.java
+++ 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/LongArray2Long.java
@@ -25,11 +25,6 @@ public class LongArray2Long implements SeedConverter<long[], 
Long> {
     /** {@inheritDoc} */
     @Override
     public Long convert(long[] seed) {
-        long out = 0;
-        for (final long s : seed) {
-            out ^= s;
-        }
-
-        return out;
+        return Conversions.longArray2Long(seed);
     }
 }
diff --git 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/NativeSeedType.java
 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/NativeSeedType.java
index 6ccc436..494ff1c 100644
--- 
a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/NativeSeedType.java
+++ 
b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/NativeSeedType.java
@@ -54,15 +54,15 @@ public enum NativeSeedType {
         }
         @Override
         protected Integer convert(Long seed, int size) {
-            return Conversions.long2int(seed);
+            return Conversions.long2Int(seed);
         }
         @Override
         protected Integer convert(int[] seed, int size) {
-            return INT_ARRAY_TO_INT.convert(seed);
+            return Conversions.intArray2Int(seed);
         }
         @Override
         protected Integer convert(long[] seed, int size) {
-            return LONG_TO_INT.convert(LONG_ARRAY_TO_LONG.convert(seed));
+            return Conversions.longArray2Int(seed);
         }
         @Override
         protected Integer convert(byte[] seed, int size) {
@@ -77,7 +77,7 @@ public enum NativeSeedType {
         }
         @Override
         protected Long convert(Integer seed, int size) {
-            return Conversions.int2long(seed);
+            return Conversions.int2Long(seed);
         }
         @Override
         protected Long convert(Long seed, int size) {
@@ -89,7 +89,7 @@ public enum NativeSeedType {
         }
         @Override
         protected Long convert(long[] seed, int size) {
-            return LONG_ARRAY_TO_LONG.convert(seed);
+            return Conversions.longArray2Long(seed);
         }
         @Override
         protected Long convert(byte[] seed, int size) {
@@ -106,11 +106,11 @@ public enum NativeSeedType {
         }
         @Override
         protected int[] convert(Integer seed, int size) {
-            return Conversions.int2intArray(seed, size);
+            return Conversions.int2IntArray(seed, size);
         }
         @Override
         protected int[] convert(Long seed, int size) {
-            return Conversions.long2intArray(seed, size);
+            return Conversions.long2IntArray(seed, size);
         }
         @Override
         protected int[] convert(int[] seed, int size) {
@@ -119,13 +119,13 @@ public enum NativeSeedType {
         @Override
         protected int[] convert(long[] seed, int size) {
             // Avoid zero filling seeds that are too short
-            return LONG_ARRAY_TO_INT_ARRAY.convert(seed,
+            return Conversions.longArray2IntArray(seed,
                 Math.min(size, SeedUtils.intSizeFromLongSize(seed.length)));
         }
         @Override
         protected int[] convert(byte[] seed, int size) {
             // Avoid zero filling seeds that are too short
-            return BYTE_ARRAY_TO_INT_ARRAY.convert(seed,
+            return Conversions.byteArray2IntArray(seed,
                 Math.min(size, SeedUtils.intSizeFromByteSize(seed.length)));
         }
     },
@@ -139,16 +139,16 @@ public enum NativeSeedType {
         }
         @Override
         protected long[] convert(Integer seed, int size) {
-            return Conversions.int2longArray(seed, size);
+            return Conversions.int2LongArray(seed, size);
         }
         @Override
         protected long[] convert(Long seed, int size) {
-            return Conversions.long2longArray(seed, size);
+            return Conversions.long2LongArray(seed, size);
         }
         @Override
         protected long[] convert(int[] seed, int size) {
             // Avoid zero filling seeds that are too short
-            return INT_ARRAY_TO_LONG_ARRAY.convert(seed,
+            return Conversions.intArray2LongArray(seed,
                 Math.min(size, SeedUtils.longSizeFromIntSize(seed.length)));
         }
         @Override
@@ -158,7 +158,7 @@ public enum NativeSeedType {
         @Override
         protected long[] convert(byte[] seed, int size) {
             // Avoid zero filling seeds that are too short
-            return BYTE_ARRAY_TO_LONG_ARRAY.convert(seed,
+            return Conversions.byteArray2LongArray(seed,
                 Math.min(size, SeedUtils.longSizeFromByteSize(seed.length)));
         }
     };
@@ -167,20 +167,6 @@ public enum NativeSeedType {
     private static final String UNRECOGNISED_SEED = "Unrecognized seed type: ";
     /** Maximum length of the seed array (for creating array seeds). */
     private static final int RANDOM_SEED_ARRAY_SIZE = 128;
-    /** Convert {@code Long} to {@code Integer}. */
-    private static final Long2Int LONG_TO_INT = new Long2Int();
-    /** Convert {@code long[]} to {@code Long}. */
-    private static final LongArray2Long LONG_ARRAY_TO_LONG = new 
LongArray2Long();
-    /** Convert {@code int[]} to {@code Integer}. */
-    private static final IntArray2Int INT_ARRAY_TO_INT = new IntArray2Int();
-    /** Convert {@code long[]} to {@code int[]}. */
-    private static final LongArray2IntArray LONG_ARRAY_TO_INT_ARRAY = new 
LongArray2IntArray();
-    /** Convert {@code Long} to {@code long[]}. */
-    private static final IntArray2LongArray INT_ARRAY_TO_LONG_ARRAY = new 
IntArray2LongArray();
-    /** Convert {@code byte[]} to {@code int[]}. */
-    private static final ByteArray2IntArray BYTE_ARRAY_TO_INT_ARRAY = new 
ByteArray2IntArray();
-    /** Convert {@code byte[]} to {@code long[]}. */
-    private static final ByteArray2LongArray BYTE_ARRAY_TO_LONG_ARRAY = new 
ByteArray2LongArray();
 
     /** Define the class type of the native seed. */
     private final Class<?> type;
diff --git 
a/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/ConversionsTest.java
 
b/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/ConversionsTest.java
index 840eefd..b2eef2c 100644
--- 
a/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/ConversionsTest.java
+++ 
b/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/ConversionsTest.java
@@ -52,18 +52,27 @@ class ConversionsTest {
         return IntStream.rangeClosed(0, (Long.BYTES / Integer.BYTES) * 2);
     }
 
+    /**
+     * Gets the lengths for the long[] seeds to convert.
+     *
+     * @return the lengths
+     */
+    static IntStream getLongLengths() {
+        return IntStream.rangeClosed(0, 2);
+    }
+
     @RepeatedTest(value = 5)
     void testInt2Long() {
         final int v = ThreadLocalRandom.current().nextInt();
-        Assertions.assertEquals(new SplitMix64(v).nextLong(), 
Conversions.int2long(v));
+        Assertions.assertEquals(new SplitMix64(v).nextLong(), 
Conversions.int2Long(v));
     }
 
     @RepeatedTest(value = 5)
     void testInt2IntArray() {
         final int v = ThreadLocalRandom.current().nextInt();
         getIntLengths().forEach(len -> {
-            Assertions.assertArrayEquals(Conversions.long2intArray(v, len),
-                                         Conversions.int2intArray(v, len));
+            Assertions.assertArrayEquals(Conversions.long2IntArray(v, len),
+                                         Conversions.int2IntArray(v, len));
         });
     }
 
@@ -71,12 +80,12 @@ class ConversionsTest {
     void testInt2LongArray() {
         final int v = ThreadLocalRandom.current().nextInt();
         getIntLengths().forEach(len -> {
-            final long[] a = Conversions.int2longArray(v, len);
-            Assertions.assertArrayEquals(Conversions.long2longArray(v, len), 
a);
+            final long[] a = Conversions.int2LongArray(v, len);
+            Assertions.assertArrayEquals(Conversions.long2LongArray(v, len), 
a);
             if (len != 0) {
                 // Special case of expansion to length 1
                 // Expandion is done by mixing
-                Assertions.assertEquals(Conversions.int2long(v), a[0]);
+                Assertions.assertEquals(Conversions.int2Long(v), a[0]);
             }
         });
     }
@@ -84,7 +93,7 @@ class ConversionsTest {
     @RepeatedTest(value = 5)
     void testLong2Int() {
         final long v = ThreadLocalRandom.current().nextLong();
-        Assertions.assertEquals(NumberFactory.makeInt(v), 
Conversions.long2int(v));
+        Assertions.assertEquals(NumberFactory.makeInt(v), 
Conversions.long2Int(v));
     }
 
     @RepeatedTest(value = 5)
@@ -101,7 +110,7 @@ class ConversionsTest {
                 expected[i] = bb.getInt();
             }
             Assertions.assertArrayEquals(expected,
-                Conversions.long2intArray(v, len));
+                Conversions.long2IntArray(v, len));
 
             // Note:
             // long -> int[] position[0] != long -> int
@@ -114,12 +123,131 @@ class ConversionsTest {
         final long v = ThreadLocalRandom.current().nextLong();
         getIntLengths().forEach(len -> {
             Assertions.assertArrayEquals(LongStream.generate(new 
SplitMix64(v)::nextLong).limit(len).toArray(),
-                Conversions.long2longArray(v, len));
+                Conversions.long2LongArray(v, len));
         });
     }
 
     @ParameterizedTest
     @MethodSource(value = {"getIntLengths"})
+    void testIntArray2Int(int ints) {
+        final int[] seed = ThreadLocalRandom.current().ints(ints).toArray();
+        // xor all the bytes
+        int expected = 0;
+        for (final int i : seed) {
+            expected ^= i;
+        }
+        Assertions.assertEquals(expected, Conversions.intArray2Int(seed));
+    }
+
+    @ParameterizedTest
+    @MethodSource(value = {"getIntLengths"})
+    void testIntArray2Long(int ints) {
+        final int[] seed = ThreadLocalRandom.current().ints(ints).toArray();
+
+        // int[] -> long[] -> long
+        // Concatenate all ints in little-endian order to bytes
+        final int outLength = SeedUtils.longSizeFromIntSize(ints);
+        final int[] filledSeed = Arrays.copyOf(seed, outLength * 2);
+        final ByteBuffer bb = ByteBuffer.allocate(filledSeed.length * 
Integer.BYTES)
+                .order(ByteOrder.LITTLE_ENDIAN);
+        Arrays.stream(filledSeed).forEach(bb::putInt);
+        // xor all the bytes read as longs
+        long expected = 0;
+        bb.flip();
+        for (int i = outLength; i-- != 0;) {
+            final long l = bb.getLong();
+            expected ^= l;
+        }
+
+        Assertions.assertEquals(expected, Conversions.intArray2Long(seed));
+    }
+
+    @ParameterizedTest
+    @MethodSource(value = {"getIntLengths"})
+    void testIntArray2LongComposed(int ints) {
+        final int[] seed = ThreadLocalRandom.current().ints(ints).toArray();
+        final long expected = new LongArray2Long().convert(new 
IntArray2LongArray().convert(seed));
+        Assertions.assertEquals(expected, Conversions.intArray2Long(seed));
+    }
+
+    @ParameterizedTest
+    @MethodSource(value = {"getIntLengths"})
+    void testIntArray2LongArray(int ints) {
+        final int[] seed = ThreadLocalRandom.current().ints(ints).toArray();
+
+        // Concatenate all bytes in little-endian order to bytes
+        final int outLength = SeedUtils.longSizeFromIntSize(ints);
+        final ByteBuffer bb = ByteBuffer.allocate(outLength * Long.BYTES)
+                .order(ByteOrder.LITTLE_ENDIAN);
+        Arrays.stream(seed).forEach(bb::putInt);
+        bb.clear();
+        final long[] expected = new long[outLength];
+        for (int i = 0; i < outLength; i++) {
+            expected[i] = bb.getLong();
+        }
+
+        Assertions.assertArrayEquals(expected, 
Conversions.intArray2LongArray(seed, outLength));
+        // Zero fill
+        Assertions.assertArrayEquals(Arrays.copyOf(expected, outLength * 2),
+            Conversions.intArray2LongArray(seed, outLength * 2));
+        // Truncation
+        for (int i = 0; i < outLength; i++) {
+            Assertions.assertArrayEquals(Arrays.copyOf(expected, i), 
Conversions.intArray2LongArray(seed, i));
+        }
+    }
+
+    @ParameterizedTest
+    @MethodSource(value = {"getLongLengths"})
+    void testLongArray2Int(long longs) {
+        final long[] seed = ThreadLocalRandom.current().longs(longs).toArray();
+        // xor all the bytes
+        long expected = 0;
+        for (final long i : seed) {
+            expected ^= i;
+        }
+        Assertions.assertEquals((int) (expected ^ expected >>> 32), 
Conversions.longArray2Int(seed));
+    }
+
+    @ParameterizedTest
+    @MethodSource(value = {"getLongLengths"})
+    void testLongArray2Long(long longs) {
+        final long[] seed = ThreadLocalRandom.current().longs(longs).toArray();
+        // xor all the bytes
+        long expected = 0;
+        for (final long i : seed) {
+            expected ^= i;
+        }
+        Assertions.assertEquals(expected, Conversions.longArray2Long(seed));
+    }
+
+    @ParameterizedTest
+    @MethodSource(value = {"getLongLengths"})
+    void testLongArray2IntArray(int longs) {
+        final long[] seed = ThreadLocalRandom.current().longs(longs).toArray();
+
+        // Concatenate all bytes in little-endian order to bytes
+        final int outLength = SeedUtils.intSizeFromLongSize(longs);
+        final ByteBuffer bb = ByteBuffer.allocate(longs * Long.BYTES)
+                .order(ByteOrder.LITTLE_ENDIAN);
+        Arrays.stream(seed).forEach(bb::putLong);
+        bb.clear();
+        final int[] expected = new int[outLength];
+        for (int i = 0; i < outLength; i++) {
+            expected[i] = bb.getInt();
+        }
+
+        Assertions.assertArrayEquals(expected, 
Conversions.longArray2IntArray(seed, outLength));
+        // Zero fill
+        Assertions.assertArrayEquals(Arrays.copyOf(expected, outLength * 2),
+            Conversions.longArray2IntArray(seed, outLength * 2));
+        // Truncation
+        for (int i = 0; i < outLength; i++) {
+            Assertions.assertArrayEquals(Arrays.copyOf(expected, i), 
Conversions.longArray2IntArray(seed, i));
+        }
+    }
+
+    @ParameterizedTest
+    @MethodSource(value = {"getByteLengths"})
     void testByteArray2Int(int bytes) {
         final byte[] seed = new byte[bytes];
         ThreadLocalRandom.current().nextBytes(seed);
@@ -133,7 +261,7 @@ class ConversionsTest {
         // xor all the bytes read as ints
         int expected = 0;
         for (int i = outLength; i-- != 0;) {
-            long l = bb.getInt();
+            final long l = bb.getInt();
             expected ^= l;
         }
 
@@ -141,7 +269,7 @@ class ConversionsTest {
     }
 
     @ParameterizedTest
-    @MethodSource(value = {"getIntLengths"})
+    @MethodSource(value = {"getByteLengths"})
     void testByteArray2IntComposed(int bytes) {
         final byte[] seed = new byte[bytes];
         ThreadLocalRandom.current().nextBytes(seed);
@@ -150,7 +278,33 @@ class ConversionsTest {
     }
 
     @ParameterizedTest
-    @MethodSource(value = {"getIntLengths"})
+    @MethodSource(value = {"getByteLengths"})
+    void testByteArray2IntArray(int bytes) {
+        final byte[] seed = new byte[bytes];
+        ThreadLocalRandom.current().nextBytes(seed);
+
+        // Concatenate all bytes in little-endian order to bytes
+        final int outLength = SeedUtils.intSizeFromByteSize(bytes);
+        final byte[] filledSeed = Arrays.copyOf(seed, outLength * 
Integer.BYTES);
+        final ByteBuffer bb = ByteBuffer.wrap(filledSeed)
+                .order(ByteOrder.LITTLE_ENDIAN);
+        final int[] expected = new int[outLength];
+        for (int i = 0; i < outLength; i++) {
+            expected[i] = bb.getInt();
+        }
+
+        Assertions.assertArrayEquals(expected, 
Conversions.byteArray2IntArray(seed, outLength));
+        // Zero fill
+        Assertions.assertArrayEquals(Arrays.copyOf(expected, outLength * 2),
+            Conversions.byteArray2IntArray(seed, outLength * 2));
+        // Truncation
+        for (int i = 0; i < outLength; i++) {
+            Assertions.assertArrayEquals(Arrays.copyOf(expected, i), 
Conversions.byteArray2IntArray(seed, i));
+        }
+    }
+
+    @ParameterizedTest
+    @MethodSource(value = {"getByteLengths"})
     void testByteArray2Long(int bytes) {
         final byte[] seed = new byte[bytes];
         ThreadLocalRandom.current().nextBytes(seed);
@@ -164,7 +318,7 @@ class ConversionsTest {
         // xor all the bytes read as longs
         long expected = 0;
         for (int i = outLength; i-- != 0;) {
-            long l = bb.getLong();
+            final long l = bb.getLong();
             expected ^= l;
         }
 
@@ -172,7 +326,7 @@ class ConversionsTest {
     }
 
     @ParameterizedTest
-    @MethodSource(value = {"getIntLengths"})
+    @MethodSource(value = {"getByteLengths"})
     void testByteArray2LongComposed(int bytes) {
         final byte[] seed = new byte[bytes];
         ThreadLocalRandom.current().nextBytes(seed);
@@ -181,33 +335,28 @@ class ConversionsTest {
     }
 
     @ParameterizedTest
-    @MethodSource(value = {"getIntLengths"})
-    void testIntArray2Long(int ints) {
-        final int[] seed = ThreadLocalRandom.current().ints(ints).toArray();
+    @MethodSource(value = {"getByteLengths"})
+    void testByteArray2LongArray(int bytes) {
+        final byte[] seed = new byte[bytes];
+        ThreadLocalRandom.current().nextBytes(seed);
 
-        // int[] -> long[] -> long
-        // Concatenate all ints in little-endian order to bytes
-        final int outLength = SeedUtils.longSizeFromIntSize(ints);
-        final int[] filledSeed = Arrays.copyOf(seed, outLength * 2);
-        final ByteBuffer bb = ByteBuffer.allocate(filledSeed.length * 
Integer.BYTES)
+        // Concatenate all bytes in little-endian order to bytes
+        final int outLength = SeedUtils.longSizeFromByteSize(bytes);
+        final byte[] filledSeed = Arrays.copyOf(seed, outLength * Long.BYTES);
+        final ByteBuffer bb = ByteBuffer.wrap(filledSeed)
                 .order(ByteOrder.LITTLE_ENDIAN);
-        Arrays.stream(filledSeed).forEach(bb::putInt);
-        // xor all the bytes read as longs
-        long expected = 0;
-        bb.flip();
-        for (int i = outLength; i-- != 0;) {
-            long l = bb.getLong();
-            expected ^= l;
+        final long[] expected = new long[outLength];
+        for (int i = 0; i < outLength; i++) {
+            expected[i] = bb.getLong();
         }
 
-        Assertions.assertEquals(expected, Conversions.intArray2Long(seed));
-    }
-
-    @ParameterizedTest
-    @MethodSource(value = {"getIntLengths"})
-    void testIntArray2LongComposed(int ints) {
-        final int[] seed = ThreadLocalRandom.current().ints(ints).toArray();
-        final long expected = new LongArray2Long().convert(new 
IntArray2LongArray().convert(seed));
-        Assertions.assertEquals(expected, Conversions.intArray2Long(seed));
+        Assertions.assertArrayEquals(expected, 
Conversions.byteArray2LongArray(seed, outLength));
+        // Zero fill
+        Assertions.assertArrayEquals(Arrays.copyOf(expected, outLength * 2),
+            Conversions.byteArray2LongArray(seed, outLength * 2));
+        // Truncation
+        for (int i = 0; i < outLength; i++) {
+            Assertions.assertArrayEquals(Arrays.copyOf(expected, i), 
Conversions.byteArray2LongArray(seed, i));
+        }
     }
 }
diff --git 
a/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/NativeSeedTypeTest.java
 
b/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/NativeSeedTypeTest.java
index c81b51e..41ae3dc 100644
--- 
a/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/NativeSeedTypeTest.java
+++ 
b/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/NativeSeedTypeTest.java
@@ -23,6 +23,7 @@ import java.util.Arrays;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.stream.IntStream;
 import java.util.stream.LongStream;
+import org.apache.commons.rng.core.source64.SplitMix64;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -35,49 +36,69 @@ import org.junit.jupiter.params.provider.MethodSource;
  * <p>Note: All supported types are tested in the {@link 
NativeSeedTypeParametricTest}.
  */
 class NativeSeedTypeTest {
-    /** Convert {@code Integer} to {@code Long}. */
-    private static final Int2Long INT_TO_LONG = new Int2Long();
-    /** Convert {@code Long} to {@code int[]}. */
-    private static final Long2IntArray LONG_TO_INT_ARRAY = new 
Long2IntArray(0);
-    /** Convert {@code Long} to {@code long[]}. */
-    private static final Long2LongArray LONG_TO_LONG_ARRAY = new 
Long2LongArray(0);
-
     /**
      * Perform the reference int to long conversion.
      * This may change between release versions.
-     * The reference implementation is in the Int2Long converter.
+     * The reference implementation is to create a long using a SplitMix64 
generator.
      *
      * @param v Value
      * @return the result
      */
     private static long int2long(int v) {
-        return INT_TO_LONG.convert(v);
+        return new SplitMix64(v).nextLong();
     }
 
     /**
      * Perform the reference long to int[] conversion.
      * This may change between release versions.
-     * The reference implementation is in the Long2IntArray converter.
+     * The reference implementation is to create a long[] using a SplitMix64 
generator
+     * and split each into an int, least significant bytes first.
      *
      * @param v Value
      * @param length Array length
      * @return the result
      */
     private static int[] long2intArray(long v, int length) {
-        return LONG_TO_INT_ARRAY.convert(v, length);
+        class LoHiSplitMix64 extends SplitMix64 {
+            /** Cache part of the most recently generated long value.
+             * Store the upper 32-bits from nextLong() in the lower half
+             * and all zero bits in the upper half when cached.
+             * Set to -1 when empty and requires a refill. */
+            private long next = -1;
+
+            LoHiSplitMix64(long seed) {
+                super(seed);
+            }
+
+            @Override
+            public int nextInt() {
+                long l = next;
+                if (l < 0) {
+                    l = nextLong();
+                    // Reserve the upper 32-bits
+                    next = l >>> 32;
+                    // Return the lower 32-bits
+                    return (int) l;
+                }
+                // Clear cache and return the previous upper 32-bits
+                next = -1;
+                return (int) l;
+            }
+        }
+        return IntStream.generate(new 
LoHiSplitMix64(v)::nextInt).limit(length).toArray();
     }
 
     /**
      * Perform the reference long to long[] conversion.
      * This may change between release versions.
-     * The reference implementation is in the Long2LongArray converter.
+     * The reference implementation is to create a long[] using a SplitMix64 
generator.
      *
      * @param v Value
      * @param length Array length
      * @return the result
      */
     private static long[] long2longArray(long v, int length) {
-        return LONG_TO_LONG_ARRAY.convert(v, length);
+        return LongStream.generate(new 
SplitMix64(v)::nextLong).limit(length).toArray();
     }
 
     /**
@@ -273,11 +294,11 @@ class NativeSeedTypeTest {
     // - Native seed types are passed through with no change
     // - long to int conversion uses hi ^ lo
     // - int to long conversion expands the bits.
-    //   The Int2Long converter is the reference implementation.
+    //   Creating a long using a SplitMix64 is the reference implementation.
     // - long to long[] conversion seeds a RNG then expands.
-    //   The Long2LongArray converter is the reference implementation.
+    //   Filling using a SplitMix64 is the reference implementation.
     // - long to int[] conversion seeds a RNG then expands.
-    //   The Long2IntArray converter is the reference implementation.
+    //   Filling using a SplitMix64 is the reference implementation.
     // - Primitive expansion should produce equivalent output bits
     //   for all larger output seed types,
     //   i.e. int -> long == int -> int[0]+int[1] == int -> long[0]

Reply via email to