001/* 002 * Copyright 2005, Nick Galbreath -- nickg [at] modp [dot] com 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without 006 * modification, are permitted provided that the following conditions are 007 * met: 008 * 009 * Redistributions of source code must retain the above copyright 010 * notice, this list of conditions and the following disclaimer. 011 * 012 * Redistributions in binary form must reproduce the above copyright 013 * notice, this list of conditions and the following disclaimer in the 014 * documentation and/or other materials provided with the distribution. 015 * 016 * Neither the name of the modp.com nor the names of its 017 * contributors may be used to endorse or promote products derived from 018 * this software without specific prior written permission. 019 * 020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 021 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 022 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 023 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 024 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 025 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 026 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 027 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 028 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 029 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 030 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 031 * 032 * This is the standard "new" BSD license: 033 * http://www.opensource.org/licenses/bsd-license.php 034 * 035 * Portions may also be 036 * Copyright (C) 2004, Makoto Matsumoto and Takuji Nishimura, 037 * All rights reserved. 038 * (and covered under the BSD license) 039 * See http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/C-LANG/mt19937-64.c 040 */ 041package squidpony.squidmath; 042 043import squidpony.StringKit; 044 045import java.io.Serializable; 046import java.util.Arrays; 047 048/** 049 * Mersenne Twister, 64-bit version as a RandomnessSource. 050 * <br> 051 * Similar to the regular 32-bit Mersenne Twister but implemented with 64-bit 052 * values (Java <code>long</code>), and with different output. This generator is probably 053 * not the best to use because of known statistical problems and low speed, but its period 054 * is absurdly high, {@code pow(2, 19937) - 1}. {@link LongPeriodRNG} has significantly 055 * better speed and statistical quality, and also has a large period, {@code pow(2, 1024) - 1}. 056 * {@link IsaacRNG} is slower, but offers impeccable quality, and from its webpage, "Cycles 057 * are guaranteed to be at least {@code pow(2, 40)} values long, and they are 058 * {@code pow(2, 8295)} values long on average." IsaacRNG should be your choice if security is a 059 * concern, LongPeriodRNG if quality and speed are important, and MersenneTwister should be used 060 * if period is the only criterion to judge an RNG on. Keep in mind that extremely long periods 061 * are not always a good thing; there are known states for the Mersenne Twister that produce dozens 062 * of {@code 0} outputs in a row, which is fundamentally impossible for {@link LightRNG} or 063 * {@link DiverRNG}. It also would take longer to exhaust the period of a 128-bit-state generator 064 * (generating 100 gigabytes per second) than the amount of time humans have walked the Earth. 065 * This has 19968 bits of state... so if 128 is more than is possible to exhaust, why do you need 066 * 19968 bits, again? Consider {@link GoatRNG} if you want a high-quality 128-bit generator. 067 * <br> 068 * This is mostly a straight port of the 069 * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/C-LANG/mt19937-64.c"> 070 * C-code (mt19937-64.c)</a>, but made more "java-like". This version was originally found 071 * at <a href="https://github.com/javabeanz/javarng/blob/master/com/modp/random/MersenneTwister64.java"> 072 * an archived version of a Google Code repo</a>, and it is licensed under the 3-clause BSD license, like 073 * the Mersenne Twister. 074 * <br> 075 * References: 076 * <br> 077 * <ul> 078 * <li> 079 * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html"> 080 * The Mersenne Twister Home Page </a> 081 * </li> 082 * <li> Makato Matsumoto and Takuji Nishimura, 083 * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/mt.pdf">"Mersenne Twister:A 623-Dimensionally Equidistributed Uniform Pseudo-Random Number Generator"</a>, 084 * <i>ACM Transactions on Modeling and Computer Simulation, </i> Vol. 8, No. 1, 085 * January 1998, pp 3--30.</li> 086 * </ul> 087 * 088 * @author Nick Galbreath -- nickg [at] modp [dot] com 089 * @author Tommy Ettinger 090 * @version 1.1 -- 07-Oct-2017 091 */ 092public class MersenneTwister implements Serializable, RandomnessSource { 093 094 private static final long serialVersionUID = 1001000L; 095 096 private static final int NN = 312; 097 098 private static final int MM = 156; 099 100 private static final long MATRIX_A = 0xB5026F5AA96619E9L; 101 102 /** 103 * Mask: Most significant 33 bits 104 */ 105 private static final long UM = 0xFFFFFFFF80000000L; 106 107 /** 108 * Mask: Least significant 31 bits 109 */ 110 private static final long LM = 0x7FFFFFFFL; 111 112 /** 113 * Mersenne Twister data. 114 */ 115 private final long[] mt = new long[NN]; 116 117 /** 118 * Mersenne Twister Index. 119 */ 120 private int mti = NN + 1; 121 122 /** 123 * Internal to hold 64 bits, that might 124 * used to generate two 32 bit values. 125 */ 126 private long extra; 127 128 /** 129 * Set to true if we need to generate another 64 bits, false if we have enough bits available for an int. 130 */ 131 private boolean bitState = true; 132 133 /** 134 * Seeds this using two calls to Math.random(). 135 */ 136 public MersenneTwister() { 137 setSeed((long) ((Math.random() * 2.0 - 1.0) * 0x8000000000000L) 138 ^ (long) ((Math.random() * 2.0 - 1.0) * 0x8000000000000000L)); 139 } 140 141 /** 142 * Seeds this with the given long, which will be used to affect the large state. 143 * 144 * @param seed any long 145 */ 146 public MersenneTwister(final long seed) { 147 setSeed(seed); 148 } 149 150 /** 151 * Seeds this with the given long array, which will be used to affect the large state, and not used directly. 152 * 153 * @param seed a long array; generally should be non-null 154 */ 155 public MersenneTwister(final long[] seed) { 156 setSeed(seed); 157 } 158 159 /** 160 * Initalize the pseudo random number generator with 64 bits. 161 * Not the same as setState() in StatefulRandomness; this changes the seed quite a bit. 162 * 163 * @param seed any long 164 */ 165 public void setSeed(final long seed) { 166 mt[0] = seed; 167 for (mti = 1; mti < NN; mti++) { 168 mt[mti] = (6364136223846793005L * (mt[mti - 1] ^ (mt[mti - 1] >>> 62)) + mti); 169 } 170 } 171 172 /** 173 * Initalize the pseudo random number generator with a long array of any size, which should not be null but can be. 174 * Not the same as setState() in StatefulRandomness; this changes the seed quite a bit. 175 * 176 * @param array any long array 177 */ 178 public void setSeed(final long[] array) { 179 setSeed(19650218L); 180 if (array == null) 181 return; 182 int i = 1; 183 int j = 0; 184 int k = (Math.max(NN, array.length)); 185 for (; k != 0; k--) { 186 mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >>> 62)) * 3935559000370003845L)) 187 + array[j] + j; 188 i++; 189 j++; 190 if (i >= NN) { 191 mt[0] = mt[NN - 1]; 192 i = 1; 193 } 194 if (j >= array.length) 195 j = 0; 196 } 197 for (k = NN - 1; k != 0; k--) { 198 mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >>> 62)) * 2862933555777941757L)) 199 - i; 200 i++; 201 if (i >= NN) { 202 mt[0] = mt[NN - 1]; 203 i = 1; 204 } 205 } 206 207 mt[0] = 0x8000000000000000L; /* MSB is 1; assuring non-zero initial array */ 208 } 209 210 /** 211 * Returns up to 32 random bits. 212 * <br> 213 * The implementation splits a 64-bit long into two 32-bit chunks. 214 * @param bits the number of bits to output, between 1 and 32 (both inclusive) 215 * @return an int with the specified number of pseudo-random bits 216 */ 217 @Override 218 public int next(final int bits) { 219 //return ((int)nextLong()) >>> (32 - numbits); 220 221 if (bitState) { 222 extra = nextLong(); 223 bitState = false; 224 return (int) (extra >>> (64 - bits)); 225 } else { 226 bitState = true; 227 return ((int) extra) >>> (32 - bits); 228 } 229 } 230 231 /** 232 * Returns 64 random bits. 233 * @return a pseudo-random long, which can have any 64-bit value, positive or negative 234 */ 235 @Override 236 public long nextLong() { 237 int i; 238 long x; 239 if (mti >= NN) { /* generate NN words at one time */ 240 241 for (i = 0; i < NN - MM; i++) { 242 x = (mt[i] & UM) | (mt[i + 1] & LM); 243 mt[i] = mt[i + MM] ^ (x >>> 1) ^ (x & 1L) * MATRIX_A; 244 } 245 for (; i < NN - 1; i++) { 246 x = (mt[i] & UM) | (mt[i + 1] & LM); 247 mt[i] = mt[i + (MM - NN)] ^ (x >>> 1) ^ (x & 1L) * MATRIX_A; 248 } 249 x = (mt[NN - 1] & UM) | (mt[0] & LM); 250 mt[NN - 1] = mt[MM - 1] ^ (x >>> 1) ^ (x & 1L) * MATRIX_A; 251 252 mti = 0; 253 } 254 255 x = mt[mti++]; 256 257 x ^= (x >>> 29) & 0x5555555555555555L; 258 x ^= (x << 17) & 0x71D67FFFEDA60000L; 259 x ^= (x << 37) & 0xFFF7EEE000000000L; 260 x ^= (x >>> 43); 261 262 return x; 263 } 264 265 @Override 266 public final MersenneTwister copy() { 267 MersenneTwister f = new MersenneTwister(MATRIX_A); 268 f.mti = mti; 269 f.extra = extra; 270 f.bitState = bitState; 271 System.arraycopy(mt, 0, f.mt, 0, mt.length); 272 return f; 273 } 274 275 @Override 276 public String toString() { 277 return "MersenneTwister with state hashed as " + StringKit.hexHash(mt) + 278 " and index " + mti; 279 } 280 281 @Override 282 public boolean equals(Object o) { 283 if (this == o) return true; 284 if (o == null || getClass() != o.getClass()) return false; 285 286 MersenneTwister mt64RNG = (MersenneTwister) o; 287 288 return mti == mt64RNG.mti && extra == mt64RNG.extra && bitState == mt64RNG.bitState && Arrays.equals(mt, mt64RNG.mt); 289 } 290 291 @Override 292 public int hashCode() { 293 int result = CrossHash.hash(mt); 294 result = 31 * result + mti; 295 result = 31 * result + (int) (extra ^ (extra >>> 32)); 296 result = 31 * result + (bitState ? 1 : 0); 297 return result; 298 } 299 300}