You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2019/06/11 17:08:25 UTC

[commons-rng] branch master updated: Test generators known to be non-functional with a zero-byte seed.

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


The following commit(s) were added to refs/heads/master by this push:
     new aed6da0  Test generators known to be non-functional with a zero-byte seed.
aed6da0 is described below

commit aed6da0f56e53757cb9b27c47faa380baf733261
Author: aherbert <ah...@apache.org>
AuthorDate: Tue Jun 11 17:38:31 2019 +0100

    Test generators known to be non-functional with a zero-byte seed.
---
 .../org/apache/commons/rng/core/RandomAssert.java  | 65 +++++++++++++++++++---
 .../core/source32/MultiplyWithCarry256Test.java    | 13 +++++
 .../commons/rng/core/source32/Well1024aTest.java   | 13 +++++
 .../commons/rng/core/source32/Well19937aTest.java  | 13 +++++
 .../commons/rng/core/source32/Well19937cTest.java  | 13 +++++
 .../commons/rng/core/source32/Well44497aTest.java  | 13 +++++
 .../commons/rng/core/source32/Well44497bTest.java  | 13 +++++
 .../commons/rng/core/source32/Well512aTest.java    | 13 +++++
 8 files changed, 147 insertions(+), 9 deletions(-)

diff --git a/commons-rng-core/src/test/java/org/apache/commons/rng/core/RandomAssert.java b/commons-rng-core/src/test/java/org/apache/commons/rng/core/RandomAssert.java
index b3743ce..76c5293 100644
--- a/commons-rng-core/src/test/java/org/apache/commons/rng/core/RandomAssert.java
+++ b/commons-rng-core/src/test/java/org/apache/commons/rng/core/RandomAssert.java
@@ -214,6 +214,29 @@ public class RandomAssert {
     }
 
     /**
+     * Assert that following a set number of warm-up cycles the random generator produces
+     * at least one non-zero output for {@link UniformRandomProvider#nextLong()} over the
+     * given number of test cycles.
+     * 
+     * <p>Helper function to add the seed element and bit that was non zero to the fail message.
+     *
+     * @param rng Random generator.
+     * @param warmupCycles Number of warm-up cycles.
+     * @param testCycles Number of test cycles.
+     * @param seedElement Seed element for the message.
+     * @param bit Seed bit for the message.
+     */
+    private static void assertNextLongNonZeroOutputFromSingleBitSeed(
+        UniformRandomProvider rng, int warmupCycles, int testCycles, int seedElement, int bit) {
+        try {
+            assertNextLongNonZeroOutput(rng, warmupCycles, testCycles);
+        } catch (AssertionError ex) {
+            Assert.fail("No non-zero output after " + (warmupCycles + testCycles) + " cycles. " +
+                        "Seed element [" + seedElement + "], bit=" + bit);
+        }
+    }
+
+    /**
      * Assert that the random generator created using an {@code int[]} seed with a
      * single bit set is functional. This is tested using the
      * {@link #assertNextLongNonZeroOutput(UniformRandomProvider, int, int)} using
@@ -224,17 +247,41 @@ public class RandomAssert {
      */
     public static <T extends UniformRandomProvider> void
         assertIntArrayConstructorWithSingleBitSeedIsFunctional(Class<T> type, int size) {
+        assertIntArrayConstructorWithSingleBitInPoolIsFunctional(type, 32 * size);
+    }
+
+    /**
+     * Assert that the random generator created using an {@code int[]} seed with a
+     * single bit set is functional. This is tested using the
+     * {@link #assertNextLongNonZeroOutput(UniformRandomProvider, int, int)} using
+     * two times the seed size as the warm-up and test cycles.
+     *
+     * <p>The seed size is determined from the size of the bit pool. Bits are set for every position
+     * in the pool from most significant first. If the pool size is not a multiple of 32 then the
+     * remaining lower significant bits of the last seed position are not tested.</p>
+     *
+     * @param type Class of the generator.
+     * @param k Number of bits in the pool (not necessarily a multiple of 32).
+     */
+    public static <T extends UniformRandomProvider> void
+        assertIntArrayConstructorWithSingleBitInPoolIsFunctional(Class<T> type, int k) {
         try {
             // Find the int[] constructor
             final Constructor<T> constructor = type.getConstructor(int[].class);
+            final int size = (k + 31) / 32;
             final int[] seed = new int[size];
-            for (int i = 0; i < size; i++) {
-                seed[i] = 1;
+            int remaining = k;
+            for (int i = 0; i < seed.length; i++) {
+                seed[i] = 0x80000000;
                 for (int j = 0; j < 32; j++) {
                     final UniformRandomProvider rng = constructor.newInstance(seed);
-                    RandomAssert.assertNextLongNonZeroOutput(rng, 2 * size, 2 * size);
-                    // Eventually rolls-over to reset to zero
-                    seed[i] <<= 1;
+                    RandomAssert.assertNextLongNonZeroOutputFromSingleBitSeed(rng, 2 * size, 2 * size, i, 31 - j);
+                    // Eventually reset to zero
+                    seed[i] >>>= 1;
+                    // Terminate when the entire bit pool has been tested
+                    if (--remaining == 0) {
+                        return;
+                    }
                 }
                 Assert.assertEquals("Seed element was not reset", 0, seed[i]);
             }
@@ -265,12 +312,12 @@ public class RandomAssert {
             final Constructor<T> constructor = type.getConstructor(long[].class);
             final long[] seed = new long[size];
             for (int i = 0; i < size; i++) {
-                seed[i] = 1;
+                seed[i] = 0x8000000000000000L;
                 for (int j = 0; j < 64; j++) {
                     final UniformRandomProvider rng = constructor.newInstance(seed);
-                    RandomAssert.assertNextLongNonZeroOutput(rng, 2 * size, 2 * size);
-                    // Eventually rolls-over to reset to zero
-                    seed[i] <<= 1;
+                    RandomAssert.assertNextLongNonZeroOutputFromSingleBitSeed(rng, 2 * size, 2 * size, i, 63 - j);
+                    // Eventually reset to zero
+                    seed[i] >>>= 1;
                 }
                 Assert.assertEquals("Seed element was not reset", 0L, seed[i]);
             }
diff --git a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/MultiplyWithCarry256Test.java b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/MultiplyWithCarry256Test.java
index e8f85a6..7db040b 100644
--- a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/MultiplyWithCarry256Test.java
+++ b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/MultiplyWithCarry256Test.java
@@ -20,6 +20,9 @@ import org.apache.commons.rng.core.RandomAssert;
 import org.junit.Test;
 
 public class MultiplyWithCarry256Test {
+    /** The size of the array seed. */
+    private static final int SEED_SIZE = 257;
+
     @Test
     public void testMarsaglia() {
         final int[] seed = {
@@ -192,4 +195,14 @@ public class MultiplyWithCarry256Test {
 
         RandomAssert.assertEquals(expectedSequence, new MultiplyWithCarry256(seed));
     }
+
+    @Test
+    public void testConstructorWithZeroSeedIsNonFunctional() {
+        RandomAssert.assertNextIntZeroOutput(new MultiplyWithCarry256(new int[SEED_SIZE]), 2 * SEED_SIZE);
+    }
+
+    @Test
+    public void testConstructorWithSingleBitSeedIsFunctional() {
+        RandomAssert.assertIntArrayConstructorWithSingleBitSeedIsFunctional(MultiplyWithCarry256.class, SEED_SIZE);
+    }
 }
diff --git a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well1024aTest.java b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well1024aTest.java
index a44fccb..746f096 100644
--- a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well1024aTest.java
+++ b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well1024aTest.java
@@ -20,6 +20,9 @@ import org.apache.commons.rng.core.RandomAssert;
 import org.junit.Test;
 
 public class Well1024aTest {
+    /** The size of the array seed. */
+    private static final int SEED_SIZE = 32;
+
     @Test
     public void testReferenceCode() {
         final Well1024a rng = new Well1024a(new int[] {
@@ -66,4 +69,14 @@ public class Well1024aTest {
 
         RandomAssert.assertEquals(expectedSequence, rng);
     }
+
+    @Test
+    public void testConstructorWithZeroSeedIsNonFunctional() {
+        RandomAssert.assertNextIntZeroOutput(new Well1024a(new int[SEED_SIZE]), 2 * SEED_SIZE);
+    }
+
+    @Test
+    public void testConstructorWithSingleBitSeedIsFunctional() {
+        RandomAssert.assertIntArrayConstructorWithSingleBitSeedIsFunctional(Well1024a.class, SEED_SIZE);
+    }
 }
diff --git a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well19937aTest.java b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well19937aTest.java
index cbda07e..cc2a509 100644
--- a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well19937aTest.java
+++ b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well19937aTest.java
@@ -20,6 +20,9 @@ import org.apache.commons.rng.core.RandomAssert;
 import org.junit.Test;
 
 public class Well19937aTest {
+    /** The size of the array seed. */
+    private static final int SEED_SIZE = 624;
+
     @Test
     public void testReferenceCode() {
         final int[] base = {
@@ -168,4 +171,14 @@ public class Well19937aTest {
 
         RandomAssert.assertEquals(expectedSequence, rng);
     }
+
+    @Test
+    public void testConstructorWithZeroSeedIsNonFunctional() {
+        RandomAssert.assertNextIntZeroOutput(new Well19937a(new int[SEED_SIZE]), 2 * SEED_SIZE);
+    }
+
+    @Test
+    public void testConstructorWithSingleBitSeedIsFunctional() {
+        RandomAssert.assertIntArrayConstructorWithSingleBitInPoolIsFunctional(Well19937a.class, 19937);
+    }
 }
diff --git a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well19937cTest.java b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well19937cTest.java
index a6625e1..4a28d3b 100644
--- a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well19937cTest.java
+++ b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well19937cTest.java
@@ -20,6 +20,9 @@ import org.apache.commons.rng.core.RandomAssert;
 import org.junit.Test;
 
 public class Well19937cTest {
+    /** The size of the array seed. */
+    private static final int SEED_SIZE = 624;
+
     @Test
     public void testReferenceCode() {
         final int[] base = {
@@ -168,4 +171,14 @@ public class Well19937cTest {
 
         RandomAssert.assertEquals(expectedSequence, rng);
     }
+
+    @Test
+    public void testConstructorWithZeroSeedIsNonFunctional() {
+        RandomAssert.assertNextIntZeroOutput(new Well19937c(new int[SEED_SIZE]), 2 * SEED_SIZE);
+    }
+
+    @Test
+    public void testConstructorWithSingleBitSeedIsFunctional() {
+        RandomAssert.assertIntArrayConstructorWithSingleBitInPoolIsFunctional(Well19937c.class, 19937);
+    }
 }
diff --git a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well44497aTest.java b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well44497aTest.java
index 1f8177f..e42f488 100644
--- a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well44497aTest.java
+++ b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well44497aTest.java
@@ -20,6 +20,9 @@ import org.apache.commons.rng.core.RandomAssert;
 import org.junit.Test;
 
 public class Well44497aTest {
+    /** The size of the array seed. */
+    private static final int SEED_SIZE = 1391;
+
     @Test
     public void testReferenceCode() {
         final int[] base = {
@@ -296,4 +299,14 @@ public class Well44497aTest {
 
         RandomAssert.assertEquals(expectedSequence, rng);
     }
+
+    @Test
+    public void testConstructorWithZeroSeedIsNonFunctional() {
+        RandomAssert.assertNextIntZeroOutput(new Well44497a(new int[SEED_SIZE]), 2 * SEED_SIZE);
+    }
+
+    @Test
+    public void testConstructorWithSingleBitSeedIsFunctional() {
+        RandomAssert.assertIntArrayConstructorWithSingleBitInPoolIsFunctional(Well44497a.class, 44497);
+    }
 }
diff --git a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well44497bTest.java b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well44497bTest.java
index de50a40..a7afa55 100644
--- a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well44497bTest.java
+++ b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well44497bTest.java
@@ -20,6 +20,9 @@ import org.apache.commons.rng.core.RandomAssert;
 import org.junit.Test;
 
 public class Well44497bTest {
+    /** The size of the array seed. */
+    private static final int SEED_SIZE = 1391;
+
     @Test
     public void testReferenceCode() {
         final int[] base = {
@@ -296,4 +299,14 @@ public class Well44497bTest {
 
         RandomAssert.assertEquals(expectedSequence, rng);
     }
+
+    @Test
+    public void testConstructorWithZeroSeedIsNonFunctional() {
+        RandomAssert.assertNextIntZeroOutput(new Well44497b(new int[SEED_SIZE]), 2 * SEED_SIZE);
+    }
+
+    @Test
+    public void testConstructorWithSingleBitSeedIsFunctional() {
+        RandomAssert.assertIntArrayConstructorWithSingleBitInPoolIsFunctional(Well44497b.class, 44497);
+    }
 }
diff --git a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well512aTest.java b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well512aTest.java
index dac7bab..5e858be 100644
--- a/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well512aTest.java
+++ b/commons-rng-core/src/test/java/org/apache/commons/rng/core/source32/Well512aTest.java
@@ -20,6 +20,9 @@ import org.apache.commons.rng.core.RandomAssert;
 import org.junit.Test;
 
 public class Well512aTest {
+    /** The size of the array seed. */
+    private static final int SEED_SIZE = 16;
+
     @Test
     public void testReferenceCode() {
         final Well512a rng = new Well512a(new int[] {
@@ -64,4 +67,14 @@ public class Well512aTest {
 
         RandomAssert.assertEquals(expectedSequence, rng);
     }
+
+    @Test
+    public void testConstructorWithZeroSeedIsNonFunctional() {
+        RandomAssert.assertNextIntZeroOutput(new Well512a(new int[SEED_SIZE]), 2 * SEED_SIZE);
+    }
+
+    @Test
+    public void testConstructorWithSingleBitSeedIsFunctional() {
+        RandomAssert.assertIntArrayConstructorWithSingleBitSeedIsFunctional(Well512a.class, SEED_SIZE);
+    }
 }