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 /* 19 * This is not the original file distributed by the Apache Software Foundation 20 * It has been modified by the Hipparchus project 21 */ 22 package org.hipparchus.random; 23 24 import java.io.Serializable; 25 26 import org.hipparchus.util.FastMath; 27 28 29 /** 30 * This class implements a powerful pseudo-random number generator 31 * developed by Makoto Matsumoto and Takuji Nishimura during 32 * 1996-1997. 33 * <p> 34 * <b>Caveat:</b> It is recommended to use one of WELL generators rather 35 * than the MersenneTwister generator (see 36 * <a href="http://www.iro.umontreal.ca/~panneton/WELLRNG.html"> 37 * this paper</a> for more information). 38 * </p> 39 * <p> 40 * This generator features an extremely long period 41 * (2<sup>19937</sup>-1) and 623-dimensional equidistribution up to 32 42 * bits accuracy. The home page for this generator is located at <a 43 * href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html"> 44 * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html</a>. 45 * </p> 46 * <p> 47 * This generator is described in a paper by Makoto Matsumoto and 48 * Takuji Nishimura in 1998: <a 49 * href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/mt.pdf">Mersenne 50 * Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-Random 51 * Number Generator</a>, ACM Transactions on Modeling and Computer 52 * Simulation, Vol. 8, No. 1, January 1998, pp 3--30. 53 * </p> 54 * <p> 55 * This class is mainly a Java port of the 2002-01-26 version of 56 * the generator written in C by Makoto Matsumoto and Takuji 57 * Nishimura. Here is their original copyright: 58 * </p> 59 * <blockquote> 60 * <p>Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, 61 * All rights reserved.</p> 62 * <p>Redistribution and use in source and binary forms, with or without 63 * modification, are permitted provided that the following conditions 64 * are met:</p> 65 * <ol> 66 * <li>Redistributions of source code must retain the above copyright 67 * notice, this list of conditions and the following disclaimer.</li> 68 * <li>Redistributions in binary form must reproduce the above copyright 69 * notice, this list of conditions and the following disclaimer in the 70 * documentation and/or other materials provided with the distribution.</li> 71 * <li>The names of its contributors may not be used to endorse or promote 72 * products derived from this software without specific prior written 73 * permission.</li> 74 * </ol> 75 * 76 * <p><strong>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 77 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 78 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 79 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 80 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 81 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 82 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 83 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 84 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 85 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 86 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 87 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 88 * DAMAGE.</strong></p> 89 * </blockquote> 90 */ 91 public class MersenneTwister extends IntRandomGenerator implements Serializable { 92 93 /** Serializable version identifier. */ 94 private static final long serialVersionUID = 20160529L; 95 96 /** Size of the bytes pool. */ 97 private static final int N = 624; 98 99 /** Period second parameter. */ 100 private static final int M = 397; 101 102 /** X * MATRIX_A for X = {0, 1}. */ 103 private static final int[] MAG01 = { 0x0, 0x9908b0df }; 104 105 /** Bytes pool. */ 106 private int[] mt; 107 108 /** Current index in the bytes pool. */ 109 private int mti; 110 111 /** 112 * Creates a new random number generator. 113 * <p> 114 * The instance is initialized using the current time plus the 115 * system identity hash code of this instance as the seed. 116 */ 117 public MersenneTwister() { 118 mt = new int[N]; 119 setSeed(System.currentTimeMillis() + System.identityHashCode(this)); 120 } 121 122 /** 123 * Creates a new random number generator using a single int seed. 124 * @param seed the initial seed (32 bits integer) 125 */ 126 public MersenneTwister(int seed) { 127 mt = new int[N]; 128 setSeed(seed); 129 } 130 131 /** 132 * Creates a new random number generator using an int array seed. 133 * @param seed the initial seed (32 bits integers array), if null 134 * the seed of the generator will be related to the current time 135 */ 136 public MersenneTwister(int[] seed) { 137 mt = new int[N]; 138 setSeed(seed); 139 } 140 141 /** 142 * Creates a new random number generator using a single long seed. 143 * @param seed the initial seed (64 bits integer) 144 */ 145 public MersenneTwister(long seed) { 146 mt = new int[N]; 147 setSeed(seed); 148 } 149 150 /** 151 * Reinitialize the generator as if just built with the given int seed. 152 * <p> 153 * The state of the generator is exactly the same as a new 154 * generator built with the same seed. 155 * 156 * @param seed the initial seed (32 bits integer) 157 */ 158 @Override 159 public void setSeed(int seed) { 160 // we use a long masked by 0xffffffffL as a poor man unsigned int 161 long longMT = seed & 0xffffffffL; 162 // NB: unlike original C code, we are working with java longs, 163 // the cast below makes masking unnecessary 164 mt[0]= (int) longMT; 165 for (mti = 1; mti < N; ++mti) { 166 // See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. 167 // initializer from the 2002-01-09 C version by Makoto Matsumoto 168 longMT = (1812433253l * (longMT ^ (longMT >> 30)) + mti) & 0xffffffffL; 169 mt[mti]= (int) longMT; 170 } 171 172 clearCache(); // Clear normal deviate cache 173 } 174 175 /** 176 * Reinitialize the generator as if just built with the given int array seed. 177 * <p> 178 * The state of the generator is exactly the same as a new 179 * generator built with the same seed. 180 * 181 * @param seed the initial seed (32 bits integers array), if null 182 * the seed of the generator will be the current system time plus the 183 * system identity hash code of this instance 184 */ 185 @Override 186 public void setSeed(int[] seed) { 187 188 if (seed == null) { 189 setSeed(System.currentTimeMillis() + System.identityHashCode(this)); 190 return; 191 } 192 193 setSeed(19650218); 194 int i = 1; 195 int j = 0; 196 197 for (int k = FastMath.max(N, seed.length); k != 0; k--) { 198 long l0 = (mt[i] & 0x7fffffffl) | ((mt[i] < 0) ? 0x80000000l : 0x0l); 199 long l1 = (mt[i-1] & 0x7fffffffl) | ((mt[i-1] < 0) ? 0x80000000l : 0x0l); 200 long l = (l0 ^ ((l1 ^ (l1 >> 30)) * 1664525l)) + seed[j] + j; // non linear 201 mt[i] = (int) (l & 0xffffffffl); 202 i++; j++; 203 if (i >= N) { 204 mt[0] = mt[N - 1]; 205 i = 1; 206 } 207 if (j >= seed.length) { 208 j = 0; 209 } 210 } 211 212 for (int k = N - 1; k != 0; k--) { 213 long l0 = (mt[i] & 0x7fffffffl) | ((mt[i] < 0) ? 0x80000000l : 0x0l); 214 long l1 = (mt[i-1] & 0x7fffffffl) | ((mt[i-1] < 0) ? 0x80000000l : 0x0l); 215 long l = (l0 ^ ((l1 ^ (l1 >> 30)) * 1566083941l)) - i; // non linear 216 mt[i] = (int) (l & 0xffffffffL); 217 i++; 218 if (i >= N) { 219 mt[0] = mt[N - 1]; 220 i = 1; 221 } 222 } 223 224 mt[0] = 0x80000000; // MSB is 1; assuring non-zero initial array 225 226 clearCache(); // Clear normal deviate cache 227 } 228 229 /** {@inheritDoc} */ 230 @Override 231 public int nextInt() { 232 233 int y; 234 235 if (mti >= N) { // generate N words at one time 236 int mtNext = mt[0]; 237 for (int k = 0; k < N - M; ++k) { 238 int mtCurr = mtNext; 239 mtNext = mt[k + 1]; 240 y = (mtCurr & 0x80000000) | (mtNext & 0x7fffffff); 241 mt[k] = mt[k + M] ^ (y >>> 1) ^ MAG01[y & 0x1]; 242 } 243 for (int k = N - M; k < N - 1; ++k) { 244 int mtCurr = mtNext; 245 mtNext = mt[k + 1]; 246 y = (mtCurr & 0x80000000) | (mtNext & 0x7fffffff); 247 mt[k] = mt[k + (M - N)] ^ (y >>> 1) ^ MAG01[y & 0x1]; 248 } 249 y = (mtNext & 0x80000000) | (mt[0] & 0x7fffffff); 250 mt[N - 1] = mt[M - 1] ^ (y >>> 1) ^ MAG01[y & 0x1]; 251 252 mti = 0; 253 } 254 255 y = mt[mti++]; 256 257 // tempering 258 y ^= y >>> 11; 259 y ^= (y << 7) & 0x9d2c5680; 260 y ^= (y << 15) & 0xefc60000; 261 y ^= y >>> 18; 262 263 return y; 264 } 265 266 }