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/10/02 23:07:03 UTC

[commons-rng] branch master updated: MersenneTwister: Refactor state filling procedure into sub-methods.

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 0fb91cf  MersenneTwister: Refactor state filling procedure into sub-methods.
0fb91cf is described below

commit 0fb91cfe8a6d66470ebcbcb7cc06c8a8ce9579ef
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Thu Oct 3 00:06:02 2019 +0100

    MersenneTwister: Refactor state filling procedure into sub-methods.
    
    Addresses complexity issue raised by SonarCloud.
---
 .../commons/rng/core/source32/MersenneTwister.java | 51 ++++++++++++++++++++--
 1 file changed, 47 insertions(+), 4 deletions(-)

diff --git a/commons-rng-core/src/main/java/org/apache/commons/rng/core/source32/MersenneTwister.java b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source32/MersenneTwister.java
index c4c06cd..7d30440 100644
--- a/commons-rng-core/src/main/java/org/apache/commons/rng/core/source32/MersenneTwister.java
+++ b/commons-rng-core/src/main/java/org/apache/commons/rng/core/source32/MersenneTwister.java
@@ -165,14 +165,45 @@ public class MersenneTwister extends IntProvider {
         // Accept empty seed.
         final int[] seed = (inputSeed.length == 0) ? new int[1] : inputSeed;
 
-        final int stateSize = state.length;
+        initialiseState(state);
+
+        final int nextIndex = mixSeedAndState(state, seed);
 
+        mixState(state, nextIndex);
+
+        state[0] = (int) UPPER_MASK_LONG; // MSB is 1, ensuring non-zero initial array.
+    }
+
+    /**
+     * Fill the state using a defined pseudo-random sequence.
+     *
+     * @param state State to be filled (must be allocated).
+     */
+    private static void initialiseState(int[] state) {
         long mt = 19650218 & INT_MASK_LONG;
         state[0] = (int) mt;
-        for (int i = 1; i < stateSize; i++) {
+        for (int i = 1; i < state.length; i++) {
             mt = (1812433253L * (mt ^ (mt >> 30)) + i) & INT_MASK_LONG;
             state[i] = (int) mt;
         }
+    }
+
+    /**
+     * Mix the seed into the state using a non-linear combination. The procedure
+     * uses {@code k} steps where {@code k = max(state.length, seed.length)}. If
+     * the seed is smaller than the state it is wrapped to obtain enough values.
+     * If the seed is larger than the state then the procedure visits entries in
+     * the state multiple times.
+     *
+     * <p>Returns the index immediately after the most recently visited position
+     * in the state array.</p>
+     *
+     * @param state State to be filled (must be allocated).
+     * @param seed Seed (must be at least length 1).
+     * @return the next index
+     */
+    private static int mixSeedAndState(int[] state, final int[] seed) {
+        final int stateSize = state.length;
 
         int i = 1;
         int j = 0;
@@ -192,7 +223,21 @@ public class MersenneTwister extends IntProvider {
                 j = 0;
             }
         }
+        return i;
+    }
 
+    /**
+     * Mix each position of the state using a non-linear combination. The
+     * procedure starts from the specified index in the state array and wraps
+     * iteration through the array if required.
+     *
+     * @param state State to be filled (must be allocated).
+     * @param startIndex The index to begin within the state array.
+     */
+    private static void mixState(int[] state, int startIndex) {
+        final int stateSize = state.length;
+
+        int i = startIndex;
         for (int k = stateSize - 1; k > 0; k--) {
             final long a = (state[i] & LOWER_MASK_LONG) | ((state[i] < 0) ? UPPER_MASK_LONG : 0);
             final long b = (state[i - 1] & LOWER_MASK_LONG) | ((state[i - 1] < 0) ? UPPER_MASK_LONG : 0);
@@ -204,8 +249,6 @@ public class MersenneTwister extends IntProvider {
                 i = 1;
             }
         }
-
-        state[0] = (int) UPPER_MASK_LONG; // MSB is 1, ensuring non-zero initial array.
     }
 
     /** {@inheritDoc} */