MersenneTwister.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.rng.core.source32;

  18. import java.util.Arrays;
  19. import org.apache.commons.rng.core.util.NumberFactory;

  20. /**
  21.  * This class implements a powerful pseudo-random number generator
  22.  * developed by Makoto Matsumoto and Takuji Nishimura during
  23.  * 1996-1997.
  24.  *
  25.  * <p>
  26.  * This generator features an extremely long period
  27.  * (2<sup>19937</sup>-1) and 623-dimensional equidistribution up to
  28.  * 32 bits accuracy.  The home page for this generator is located at
  29.  * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html">
  30.  * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html</a>.
  31.  * </p>
  32.  *
  33.  * <p>
  34.  * This generator is described in a paper by Makoto Matsumoto and
  35.  * Takuji Nishimura in 1998:
  36.  * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/mt.pdf">
  37.  * Mersenne Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-Random
  38.  * Number Generator</a>,
  39.  * ACM Transactions on Modeling and Computer Simulation, Vol. 8, No. 1,
  40.  * January 1998, pp 3--30
  41.  * </p>
  42.  *
  43.  * <p>
  44.  * This class is mainly a Java port of the
  45.  * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html">
  46.  * 2002-01-26 version of the generator</a> written in C by Makoto Matsumoto
  47.  * and Takuji Nishimura. Here is their original copyright:
  48.  * </p>
  49.  *
  50.  * <table style="background-color: #E0E0E0; width: 80%">
  51.  * <caption>Mersenne Twister licence</caption>
  52.  * <tr><td style="padding: 10px">Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
  53.  *     All rights reserved.</td></tr>
  54.  *
  55.  * <tr><td style="padding: 10px">Redistribution and use in source and binary forms, with or without
  56.  * modification, are permitted provided that the following conditions
  57.  * are met:
  58.  * <ol>
  59.  *   <li>Redistributions of source code must retain the above copyright
  60.  *       notice, this list of conditions and the following disclaimer.</li>
  61.  *   <li>Redistributions in binary form must reproduce the above copyright
  62.  *       notice, this list of conditions and the following disclaimer in the
  63.  *       documentation and/or other materials provided with the distribution.</li>
  64.  *   <li>The names of its contributors may not be used to endorse or promote
  65.  *       products derived from this software without specific prior written
  66.  *       permission.</li>
  67.  * </ol></td></tr>
  68.  *
  69.  * <tr><td style="padding: 10px"><strong>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  70.  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  71.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  72.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  73.  * DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
  74.  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  75.  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  76.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  77.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  78.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  79.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  80.  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  81.  * DAMAGE.</strong></td></tr>
  82.  * </table>
  83.  *
  84.  * @see <a href="https://en.wikipedia.org/wiki/Mersenne_Twister">Mersenne Twister (Wikipedia)</a>
  85.  * @since 1.0
  86.  */
  87. public class MersenneTwister extends IntProvider {
  88.     /** Mask 32 most significant bits. */
  89.     private static final long INT_MASK_LONG = 0xffffffffL;
  90.     /** Most significant w-r bits. */
  91.     private static final long UPPER_MASK_LONG = 0x80000000L;
  92.     /** Least significant r bits. */
  93.     private static final long LOWER_MASK_LONG = 0x7fffffffL;
  94.     /** Most significant w-r bits. */
  95.     private static final int UPPER_MASK = 0x80000000;
  96.     /** Least significant r bits. */
  97.     private static final int LOWER_MASK = 0x7fffffff;
  98.     /** Size of the bytes pool. */
  99.     private static final int N = 624;
  100.     /** Period second parameter. */
  101.     private static final int M = 397;
  102.     /** X * MATRIX_A for X = {0, 1}. */
  103.     private static final int[] MAG01 = {0x0, 0x9908b0df};
  104.     /** Bytes pool. */
  105.     private final int[] mt = new int[N];
  106.     /** Current index in the bytes pool. */
  107.     private int mti;

  108.     /**
  109.      * Creates a new random number generator.
  110.      *
  111.      * @param seed Initial seed.
  112.      */
  113.     public MersenneTwister(int[] seed) {
  114.         setSeedInternal(seed);
  115.     }

  116.     /** {@inheritDoc} */
  117.     @Override
  118.     protected byte[] getStateInternal() {
  119.         final int[] s = Arrays.copyOf(mt, N + 1);
  120.         s[N] = mti;

  121.         return composeStateInternal(NumberFactory.makeByteArray(s),
  122.                                     super.getStateInternal());
  123.     }

  124.     /** {@inheritDoc} */
  125.     @Override
  126.     protected void setStateInternal(byte[] s) {
  127.         final byte[][] c = splitStateInternal(s, (N + 1) * 4);

  128.         final int[] tmp = NumberFactory.makeIntArray(c[0]);
  129.         System.arraycopy(tmp, 0, mt, 0, N);
  130.         mti = tmp[N];

  131.         super.setStateInternal(c[1]);
  132.     }

  133.     /**
  134.      * Initializes the generator with the given seed.
  135.      *
  136.      * @param seed Initial seed.
  137.      */
  138.     private void setSeedInternal(int[] seed) {
  139.         fillStateMersenneTwister(mt, seed);

  140.         // Initial index.
  141.         mti = N;
  142.     }

  143.     /**
  144.      * Utility for wholly filling a {@code state} array with non-zero
  145.      * bytes, even if the {@code seed} has a smaller size.
  146.      * The procedure is the one defined by the standard implementation
  147.      * of the algorithm.
  148.      *
  149.      * @param state State to be filled (must be allocated).
  150.      * @param inputSeed Seed (cannot be {@code null}).
  151.      */
  152.     private static void fillStateMersenneTwister(int[] state,
  153.                                                  int[] inputSeed) {
  154.         // Accept empty seed.
  155.         final int[] seed = (inputSeed.length == 0) ? new int[1] : inputSeed;

  156.         initializeState(state);

  157.         final int nextIndex = mixSeedAndState(state, seed);

  158.         mixState(state, nextIndex);

  159.         state[0] = (int) UPPER_MASK_LONG; // MSB is 1, ensuring non-zero initial array.
  160.     }

  161.     /**
  162.      * Fill the state using a defined pseudo-random sequence.
  163.      *
  164.      * @param state State to be filled (must be allocated).
  165.      */
  166.     private static void initializeState(int[] state) {
  167.         long mt = 19650218 & INT_MASK_LONG;
  168.         state[0] = (int) mt;
  169.         for (int i = 1; i < state.length; i++) {
  170.             mt = (1812433253L * (mt ^ (mt >> 30)) + i) & INT_MASK_LONG;
  171.             state[i] = (int) mt;
  172.         }
  173.     }

  174.     /**
  175.      * Mix the seed into the state using a non-linear combination. The procedure
  176.      * uses {@code k} steps where {@code k = max(state.length, seed.length)}. If
  177.      * the seed is smaller than the state it is wrapped to obtain enough values.
  178.      * If the seed is larger than the state then the procedure visits entries in
  179.      * the state multiple times.
  180.      *
  181.      * <p>Returns the index immediately after the most recently visited position
  182.      * in the state array.</p>
  183.      *
  184.      * @param state State to be filled (must be allocated).
  185.      * @param seed Seed (must be at least length 1).
  186.      * @return the next index
  187.      */
  188.     private static int mixSeedAndState(int[] state, final int[] seed) {
  189.         final int stateSize = state.length;

  190.         int i = 1;
  191.         int j = 0;

  192.         for (int k = Math.max(stateSize, seed.length); k > 0; k--) {
  193.             final long a = (state[i] & LOWER_MASK_LONG) | ((state[i] < 0) ? UPPER_MASK_LONG : 0);
  194.             final long b = (state[i - 1] & LOWER_MASK_LONG) | ((state[i - 1] < 0) ? UPPER_MASK_LONG : 0);
  195.             final long c = (a ^ ((b ^ (b >> 30)) * 1664525L)) + seed[j] + j; // Non linear.
  196.             state[i] = (int) (c & INT_MASK_LONG);
  197.             i++;
  198.             j++;
  199.             if (i >= stateSize) {
  200.                 state[0] = state[stateSize - 1];
  201.                 i = 1;
  202.             }
  203.             if (j >= seed.length) {
  204.                 j = 0;
  205.             }
  206.         }
  207.         return i;
  208.     }

  209.     /**
  210.      * Mix each position of the state using a non-linear combination. The
  211.      * procedure starts from the specified index in the state array and wraps
  212.      * iteration through the array if required.
  213.      *
  214.      * @param state State to be filled (must be allocated).
  215.      * @param startIndex The index to begin within the state array.
  216.      */
  217.     private static void mixState(int[] state, int startIndex) {
  218.         final int stateSize = state.length;

  219.         int i = startIndex;
  220.         for (int k = stateSize - 1; k > 0; k--) {
  221.             final long a = (state[i] & LOWER_MASK_LONG) | ((state[i] < 0) ? UPPER_MASK_LONG : 0);
  222.             final long b = (state[i - 1] & LOWER_MASK_LONG) | ((state[i - 1] < 0) ? UPPER_MASK_LONG : 0);
  223.             final long c = (a ^ ((b ^ (b >> 30)) * 1566083941L)) - i; // Non linear.
  224.             state[i] = (int) (c & INT_MASK_LONG);
  225.             i++;
  226.             if (i >= stateSize) {
  227.                 state[0] = state[stateSize - 1];
  228.                 i = 1;
  229.             }
  230.         }
  231.     }

  232.     /** {@inheritDoc} */
  233.     @Override
  234.     public int next() {
  235.         int y;

  236.         if (mti >= N) { // Generate N words at one time.
  237.             int mtNext = mt[0];
  238.             for (int k = 0; k < N - M; ++k) {
  239.                 final int mtCurr = mtNext;
  240.                 mtNext = mt[k + 1];
  241.                 y = (mtCurr & UPPER_MASK) | (mtNext & LOWER_MASK);
  242.                 mt[k] = mt[k + M] ^ (y >>> 1) ^ MAG01[y & 1];
  243.             }
  244.             for (int k = N - M; k < N - 1; ++k) {
  245.                 final int mtCurr = mtNext;
  246.                 mtNext = mt[k + 1];
  247.                 y = (mtCurr & UPPER_MASK) | (mtNext & LOWER_MASK);
  248.                 mt[k] = mt[k + (M - N)] ^ (y >>> 1) ^ MAG01[y & 1];
  249.             }
  250.             y = (mtNext & UPPER_MASK) | (mt[0] & LOWER_MASK);
  251.             mt[N - 1] = mt[M - 1] ^ (y >>> 1) ^ MAG01[y & 1];

  252.             mti = 0;
  253.         }

  254.         y = mt[mti++];

  255.         // Tempering.
  256.         y ^=  y >>> 11;
  257.         y ^= (y << 7) & 0x9d2c5680;
  258.         y ^= (y << 15) & 0xefc60000;
  259.         y ^=  y >>> 18;

  260.         return y;
  261.     }
  262. }