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.  *      https://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. /*
  18.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */
  21. package org.hipparchus.random;

  22. import java.io.Serializable;

  23. import org.hipparchus.util.FastMath;


  24. /**
  25.  * This class implements a powerful pseudo-random number generator
  26.  * developed by Makoto Matsumoto and Takuji Nishimura during
  27.  * 1996-1997.
  28.  * <p>
  29.  * <b>Caveat:</b> It is recommended to use one of WELL generators rather
  30.  * than the MersenneTwister generator (see
  31.  * <a href="http://www.iro.umontreal.ca/~panneton/WELLRNG.html">
  32.  * this paper</a> for more information).
  33.  * </p>
  34.  * <p>
  35.  * This generator features an extremely long period
  36.  * (2<sup>19937</sup>-1) and 623-dimensional equidistribution up to 32
  37.  * bits accuracy. The home page for this generator is located at <a
  38.  * href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html">
  39.  * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html</a>.
  40.  * </p>
  41.  * <p>
  42.  * This generator is described in a paper by Makoto Matsumoto and
  43.  * Takuji Nishimura in 1998: <a
  44.  * href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/mt.pdf">Mersenne
  45.  * Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-Random
  46.  * Number Generator</a>, ACM Transactions on Modeling and Computer
  47.  * Simulation, Vol. 8, No. 1, January 1998, pp 3--30.
  48.  * </p>
  49.  * <p>
  50.  * This class is mainly a Java port of the 2002-01-26 version of
  51.  * the generator written in C by Makoto Matsumoto and Takuji
  52.  * Nishimura. Here is their original copyright:
  53.  * </p>
  54.  * <blockquote>
  55.  * <p>Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
  56.  *     All rights reserved.</p>
  57.  * <p>Redistribution and use in source and binary forms, with or without
  58.  * modification, are permitted provided that the following conditions
  59.  * are met:</p>
  60.  * <ol>
  61.  *   <li>Redistributions of source code must retain the above copyright
  62.  *       notice, this list of conditions and the following disclaimer.</li>
  63.  *   <li>Redistributions in binary form must reproduce the above copyright
  64.  *       notice, this list of conditions and the following disclaimer in the
  65.  *       documentation and/or other materials provided with the distribution.</li>
  66.  *   <li>The names of its contributors may not be used to endorse or promote
  67.  *       products derived from this software without specific prior written
  68.  *       permission.</li>
  69.  * </ol>
  70.  *
  71.  * <p><strong>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  72.  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  73.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  74.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  75.  * DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
  76.  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  77.  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  78.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  79.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  80.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  81.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  82.  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  83.  * DAMAGE.</strong></p>
  84.  * </blockquote>
  85.  */
  86. public class MersenneTwister extends IntRandomGenerator implements Serializable {

  87.     /** Serializable version identifier. */
  88.     private static final long serialVersionUID = 20160529L;

  89.     /** Size of the bytes pool. */
  90.     private static final int   N     = 624;

  91.     /** Period second parameter. */
  92.     private static final int   M     = 397;

  93.     /** X * MATRIX_A for X = {0, 1}. */
  94.     private static final int[] MAG01 = { 0x0, 0x9908b0df };

  95.     /** Bytes pool. */
  96.     private int[] mt;

  97.     /** Current index in the bytes pool. */
  98.     private int   mti;

  99.     /**
  100.      * Creates a new random number generator.
  101.      * <p>
  102.      * The instance is initialized using the current time plus the
  103.      * system identity hash code of this instance as the seed.
  104.      */
  105.     public MersenneTwister() {
  106.         mt = new int[N];
  107.         setSeed(System.currentTimeMillis() + System.identityHashCode(this));
  108.     }

  109.     /**
  110.      * Creates a new random number generator using a single int seed.
  111.      * @param seed the initial seed (32 bits integer)
  112.      */
  113.     public MersenneTwister(int seed) {
  114.         mt = new int[N];
  115.         setSeed(seed);
  116.     }

  117.     /**
  118.      * Creates a new random number generator using an int array seed.
  119.      * @param seed the initial seed (32 bits integers array), if null
  120.      * the seed of the generator will be related to the current time
  121.      */
  122.     public MersenneTwister(int[] seed) {
  123.         mt = new int[N];
  124.         setSeed(seed);
  125.     }

  126.     /**
  127.      * Creates a new random number generator using a single long seed.
  128.      * @param seed the initial seed (64 bits integer)
  129.      */
  130.     public MersenneTwister(long seed) {
  131.         mt = new int[N];
  132.         setSeed(seed);
  133.     }

  134.     /**
  135.      * Reinitialize the generator as if just built with the given int seed.
  136.      * <p>
  137.      * The state of the generator is exactly the same as a new
  138.      * generator built with the same seed.
  139.      *
  140.      * @param seed the initial seed (32 bits integer)
  141.      */
  142.     @Override
  143.     public void setSeed(int seed) {
  144.         // we use a long masked by 0xffffffffL as a poor man unsigned int
  145.         long longMT = seed & 0xffffffffL;
  146.         // NB: unlike original C code, we are working with java longs,
  147.         // the cast below makes masking unnecessary
  148.         mt[0]= (int) longMT;
  149.         for (mti = 1; mti < N; ++mti) {
  150.             // See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.
  151.             // initializer from the 2002-01-09 C version by Makoto Matsumoto
  152.             longMT = (1812433253l * (longMT ^ (longMT >> 30)) + mti) & 0xffffffffL;
  153.             mt[mti]= (int) longMT;
  154.         }

  155.         clearCache(); // Clear normal deviate cache
  156.     }

  157.     /**
  158.      * Reinitialize the generator as if just built with the given int array seed.
  159.      * <p>
  160.      * The state of the generator is exactly the same as a new
  161.      * generator built with the same seed.
  162.      *
  163.      * @param seed the initial seed (32 bits integers array), if null
  164.      * the seed of the generator will be the current system time plus the
  165.      * system identity hash code of this instance
  166.      */
  167.     @Override
  168.     public void setSeed(int[] seed) {

  169.         if (seed == null) {
  170.             setSeed(System.currentTimeMillis() + System.identityHashCode(this));
  171.             return;
  172.         }

  173.         setSeed(19650218);
  174.         int i = 1;
  175.         int j = 0;

  176.         for (int k = FastMath.max(N, seed.length); k != 0; k--) {
  177.             long l0 = (mt[i] & 0x7fffffffl)   | ((mt[i]   < 0) ? 0x80000000l : 0x0l);
  178.             long l1 = (mt[i-1] & 0x7fffffffl) | ((mt[i-1] < 0) ? 0x80000000l : 0x0l);
  179.             long l  = (l0 ^ ((l1 ^ (l1 >> 30)) * 1664525l)) + seed[j] + j; // non linear
  180.             mt[i]   = (int) (l & 0xffffffffl);
  181.             i++; j++;
  182.             if (i >= N) {
  183.                 mt[0] = mt[N - 1];
  184.                 i = 1;
  185.             }
  186.             if (j >= seed.length) {
  187.                 j = 0;
  188.             }
  189.         }

  190.         for (int k = N - 1; k != 0; k--) {
  191.             long l0 = (mt[i] & 0x7fffffffl)   | ((mt[i]   < 0) ? 0x80000000l : 0x0l);
  192.             long l1 = (mt[i-1] & 0x7fffffffl) | ((mt[i-1] < 0) ? 0x80000000l : 0x0l);
  193.             long l  = (l0 ^ ((l1 ^ (l1 >> 30)) * 1566083941l)) - i; // non linear
  194.             mt[i]   = (int) (l & 0xffffffffL);
  195.             i++;
  196.             if (i >= N) {
  197.                 mt[0] = mt[N - 1];
  198.                 i = 1;
  199.             }
  200.         }

  201.         mt[0] = 0x80000000; // MSB is 1; assuring non-zero initial array

  202.         clearCache(); // Clear normal deviate cache
  203.     }

  204.     /** {@inheritDoc} */
  205.     @Override
  206.     public int nextInt() {

  207.         int y;

  208.         if (mti >= N) { // generate N words at one time
  209.             int mtNext = mt[0];
  210.             for (int k = 0; k < N - M; ++k) {
  211.                 int mtCurr = mtNext;
  212.                 mtNext = mt[k + 1];
  213.                 y = (mtCurr & 0x80000000) | (mtNext & 0x7fffffff);
  214.                 mt[k] = mt[k + M] ^ (y >>> 1) ^ MAG01[y & 0x1];
  215.             }
  216.             for (int k = N - M; k < N - 1; ++k) {
  217.                 int mtCurr = mtNext;
  218.                 mtNext = mt[k + 1];
  219.                 y = (mtCurr & 0x80000000) | (mtNext & 0x7fffffff);
  220.                 mt[k] = mt[k + (M - N)] ^ (y >>> 1) ^ MAG01[y & 0x1];
  221.             }
  222.             y = (mtNext & 0x80000000) | (mt[0] & 0x7fffffff);
  223.             mt[N - 1] = mt[M - 1] ^ (y >>> 1) ^ MAG01[y & 0x1];

  224.             mti = 0;
  225.         }

  226.         y = mt[mti++];

  227.         // tempering
  228.         y ^=  y >>> 11;
  229.         y ^= (y <<   7) & 0x9d2c5680;
  230.         y ^= (y <<  15) & 0xefc60000;
  231.         y ^=  y >>> 18;

  232.         return y;
  233.     }

  234. }