All Downloads are FREE. Search and download functionalities are using the official Maven repository.

math.rng.MersenneTwister64 Maven / Gradle / Ivy

Go to download

Elementary math utilities with a focus on random number generation, non-linear optimization, interpolation and solvers

The newest version!
/*
 * Copyright 2013, 2021 Stefan Zobel
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ====================================================
 * This is a port from the C code at
 * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/C-LANG/mt19937-64.c
 * .
 * 
 *  Copyright (C) 2004, Makoto Matsumoto and Takuji Nishimura,
 *  All rights reserved.                          
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 *    3. The names of its contributors may not be used to endorse or promote 
 *       products derived from this software without specific prior written 
 *       permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================
 */
package math.rng;

import java.security.SecureRandom;

/**
 * 64-bit Mersenne Twister. This generator has a period of
 * 219937 − 1. It is 3 to 7 times faster than
 * {@link java.util.Random} depending on the kind of output you want. Mersenne
 * Twister (mostly in its 32-bit incarnation) has been the de facto
 * standard PRNG for scientific applications in the last two decades.
 * 

* The recursion is similar to the 32-bit Mersenne Twister but different, so the * output is totally different from the 32-bit version. *

*

* This is a port of the "mt19937-64.c" C code (2004/9/29 version). *

* See: The * Mersenne Twister Home Page */ public class MersenneTwister64 extends AbstractRng64 { private static final int NN = 312; private static final int MM = 156; private static final long MATRIX_A = 0xb5026f5aa96619e9L; /* Most significant 33 bits */ private static final long UM = 0xffffffff80000000L; /* Least significant 31 bits */ private static final long LM = 0x7fffffffL; private static final long[] mag01 = { 0L, MATRIX_A }; private static final MersenneTwister64 defaultRng = createDefaultRng(); /* The array for the state vector */ private long[] mt = new long[NN]; /* mti == NN + 1 means mt[] is not initialized */ private int mti = NN + 1; public MersenneTwister64() { setSeed(XorShift1024Star.getDefault().nextLong()); saveSeed(mt); } public MersenneTwister64(long seed) { setSeed(seed == 0L ? -1L : seed); saveSeed(mt); } public MersenneTwister64(long[] seedArray) { setSeed(seedArray); saveSeed(mt); } /* * Initialize the RNG with a 64-bit seed. */ private void setSeed(long seed) { mt[0] = seed; for (mti = 1; mti < NN; mti++) { mt[mti] = (6364136223846793005L * (mt[mti - 1] ^ (mt[mti - 1] >>> 62)) + mti); } } /* * Initialize the RNG by an array. */ private void setSeed(long[] seedArray) { setSeed(19650218L); // birthday of Makoto Matsumoto int i = 1; int j = 0; int k = (NN > seedArray.length ? NN : seedArray.length); for (; k != 0; k--) { mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >>> 62)) * 3935559000370003845L)) + seedArray[j] + j; /* non linear */ i++; j++; if (i >= NN) { mt[0] = mt[NN - 1]; i = 1; } if (j >= seedArray.length) { j = 0; } } for (k = NN - 1; k != 0; k--) { mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >>> 62)) * 2862933555777941757L)) - i; /* non linear */ i++; if (i >= NN) { mt[0] = mt[NN - 1]; i = 1; } } mt[0] = 1L << 63; /* MSB is 1; assuring non-zero initial array */ } public final long nextLong() { long x; if (mti >= NN) { /* generate NN words at one time */ int i; for (i = 0; i < NN - MM; i++) { x = (mt[i] & UM) | (mt[i + 1] & LM); mt[i] = mt[i + MM] ^ (x >>> 1) ^ mag01[(int) (x & 1L)]; } for (; i < NN - 1; i++) { x = (mt[i] & UM) | (mt[i + 1] & LM); mt[i] = mt[i + (MM - NN)] ^ (x >>> 1) ^ mag01[(int) (x & 1L)]; } x = (mt[NN - 1] & UM) | (mt[0] & LM); mt[NN - 1] = mt[MM - 1] ^ (x >>> 1) ^ mag01[(int) (x & 1L)]; mti = 0; } x = mt[mti++]; x ^= (x >>> 29) & 0x5555555555555555L; x ^= (x << 17) & 0x71d67fffeda60000L; x ^= (x << 37) & 0xfff7eee000000000L; x ^= (x >>> 43); return x; } public static PseudoRandom getDefault() { return defaultRng; } private static MersenneTwister64 createDefaultRng() { final long[] randSeed = new long[NN]; try { SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); for (int i = 0; i < NN; ++i) { randSeed[i] = sr.nextLong(); } } catch (Exception e) { PseudoRandom rng = XorShift1024Star.getDefault(); for (int i = 0; i < NN; ++i) { randSeed[i] = rng.nextLong(); } } return new MersenneTwister64(randSeed); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy