RNG-117: RandomSource to support creating byte[] seed for implementing class.

Added methods:

public byte[] createSeed();
public byte[] createSeed(UniformRandomProvider);
diff --git a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/RandomSource.java b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/RandomSource.java
index 62b83b3..e8048a4 100644
--- a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/RandomSource.java
+++ b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/RandomSource.java
@@ -490,6 +490,53 @@
     }
 
     /**
+     * Creates a seed suitable for the implementing class represented by this random source.
+     *
+     * <p>The seed will be created as if passing a {@code null} seed to the factory method
+     * {@link #create(RandomSource, Object, Object...)}. It will satisfy the seed size and any
+     * other seed requirements for the implementing class. The seed is converted from the native
+     * type to a byte representation.</p>
+     *
+     * <p>Usage example:</p>
+     * <pre><code>
+     *  RandomSource source = ...;
+     *  byte[] seed = source.createSeed();
+     *  UniformRandomProvider rng = RandomSource.create(source, seed);
+     * </code></pre>
+     *
+     * @return the seed
+     *
+     * @since 1.3
+     */
+    public byte[] createSeed() {
+        return internalIdentifier.createSeedBytes();
+    }
+
+    /**
+     * Creates a seed suitable for the implementing class represented by this random source
+     * using the supplied source of randomness.
+     *
+     * <p>The seed will satisfy the seed size and any other seed requirements for the
+     * implementing class.</p>
+     *
+     * <p>Usage example:</p>
+     * <pre><code>
+     *  RandomSource source = ...;
+     *  UniformRandomProvider seedRng = new JDKRandomWrapper(new SecureRandom());
+     *  byte[] seed = source.createSeed(seedRng);
+     *  UniformRandomProvider rng = RandomSource.create(source, seed);
+     * </code></pre>
+     *
+     * @param rng Source of randomness.
+     * @return the seed
+     *
+     * @since 1.3
+     */
+    public byte[] createSeed(UniformRandomProvider rng) {
+        return internalIdentifier.createSeedBytes(rng);
+    }
+
+    /**
      * Checks whether the implementing class represented by this random source
      * supports the {@link org.apache.commons.rng.JumpableUniformRandomProvider
      * JumpableUniformRandomProvider} interface. If {@code true} the instance returned
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 1db19ee..0fe9da5 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
@@ -16,6 +16,8 @@
  */
 package org.apache.commons.rng.simple.internal;
 
+import org.apache.commons.rng.core.util.NumberFactory;
+
 /**
  * The native seed type. Contains values for all native seed types and methods
  * to convert supported seed types to the native seed type.
@@ -41,7 +43,7 @@
  */
 public enum NativeSeedType {
     /** The seed type is {@code Integer}. */
-    INT(Integer.class) {
+    INT(Integer.class, 4) {
         @Override
         public Integer createSeed(int size) {
             return SeedFactory.createInt();
@@ -68,7 +70,7 @@
         }
     },
     /** The seed type is {@code Long}. */
-    LONG(Long.class) {
+    LONG(Long.class, 8) {
         @Override
         public Long createSeed(int size) {
             return SeedFactory.createLong();
@@ -95,7 +97,7 @@
         }
     },
     /** The seed type is {@code int[]}. */
-    INT_ARRAY(int[].class) {
+    INT_ARRAY(int[].class, 4) {
         @Override
         public int[] createSeed(int size) {
             // Limit the number of calls to the synchronized method. The generator
@@ -124,7 +126,7 @@
         }
     },
     /** The seed type is {@code long[]}. */
-    LONG_ARRAY(long[].class) {
+    LONG_ARRAY(long[].class, 8) {
         @Override
         public long[] createSeed(int size) {
             // Limit the number of calls to the synchronized method. The generator
@@ -153,6 +155,8 @@
         }
     };
 
+    /** Error message for unrecognised seed types. */
+    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}. */
@@ -180,10 +184,20 @@
     private final Class<?> type;
 
     /**
-     * @param type Define the class type of the native seed.
+     * Define the number of bytes required to represent the native seed. If the type is
+     * an array then this represents the size of a single value of the type.
      */
-    NativeSeedType(Class<?> type) {
+    private final int bytes;
+
+    /**
+     * Instantiates a new native seed type.
+     *
+     * @param type Define the class type of the native seed.
+     * @param bytes Define the number of bytes required to represent the native seed.
+     */
+    NativeSeedType(Class<?> type, int bytes) {
         this.type = type;
+        this.bytes = bytes;
     }
 
     /**
@@ -196,6 +210,16 @@
     }
 
     /**
+     * Gets the number of bytes required to represent the native seed type. If the type is
+     * an array then this represents the size of a single value of the type.
+     *
+     * @return the number of bytes
+     */
+    public int getBytes() {
+        return bytes;
+    }
+
+    /**
      * Creates the seed. The output seed type is determined by the native seed type. If the
      * output is an array the required size of the array can be specified.
      *
@@ -230,7 +254,7 @@
             return convert((byte[]) seed, size);
         }
 
-        throw new UnsupportedOperationException("Unrecognized seed type: " + seed);
+        throw new UnsupportedOperationException(UNRECOGNISED_SEED + seed);
     }
 
     /**
@@ -277,4 +301,27 @@
      * @return the native seed.
      */
     protected abstract Object convert(byte[] seed, int size);
+
+    /**
+     * Converts the input seed from any of the supported seed types to bytes.
+     *
+     * @param seed Input seed.
+     * @return the seed bytes.
+     * @throws UnsupportedOperationException if the {@code seed} type is invalid.
+     */
+    public static byte[] convertSeedToBytes(Object seed) {
+        if (seed instanceof Integer) {
+            return NumberFactory.makeByteArray((Integer) seed);
+        } else if (seed instanceof Long) {
+            return NumberFactory.makeByteArray((Long) seed);
+        } else if (seed instanceof int[]) {
+            return NumberFactory.makeByteArray((int[]) seed);
+        } else if (seed instanceof long[]) {
+            return NumberFactory.makeByteArray((long[]) seed);
+        } else if (seed instanceof byte[]) {
+            return (byte[]) seed;
+        }
+
+        throw new UnsupportedOperationException(UNRECOGNISED_SEED + seed);
+    }
 }
diff --git a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/ProviderBuilder.java b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/ProviderBuilder.java
index 59b9271..02af9fc 100644
--- a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/ProviderBuilder.java
+++ b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/ProviderBuilder.java
@@ -272,20 +272,35 @@
                 return super.convertSeed(seed);
             }
 
+            @Override
+            protected byte[] createByteArraySeed(UniformRandomProvider source) {
+                return NativeSeedType.convertSeedToBytes(createMswsSeed(source));
+            }
+
             /**
-             * Creates the full length seed array from the input seed using the method
-             * recommended for the generator. This is a high quality Weyl increment composed
-             * of a hex character permutation.
+             * Creates the full length seed array from the input seed.
              *
              * @param seed the seed
              * @return the seed array
              */
             private long[] createMswsSeed(long seed) {
-                final long increment = SeedUtils.createLongHexPermutation(new SplitMix64(seed));
+                return createMswsSeed(new SplitMix64(seed));
+            }
+
+            /**
+             * Creates the full length seed array from the input seed using the method
+             * recommended for the generator. This is a high quality Weyl increment composed
+             * of a hex character permutation.
+             *
+             * @param source Source of randomness.
+             * @return the seed array
+             */
+            private long[] createMswsSeed(UniformRandomProvider source) {
+                final long increment = SeedUtils.createLongHexPermutation(source);
                 // The initial state should not be low complexity but the Weyl
                 // state can be any number.
                 final long state = increment;
-                final long weylState = seed;
+                final long weylState = source.nextLong();
                 return new long[] {state, weylState, increment};
             }
         },
@@ -383,6 +398,16 @@
         }
 
         /**
+         * Gets the number of seed bytes required to seed the implementing class represented by
+         * this random source.
+         *
+         * @return the number of seed bytes
+         */
+        private int getSeedByteSize() {
+            return nativeSeedSize * nativeSeedType.getBytes();
+        }
+
+        /**
          * Creates a RNG instance.
          *
          * <p>This method can be over-ridden to allow fast construction of a generator
@@ -442,8 +467,10 @@
         /**
          * Creates a native seed.
          *
-         * <p>This method should be over-ridden to satisfy seed requirements for the generator,
-         * for example if a seed must contain non-zero bits.</p>
+         * <p>The default implementation creates a seed of the native type and, for array seeds,
+         * ensures not all bits are zero.</p>
+         *
+         * <p>This method should be over-ridden to satisfy seed requirements for the generator.</p>
          *
          * @return the native seed
          */
@@ -452,6 +479,21 @@
         }
 
         /**
+         * Creates a {@code byte[]} seed using the provided source of randomness.
+         *
+         * <p>The default implementation creates a full-length seed and ensures not all bits
+         * are zero.</p>
+         *
+         * <p>This method should be over-ridden to satisfy seed requirements for the generator.</p>
+         *
+         * @param source Source of randomness.
+         * @return the byte[] seed
+         */
+        protected byte[] createByteArraySeed(UniformRandomProvider source) {
+            return SeedFactory.createByteArray(source, getSeedByteSize());
+        }
+
+        /**
          * Converts a seed from any of the supported seed types to a native seed.
          *
          * @param seed Input seed (must not be null).
@@ -476,6 +518,39 @@
         }
 
         /**
+         * Creates a seed suitable for the implementing class represented by this random source.
+         *
+         * <p>It will satisfy the seed size and any other seed requirements for the
+         * implementing class. The seed is converted from the native type to bytes.</p>
+         *
+         * @return the seed bytes
+         *
+         * @since 1.3
+         */
+        public final byte[] createSeedBytes() {
+            // Custom implementations can override createSeed
+            final Object seed = createSeed();
+            return NativeSeedType.convertSeedToBytes(seed);
+        }
+
+        /**
+         * Creates a seed suitable for the implementing class represented by this random source
+         * using the supplied source of randomness.
+         *
+         * <p>It will satisfy the seed size and any other seed requirements for the
+         * implementing class. The seed is converted from the native type to bytes.</p>
+         *
+         * @param source Source of randomness.
+         * @return the seed bytes
+         *
+         * @since 1.3
+         */
+        public final byte[] createSeedBytes(UniformRandomProvider source) {
+            // Custom implementations can override createByteArraySeed
+            return createByteArraySeed(source);
+        }
+
+        /**
          * Gets the constructor.
          *
          * @return the RNG constructor.
@@ -492,6 +567,7 @@
             }
             return constructor;
         }
+
         /**
          * Creates a constructor.
          *
diff --git a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/SeedFactory.java b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/SeedFactory.java
index 170c978..4b336ea 100644
--- a/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/SeedFactory.java
+++ b/commons-rng-simple/src/main/java/org/apache/commons/rng/simple/internal/SeedFactory.java
@@ -203,6 +203,25 @@
     }
 
     /**
+     * Creates an array of {@code byte} numbers for use as a seed using the supplied source of
+     * randomness. The result will not be all zeros.
+     *
+     * @param source Source of randomness.
+     * @param n Size of the array to create.
+     * @return an array of {@code n} random numbers.
+     */
+    static byte[] createByteArray(UniformRandomProvider source,
+                                  int n) {
+        final byte[] seed = new byte[n];
+        source.nextBytes(seed);
+        // If the seed is zero it is assumed the input source RNG is either broken
+        // or the seed is small and it was zero by chance. Revert to the built-in
+        // source of randomness to ensure it is non-zero.
+        ensureNonZero(seed);
+        return seed;
+    }
+
+    /**
      * Ensure the seed is non-zero at the first position in the array.
      *
      * <p>This method will replace a zero at index 0 in the array with
@@ -243,6 +262,42 @@
     }
 
     /**
+     * Ensure the seed is not zero at all positions in the array.
+     *
+     * <p>This method will check all positions in the array and if all
+     * are zero it will replace index 0 in the array with
+     * a non-zero random number. The method ensures any length seed
+     * contains non-zero bits. The output seed is suitable for generators
+     * that cannot be seeded with all zeros.</p>
+     *
+     * @param seed Seed array (modified in place).
+     * @see #createInt()
+     */
+    private static void ensureNonZero(byte[] seed) {
+        // Since zero occurs 1 in 2^8 for a single byte this checks the entire array for zeros.
+        if (seed.length != 0 && isAllZero(seed)) {
+            do {
+                seed[0] = (byte) createInt();
+            } while (seed[0] == 0);
+        }
+    }
+
+    /**
+     * Test if each position in the array is zero.
+     *
+     * @param array Array data.
+     * @return true if all position are zero
+     */
+    private static boolean isAllZero(byte[] array) {
+        for (final byte value : array) {
+            if (value != 0) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
      * Ensure the value is non-zero.
      *
      * <p>This method will replace a zero with a non-zero random number from the random source.</p>
diff --git a/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/ProvidersCommonParametricTest.java b/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/ProvidersCommonParametricTest.java
index 4641937..aa403da 100644
--- a/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/ProvidersCommonParametricTest.java
+++ b/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/ProvidersCommonParametricTest.java
@@ -39,6 +39,7 @@
 import org.apache.commons.rng.RandomProviderState;
 import org.apache.commons.rng.RestorableUniformRandomProvider;
 import org.apache.commons.rng.core.RandomProviderDefaultState;
+import org.apache.commons.rng.core.source64.SplitMix64;
 
 /**
  * Tests which all generators must pass.
@@ -155,6 +156,20 @@
         checkNextIntegerInRange(rng, 10, 10000);
     }
 
+    @Test
+    public void testRandomSourceCreateSeed() {
+        final byte[] seed = originalSource.createSeed();
+        final UniformRandomProvider rng = RandomSource.create(originalSource, seed, originalArgs);
+        checkNextIntegerInRange(rng, 10, 10000);
+    }
+
+    @Test
+    public void testRandomSourceCreateSeedFromRNG() {
+        final byte[] seed = originalSource.createSeed(new SplitMix64(RandomSource.createLong()));
+        final UniformRandomProvider rng = RandomSource.create(originalSource, seed, originalArgs);
+        checkNextIntegerInRange(rng, 10, 10000);
+    }
+
     // State save and restore tests.
 
     @Test
diff --git a/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/NativeSeedTypeParametricTest.java b/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/NativeSeedTypeParametricTest.java
index 9a2ebf3..3913341 100644
--- a/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/NativeSeedTypeParametricTest.java
+++ b/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/NativeSeedTypeParametricTest.java
@@ -112,6 +112,28 @@
     }
 
     /**
+     * Test the seed can be created, converted to a byte[] and then back to the native type.
+     */
+    @Test
+    public void testConvertSeedToBytes() {
+        final int size = 3;
+        final Object seed = nativeSeedType.createSeed(size);
+        Assert.assertNotNull("Null seed", seed);
+
+        final byte[] bytes = NativeSeedType.convertSeedToBytes(seed);
+        Assert.assertNotNull("Null byte[] seed", bytes);
+
+        final Object seed2 = nativeSeedType.convertSeed(bytes, size);
+        if (type.isArray()) {
+            // This handles nested primitive arrays
+            Assert.assertArrayEquals("byte[] seed was not converted back",
+                                     new Object[] {seed}, new Object[] {seed2});
+        } else {
+            Assert.assertEquals("byte[] seed was not converted back", seed, seed2);
+        }
+    }
+
+    /**
      * Test the seed can be converted to the correct type from any of the supported input types.
      */
     @Test
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
new file mode 100644
index 0000000..be699ae
--- /dev/null
+++ b/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/NativeSeedTypeTest.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.rng.simple.internal;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests for the {@link NativeSeedType} factory seed conversions.
+ */
+public class NativeSeedTypeTest {
+    /**
+     * Test the conversion throws for an unsupported type. All supported types are
+     * tested in the {@link NativeSeedTypeParametricTest}.
+     */
+    @Test(expected = UnsupportedOperationException.class)
+    public void testConvertSeedToBytesUsingNullThrows() {
+        NativeSeedType.convertSeedToBytes(null);
+    }
+
+    /**
+     * Test the conversion passes through a byte[]. This hits the edge case of a seed
+     * that can be converted that is not a native type.
+     */
+    @Test
+    public void testConvertSeedToBytesUsingByteArray() {
+        final byte[] seed = {42, 78, 99};
+        Assert.assertSame(seed, NativeSeedType.convertSeedToBytes(seed));
+    }
+}
diff --git a/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/RandomSourceInternalParametricTest.java b/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/RandomSourceInternalParametricTest.java
index 69736f2..e58f4ff 100644
--- a/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/RandomSourceInternalParametricTest.java
+++ b/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/RandomSourceInternalParametricTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.commons.rng.simple.internal;
 
+import org.apache.commons.rng.core.source64.SplitMix64;
 import org.apache.commons.rng.simple.internal.ProviderBuilder.RandomSourceInternal;
 import org.junit.Assert;
 import org.junit.Test;
@@ -23,6 +24,8 @@
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
 
+import java.util.EnumMap;
+
 /**
  * Tests for the {@link ProviderBuilder.RandomSourceInternal} seed conversions. This test
  * ensures that all random sources can create a seed or convert any supported seed to the
@@ -43,6 +46,53 @@
         null,
         Double.valueOf(Math.PI),
     };
+    /** The expected byte size of the seed for each RandomSource. */
+    private static final EnumMap<RandomSourceInternal, Integer> EXPECTED_SEED_BYTES =
+            new EnumMap<RandomSourceInternal, Integer>(RandomSourceInternal.class);
+
+    static {
+        final int intBytes = 4;
+        final int longBytes = 8;
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.JDK, longBytes * 1);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.WELL_512_A, intBytes * 16);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.WELL_1024_A, intBytes * 32);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.WELL_19937_A, intBytes * 624);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.WELL_19937_C, intBytes * 624);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.WELL_44497_A, intBytes * 1391);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.WELL_44497_B, intBytes * 1391);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.MT, intBytes * 624);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.ISAAC, intBytes * 256);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.SPLIT_MIX_64, longBytes * 1);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.XOR_SHIFT_1024_S, longBytes * 16);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.TWO_CMRES, intBytes * 1);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.TWO_CMRES_SELECT, intBytes * 1);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.MT_64, longBytes * 312);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.MWC_256, intBytes * 257);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.KISS, intBytes * 4);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.XOR_SHIFT_1024_S_PHI, longBytes * 16);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.XO_RO_SHI_RO_64_S, intBytes * 2);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.XO_RO_SHI_RO_64_SS, intBytes * 2);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.XO_SHI_RO_128_PLUS, intBytes * 4);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.XO_SHI_RO_128_SS, intBytes * 4);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.XO_RO_SHI_RO_128_PLUS, longBytes * 2);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.XO_RO_SHI_RO_128_SS, longBytes * 2);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.XO_SHI_RO_256_PLUS, longBytes * 4);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.XO_SHI_RO_256_SS, longBytes * 4);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.XO_SHI_RO_512_PLUS, longBytes * 8);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.XO_SHI_RO_512_SS, longBytes * 8);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.PCG_XSH_RR_32, longBytes * 2);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.PCG_XSH_RS_32, longBytes * 2);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.PCG_RXS_M_XS_64, longBytes * 2);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.PCG_MCG_XSH_RR_32, longBytes * 1);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.PCG_MCG_XSH_RS_32, longBytes * 1);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.MSWS, longBytes * 3);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.SFC_32, intBytes * 3);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.SFC_64, longBytes * 3);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.JSF_32, intBytes * 1);
+        EXPECTED_SEED_BYTES.put(RandomSourceInternal.JSF_64, longBytes * 1);
+        // ... add more here.
+        // Verify the seed byte size is reflected in the enum javadoc for RandomSource.
+    }
 
     /** Internal identifier for the random source. */
     private final RandomSourceInternal randomSourceInternal;
@@ -109,4 +159,49 @@
             }
         }
     }
+
+    /**
+     * Test the seed byte size is reported as the size of a int/long primitive for Int/Long
+     * seed types and a multiple of it for int[]/long[] types.
+     */
+    @Test
+    public void testCreateSeedBytesSizeIsPositiveAndMultipleOf4Or8() {
+        // This should be the full length seed
+        final byte[] seed = randomSourceInternal.createSeedBytes(new SplitMix64(12345L));
+
+        final int size = seed.length;
+        Assert.assertNotEquals("Seed is empty", 0, size);
+
+        if (randomSourceInternal.isNativeSeed(Integer.valueOf(0))) {
+            Assert.assertEquals("Expect 4 bytes for Integer", 4, size);
+        } else if (randomSourceInternal.isNativeSeed(Long.valueOf(0))) {
+            Assert.assertEquals("Expect 8 bytes for Long", 8, size);
+        } else if (randomSourceInternal.isNativeSeed(new int[0])) {
+            Assert.assertEquals("Expect 4n bytes for int[]", 0, size % 4);
+        } else if (randomSourceInternal.isNativeSeed(new long[0])) {
+            Assert.assertEquals("Expect 8n bytes for long[]", 0, size % 8);
+        } else {
+            Assert.fail("Unknown native seed type");
+        }
+    }
+
+    /**
+     * Test the seed byte size against the expected value.
+     *
+     * <p>The expected values are maintained in a table and must be manually updated
+     * for new generators. This test forms an additional cross-reference check that the
+     * seed size in RandomSourceInternal has been correctly set and the size should map to
+     * the array size in the RandomSource javadoc (if applicable).
+     */
+    @Test
+    public void testCreateSeedBytes() {
+        // This should be the full length seed
+        final byte[] seed = randomSourceInternal.createSeedBytes(new SplitMix64(12345L));
+        final int size = seed.length;
+
+        final Integer expected = EXPECTED_SEED_BYTES.get(randomSourceInternal);
+        Assert.assertNotNull("Missing expected seed byte size: " + randomSourceInternal, expected);
+        Assert.assertEquals(randomSourceInternal.toString(),
+                            expected.intValue(), size);
+    }
 }
diff --git a/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/SeedFactoryTest.java b/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/SeedFactoryTest.java
index 842bdaa..b936d81 100644
--- a/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/SeedFactoryTest.java
+++ b/commons-rng-simple/src/test/java/org/apache/commons/rng/simple/internal/SeedFactoryTest.java
@@ -20,6 +20,8 @@
 import java.util.HashMap;
 import org.junit.Assert;
 import org.junit.Test;
+import org.apache.commons.rng.UniformRandomProvider;
+import org.apache.commons.rng.core.source32.IntProvider;
 import org.apache.commons.rng.core.source64.RandomLongSource;
 import org.apache.commons.rng.core.util.NumberFactory;
 
@@ -206,6 +208,63 @@
     }
 
     @Test
+    public void testCreateByteArrayWithSizeZero() {
+        assertCreateByteArray(new byte[0]);
+    }
+
+    @Test
+    public void testCreateByteArrayIgnoresNonZeroPositions() {
+        final byte position = 123;
+        int n = 3;
+        for (int i = 0; i < n; i++) {
+            final byte[] expected = new byte[n];
+            expected[i] = position;
+            assertCreateByteArray(expected);
+        }
+    }
+
+    /**
+     * Assert that the SeedFactory uses the bytes exactly as generated by the
+     * {@link UniformRandomProvider#nextBytes(byte[])} method (assuming they are not all zero).
+     *
+     * @param expected the expected
+     */
+    private static void assertCreateByteArray(final byte[] expected) {
+        final UniformRandomProvider rng = new IntProvider() {
+            @Override
+            public int next() {
+                Assert.fail("This method should not be used");
+                return 0;
+            }
+
+            @Override
+            public void nextBytes(byte[] bytes) {
+                System.arraycopy(expected, 0, bytes, 0, Math.min(expected.length, bytes.length));
+            }
+        };
+
+        final byte[] seed = SeedFactory.createByteArray(rng, expected.length);
+        Assert.assertArrayEquals(expected, seed);
+    }
+
+    @Test
+    public void testCreateByteArrayWithAllZeroBytesUpdatesPosition0() {
+        final UniformRandomProvider rng = new IntProvider() {
+            @Override
+            public int next() {
+                // Deliberately produce zero
+                return 0;
+            }
+        };
+        // Test the method only replaces position 0
+        final byte[] seed = SeedFactory.createByteArray(rng, 4);
+        Assert.assertNotEquals("Zero at position 0 should be modified", 0, seed[0]);
+        for (int i = 1; i < seed.length; i++) {
+            Assert.assertEquals("Position above 0 should be unmodified", 0, seed[i]);
+        }
+    }
+
+    @Test
     public void testEnsureNonZeroIntArrayIgnoresEmptySeed() {
         final int[] seed = new int[0];
         SeedFactory.ensureNonZero(seed);