package water.util; import java.util.Random; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.ReentrantLock; import water.H2O; public class RandomUtils { public enum RNGType { PCGRNG, MersenneTwisterRNG, JavaRNG, XorShiftRNG } private static RNGType _rngType = RNGType.PCGRNG; /* Returns the configured random generator */ public static Random getRNG(long... seed) { switch(_rngType) { case JavaRNG: return new H2ORandomRNG(seed[0]); case XorShiftRNG: return new XorShiftRNG (seed[0]); case PCGRNG: return new PCGRNG (seed[0],seed.length > 1 ? seed[1] : 1); case MersenneTwisterRNG: // Do not copy the seeds - use them, and initialize the first two ints by // seeds based given argument. The call is locked, and also // MersenneTwisterRNG will just copy the seeds into its datastructures return new MersenneTwisterRNG(ArrayUtils.unpackInts(seed)); } throw H2O.fail(); } // Converted to Java from the C /* * PCG Random Number Generation for C. * * Copyright 2014 Melissa O'Neill <oneill@pcg-random.org> * * 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. * * For additional information about the PCG random number generation scheme, * including its license and other licensing options, visit * * http://www.pcg-random.org */ public static class PCGRNG extends Random { private long _state; // Random state private long _inc; // Fixed sequence, always odd // Seed the rng. Specified in two parts, state initializer and a sequence // selection constant (a.k.a. stream id) public PCGRNG(long seed, long seq) { //need to call a super-class constructor - ugly by-product of inheritance //required for reproducibility - super() would call time-based setSeed() and modify _state to non-zero super(0); assert(_state == 0); _inc = (seq<<1)|1; nextInt(); _state += seed; nextInt(); } @Override public synchronized void setSeed(long seed) { _state = 0; nextInt(); _state += seed; nextInt(); } // CNC: PCG expects the output to be an *unsigned* int which Java does not // support. Instead we're returning a signed int, and the caller has to // figure out the sign-extension. @Override public int nextInt() { long oldstate = _state; _state = oldstate * 6364136223846793005L + _inc; int xorshifted = (int)(((oldstate >>> 18) ^ oldstate) >>> 27); int rot = (int)(oldstate >>> 59); return (xorshifted >>> rot) | (xorshifted << ((-rot) & 31)); } @Override public long nextLong() { return (((long)nextInt())<<32) | (((long)nextInt())&0xFFFFFFFFL); } @Override protected int next(int bits) { long nextseed = nextLong(); return (int) (nextseed & ((1L << bits) - 1)); } // Generate a uniformly distributed number, r, where 0 <= r < bound @Override public int nextInt(int bound) { // To avoid bias, we need to make the range of the RNG a multiple of // bound, which we do by dropping output less than a threshold. A naive // scheme to calculate the threshold would be to do // // uint32_t threshold = 0x100000000ull % bound; // // but 64-bit div/mod is slower than 32-bit div/mod (especially on 32-bit // platforms). In essence, we do // // uint32_t threshold = (0x100000000ull-bound) % bound; // // because this version will calculate the same modulus, but the LHS // value is less than 2^32. long threshold = (-(long)bound % (long)bound)&0xFFFFFFFFL; // Uniformity guarantees that this loop will terminate. In practice, it // should usually terminate quickly; on average (assuming all bounds are // equally likely), 82.25% of the time, we can expect it to require just // one iteration. In the worst case, someone passes a bound of 2^31 + 1 // (i.e., 2147483649), which invalidates almost 50% of the range. In // practice, bounds are typically small and only a tiny amount of the // range is eliminated. for (;;) { long r = ((long)nextInt()) & 0xFFFFFFFFL; if (r >= threshold) return (int)(r % bound); } } } /** Stock Java RNG, but force the initial seed to have no zeros in either the * low 32 or high 32 bits - leading to well known really bad behavior. */ public static class H2ORandomRNG extends Random { public H2ORandomRNG(long seed) { super(); if ((seed >>> 32) < 0x0000ffffL) seed |= 0x5b93000000000000L; if (((seed << 32) >>> 32) < 0x0000ffffL) seed |= 0xdb910000L; setSeed(seed); } } /** Simple XorShiftRNG. * Note: According to RF benchmarks it does not provide so accurate results * as {@link java.util.Random}, however it can be used as an alternative. */ public static class XorShiftRNG extends Random { private AtomicLong _seed; public XorShiftRNG (long seed) { _seed = new AtomicLong(seed); } @Override public long nextLong() { long oldseed, nextseed; AtomicLong seed = this._seed; do { oldseed = seed.get(); nextseed = xorShift(oldseed); } while (!seed.compareAndSet(oldseed, nextseed)); return nextseed; } @Override public int nextInt() { return nextInt(Integer.MAX_VALUE); } @Override public int nextInt(int n) { int r = (int) (nextLong() % n); return r > 0 ? r : -r; } @Override protected int next(int bits) { long nextseed = nextLong(); return (int) (nextseed & ((1L << bits) - 1)); } private long xorShift(long x) { x ^= (x << 21); x ^= (x >>> 35); x ^= (x << 4); return x; } } /** * <p> * Random number generator based on the <a * href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html" * target="_top">Mersenne Twister</a> algorithm developed by Makoto Matsumoto * and Takuji Nishimura. * </p> * * <p> * This is a very fast random number generator with good statistical properties * (it passes the full DIEHARD suite). This is the best RNG for most * experiments. If a non-linear generator is required, use the slower * <code>AESCounterRNG</code> RNG. * </p> * * <p> * This PRNG is deterministic, which can be advantageous for testing purposes * since the output is repeatable. If multiple instances of this class are * created with the same seed they will all have identical output. * </p> * * <p> * This code is translated from the original C version and assumes that we will * always seed from an array of bytes. I don't pretend to know the meanings of * the magic numbers or how it works, it just does. * </p> * * <p> * <em>NOTE: Because instances of this class require 128-bit seeds, it is not * possible to seed this RNG using the {@link #setSeed(long)} method inherited * from {@link java.util.Random}. Calls to this method will have no effect. * Instead the seed must be set by a constructor.</em> * </p> * * @author Makoto Matsumoto and Takuji Nishimura (original C version) * @author Daniel Dyer (Java port) */ public static class MersenneTwisterRNG extends Random { // Magic numbers from original C version. private static final int N = 624; private static final int M = 397; private static final int[] MAG01 = { 0, 0x9908b0df }; private static final int UPPER_MASK = 0x80000000; private static final int LOWER_MASK = 0x7fffffff; private static final int BOOTSTRAP_SEED = 19650218; private static final int BOOTSTRAP_FACTOR = 1812433253; private static final int SEED_FACTOR1 = 1664525; private static final int SEED_FACTOR2 = 1566083941; private static final int GENERATE_MASK1 = 0x9d2c5680; private static final int GENERATE_MASK2 = 0xefc60000; // Lock to prevent concurrent modification of the RNG's internal state. private final ReentrantLock lock = new ReentrantLock(); /* State vector */ private final int[] mt = new int[N]; /* Index into state vector */ private int mtIndex = 0; // public MersenneTwisterRNG(long... seeds){ // this(unpackInts(seeds)); // } /** * Creates an RNG and seeds it with the specified seed data. * * @param seedInts The seed data used to initialise the RNG. */ public MersenneTwisterRNG(int... seedInts) { // This section is translated from the init_genrand code in the C version. mt[0] = BOOTSTRAP_SEED; for( mtIndex = 1; mtIndex < N; mtIndex++ ) { mt[mtIndex] = (BOOTSTRAP_FACTOR * (mt[mtIndex - 1] ^ (mt[mtIndex - 1] >>> 30)) + mtIndex); } // This section is translated from the init_by_array code in the C version. int i = 1; int j = 0; for( int k = Math.max(N, SEEDS.length); k > 0; k-- ) { int jseeds = (j == 0 || j == 1) ? seedInts[j] : SEEDS[j]; mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >>> 30)) * SEED_FACTOR1)) + jseeds + j; i++; j++; if( i >= N ) { mt[0] = mt[N - 1]; i = 1; } if( j >= SEEDS.length ) { j = 0; } } for( int k = N - 1; k > 0; k-- ) { mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >>> 30)) * SEED_FACTOR2)) - i; i++; if( i >= N ) { mt[0] = mt[N - 1]; i = 1; } } mt[0] = UPPER_MASK; // Most significant bit is 1 - guarantees non-zero // initial array. } @Override protected final int next(int bits) { int y; try { lock.lock(); if( mtIndex >= N ) // Generate N ints at a time. { int kk; for( kk = 0; kk < N - M; kk++ ) { y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK); mt[kk] = mt[kk + M] ^ (y >>> 1) ^ MAG01[y & 0x1]; } for( ; kk < N - 1; kk++ ) { y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK); mt[kk] = mt[kk + (M - N)] ^ (y >>> 1) ^ MAG01[y & 0x1]; } y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N - 1] = mt[M - 1] ^ (y >>> 1) ^ MAG01[y & 0x1]; mtIndex = 0; } y = mt[mtIndex++]; } finally { lock.unlock(); } // Tempering y ^= (y >>> 11); y ^= (y << 7) & GENERATE_MASK1; y ^= (y << 15) & GENERATE_MASK2; y ^= (y >>> 18); return y >>> (32 - bits); } /* 624 int seeds generated from /dev/random * * SEEDS[0], and SEEDS[1] are reserved for MersenneTwister initialization in hex.rf.Utils. * They can obtain any value! * * Note: SEEDS are modified at this place. The user has to ensure proper locking. */ public static final int[] SEEDS = new int[] { 0x00000000, 0x00000000, 0x8a885b28, 0xcb618e3c, 0x6812fe78, 0xca8ca770, 0xf2a19ffd, 0xb6821eaa, 0xd1fa32c7, 0xc6dbee65, 0xd9534b7f, 0xa8e765a6, 0x2da3c864, 0xb5a7766a, 0x2bc7e671, 0xf80571d0, 0xa7174754, 0xf3234de2, 0x4e7cc080, 0x1140d082, 0x5fad93ab, 0x8cce5b9f, 0x1872465a, 0x6b42ecd3, 0x2c8c9653, 0x453a2eef, 0xcc508838, 0x5a85a0e1, 0x3b7a05e9, 0x2ac09cfd, 0x88aa58c6, 0xd9680c83, 0x061c1189, 0xc5ce6f21, 0x0acff61d, 0x3f550f57, 0xfce253ce, 0x72f39c54, 0x1772831b, 0x7f61413f, 0x5971d316, 0x38306f1e, 0xe4102ecc, 0xe64f0fc5, 0x3bc7ba66, 0x739ef534, 0x1379892e, 0x8f608758, 0x4828e965, 0xf4ac7b9a, 0xa8ddaba3, 0x50f8b1cb, 0xfec0f9d0, 0x842537e7, 0x5e6231bf, 0xef3ae390, 0x420f8f3a, 0xeedd75cc, 0xe3c10283, 0x5c38cbd6, 0x662c8b91, 0x2cd589d5, 0xe28522a7, 0xda03a7b4, 0xb29877dc, 0x45a109fb, 0x99c3021e, 0x0af14661, 0xe85d6e6e, 0xbdaa929b, 0x940e053d, 0x861e7d7d, 0x73ae673f, 0x8491c460, 0xc01be6a4, 0x06e0818c, 0x142f7399, 0xc80a6a41, 0x45600653, 0x1c0516d5, 0xd2ff0694, 0xb1cb723d, 0x73f355e0, 0x076cb63a, 0x7db7190f, 0x35ea0b80, 0xa36f646b, 0xb9ebfa2f, 0x3844839b, 0x58d80a19, 0x1f3d8746, 0x229bb12e, 0x0ac3846d, 0xd2f43715, 0x04aaeb46, 0xacc87633, 0x7dd5b268, 0xba3651fc, 0xd76801e6, 0x9e413be6, 0xb31b71c5, 0x5fd36451, 0x4041662e, 0x8e87487b, 0x03126116, 0x6574b757, 0x7717d040, 0x1d15c783, 0x7a167e9c, 0x8e4ec7a0, 0x749bc3e5, 0xfa2ea1b1, 0x25df2c84, 0xf9e7ae19, 0xe071597a, 0x6ae0fb27, 0x12380f69, 0xf672e42f, 0x5425f6f6, 0xed6e16b7, 0x36b29279, 0x24cbd8fb, 0x4d682009, 0x0e17116c, 0x10428b6b, 0xe463f573, 0x2c5ff8d0, 0x1102b138, 0xc544907c, 0xcf403704, 0x2565d0ec, 0x67e3111c, 0xc5097632, 0xe3505d2d, 0xb0a31246, 0x55cbffb3, 0xf2b662cb, 0x944ba74f, 0xf64a1136, 0x67628af5, 0x1d442a18, 0x31c8c7d4, 0x648a701b, 0x563930c4, 0x28ecd115, 0x9959be3f, 0x9afa938d, 0x0c40f581, 0x8ec73f72, 0x20dbf8a1, 0x2c2ca035, 0xb81f414c, 0xfc16c15c, 0xec386121, 0x41d8bd3a, 0x60eab9ce, 0x9f4b093d, 0x56e5bb7c, 0x0d60cd53, 0x3238a405, 0xa159ab87, 0xdadaaed3, 0xc86b574f, 0x9ed3b528, 0x3137e717, 0x028012fc, 0x8477ea87, 0x6477d097, 0x06b6e294, 0x1dd29c4e, 0x5c732920, 0xc760bcec, 0x5d40a29a, 0xc581f784, 0x13b46a5e, 0xf6761ea7, 0x1b4ee8c3, 0x1637d570, 0x0c00569a, 0xd01cb95e, 0x87343e82, 0x17190e4c, 0x357078a3, 0x3b59246c, 0xdf11b5e7, 0x68971c7a, 0xcc3d497e, 0x21659527, 0x2c211ba2, 0xf34aa1ee, 0x4a07f67e, 0x7ae0eacd, 0xe05bdc85, 0xfe2347a7, 0xebc4be3f, 0x1f033044, 0x82e2a46e, 0x75c66f49, 0x56c50b1e, 0xc20f0644, 0x798ec011, 0x9eba0c81, 0x0fe34e70, 0x28061a7f, 0x26536ace, 0x6541a948, 0x305edffe, 0x25eaa0a9, 0xef64db75, 0xe1f4d734, 0xe27e22de, 0x3b68a4b3, 0x8917d09f, 0x402f7e99, 0xe9b3e3e7, 0x9a95e6fb, 0x42a5725c, 0x00d9f288, 0x9e893c59, 0x3771df6d, 0xbfb39333, 0x9039fd17, 0x3d574609, 0xb8a44bc4, 0xe12f34ad, 0x7f165a6c, 0x8e13ec33, 0xa8d935be, 0x00ac09d8, 0x3ffff87b, 0xda94be75, 0x8b1804d5, 0xd1ac4301, 0xc2b4101d, 0xb8dae770, 0x3062dbf0, 0xc5defd8d, 0xa791e2aa, 0x678f3924, 0xec4ea145, 0x457c82b5, 0x6698be3c, 0xfbd4913f, 0xff52ad6d, 0x54c7f66d, 0x7d6ec779, 0x9ce9d1d9, 0x384dd1eb, 0xb4b4d565, 0xa5736588, 0x33ae82b2, 0x051221b0, 0x11a8775f, 0xd2ed52ea, 0xdf99b00b, 0xa0425a1a, 0xd6b32a9b, 0xfa162152, 0x4de98efb, 0xb0d5553e, 0xdd9d7239, 0x05be808d, 0x438f6f74, 0xdf28fc47, 0xb6fcd76d, 0x58375c21, 0x1a88eae6, 0x1ce15ca9, 0x46304120, 0xc2a8c9ee, 0xa2eaf06e, 0xf548a76c, 0xd288b960, 0xec1c7cb5, 0x6e59f189, 0x3424b4eb, 0x521220db, 0x9d2f797d, 0x8561d680, 0x63eda823, 0x7f406b58, 0x31104105, 0x1a457dc1, 0x3a94cec4, 0xed5a24b7, 0xa11766a2, 0xefd011e1, 0x10806e51, 0x5519474f, 0x08d1a66f, 0xc83ac414, 0xf9dad4f5, 0xfa64b469, 0x6cbfd6a3, 0xb2e787ce, 0x63eb2f8e, 0xe0d36a89, 0xe232fe8f, 0xd0d28011, 0xd198ab29, 0x1e5aa524, 0x05ae372d, 0x314fb7fb, 0x7e263de0, 0x61e8d239, 0x2f76e5b6, 0xaf2af828, 0x4146a159, 0x3626bccf, 0x308a82ed, 0x1e5527a3, 0xe540898d, 0xb2e944de, 0x010007fd, 0xaabb40cc, 0xa119fd6b, 0xefca25a8, 0xd1389d26, 0x15b65a4b, 0xf1323150, 0x3798f801, 0xf5787776, 0xcd069f96, 0x91da0117, 0xb603eaa4, 0xb068125e, 0x346216d5, 0xcb0af099, 0xad8131db, 0x1c5ce132, 0x3a094b8a, 0x68d20e3f, 0x6f62b0b9, 0x5b2da8a9, 0x11530b9a, 0x5c340608, 0x9b23c1d9, 0xf175fcba, 0x70fddd5e, 0x9c554ec4, 0xfc0cb505, 0x5249997f, 0xc42f151f, 0xee9f506f, 0x8fb2cd27, 0xb799db4b, 0x4c5c0eeb, 0x37278283, 0x8183b362, 0x928b4cc7, 0x6c895352, 0x9b0a8270, 0xc5cb93da, 0xf8268a31, 0x09fd1af6, 0xbc6e89fc, 0x5a614eb8, 0xe55b1348, 0x992a69ee, 0x55b0ffb7, 0x4eb5db62, 0x5cde9e6b, 0xad9b186d, 0xa5006f43, 0xc82c2c7f, 0x822fa75f, 0xa3a4cb06, 0x6d05edda, 0x5bf76fb7, 0x846a54f8, 0xca7ce73c, 0x43c1a8d1, 0x1b4c79a7, 0x85cb66c7, 0xc541b4ad, 0x07e69a11, 0xffb1e304, 0xe585f233, 0x506773a5, 0xc7adaa3c, 0xf980d0c6, 0xa3d90125, 0xfbce4232, 0xfe6fed8f, 0xe17f437a, 0x29c45214, 0xa0ea1046, 0xc025f727, 0x820202ca, 0x554f4e76, 0x5389096c, 0x7d58de96, 0xe32295b8, 0x689b5fbe, 0xdfefacf1, 0xd4facb70, 0x0cf3703e, 0x78fec105, 0x57b53e14, 0x54bcd2ef, 0x335f4d0d, 0x58552c2e, 0xf64df202, 0x0e5c3565, 0xa4cb22c5, 0xd91c91c1, 0x7827bb3f, 0x37b456e3, 0x84950a9e, 0x273edcd7, 0xddaa5ebd, 0xb1f46855, 0xe0052b20, 0xcfb04082, 0xa449e49b, 0xfd95e21c, 0xa9f477c0, 0xacf0be15, 0x611d1edc, 0xb3dca16a, 0x781efb9a, 0x6480c096, 0x4e545269, 0xbc836952, 0xd511b539, 0xdf6248b4, 0x8ff7da61, 0x0756106d, 0x92f04a17, 0xee649e83, 0x14e35780, 0x6dc76815, 0x0fe032bb, 0x1fd66462, 0x0f4be990, 0x1627c658, 0xb95f902d, 0xa6f9e4e9, 0xb7b9aa16, 0x6a0a31d5, 0x647129e6, 0x071f89b7, 0xe4033ca9, 0xd81b3f59, 0x74f8a887, 0xc44bc880, 0xf1c2d04c, 0xf9e246c9, 0x529f9c45, 0x14d322e7, 0x8c3305b1, 0x8dd9a988, 0x8a92b883, 0x47574eb3, 0x7b5779f4, 0x759a4eb6, 0xc8ed6a11, 0x42a4e0ee, 0xf4603b1d, 0x790d9126, 0xa261034e, 0x94569718, 0x5f57c893, 0xa1c2486a, 0x6727618f, 0xcfb7c5b3, 0xa4c2f232, 0x33b5e051, 0x9ed6c2d0, 0x16f3ec37, 0x5c7c96ba, 0x3a16185f, 0x361d6c17, 0xa179808b, 0xb6751231, 0xc8486729, 0x873fc8ab, 0xe7f78a78, 0x2fd3093b, 0x489efe89, 0x83628cd1, 0x67ad9faa, 0x623cbc2f, 0x3f01e8c4, 0xfdad453f, 0x2ccfb969, 0x5d2a3806, 0x9e3df87a, 0x04700155, 0xab7b57ef, 0x262d746b, 0x737aa3e3, 0x949c724c, 0xa4120c39, 0xb0d6fc26, 0xf627a213, 0xc0a0bc60, 0x24d6564a, 0x34d460dd, 0x785b0656, 0x9376f6a5, 0x25ebee5b, 0x5a0a5018, 0x84d02b01, 0xa2b3658a, 0xad0d1cce, 0x38271683, 0x9f491585, 0x8ba28247, 0x40d5a42e, 0x7780e82e, 0x4211ccc3, 0x99da0844, 0xb85f9474, 0xbdb158b6, 0xf8194c71, 0x6339f3ec, 0x4cd66cf7, 0xb636aa4f, 0x4068c56c, 0xe41080a1, 0x55740173, 0x95903235, 0x90f39f69, 0x3f10a4e2, 0x3192a79b, 0x0590a944, 0xc9058c4f, 0x6f05a8eb, 0xdb326d13, 0xfcefbcee, 0xa699db05, 0xd819d477, 0x610f7e52, 0xfa0a4aca, 0x0e6b3f1d, 0x7a8da290, 0x6d12a9ef, 0xa12642d5, 0xebdedcff, 0x175ed926, 0xa094363a, 0xb3a07e30, 0x34fa8d2c, 0xbc16e646, 0x3e6de94d, 0xd5288754, 0x204e5283, 0xc61106f6, 0x299835e0, 0xe04e7a38, 0x2e2c1e34, 0xc069ea80, 0x5c2117cf, 0xd8fc2947, 0x10a40dc9, 0xb40dacd9, 0xfbdac86b, 0x2a8383cb, 0x46d86dc1, 0x0a1f3958, 0x0f7e59ea, 0x5c10a118, 0xea13bfc8, 0xc82c0da5, 0x4cd40dd7, 0xdaa5dfe9, 0x8c2cc0a3, 0x8dc15a64, 0x241b160c, 0xc44f573b, 0x3eb3155f, 0x284ba3fc, 0x1ece8db4, 0x03eaf07f, 0x7cbd99fb, 0x7d313b45, 0xe7ea83a7, 0x6d339d60, 0x0ef002cb, 0x92a04b40, 0x510d79bc, 0x6440e050, 0x33916596, 0xa11c5df3, 0xb582a3de, 0x031001c1, 0x85951218, 0xbe538ada, 0xe3aec1d2, 0x7fb67836, 0xc2d9ab84, 0xb1841ad9, 0x1e64cc5f, 0xa3fe111d, 0xd081d6bb, 0xf8ae6c3b, 0x3b12ae4c, 0x9ba5eb58, 0x22931b18, 0xf99b2e61, 0x628f1252, 0x2fce9aa0, 0xf99a04fb, 0x21577d22, 0x9d474c81, 0x7350e54a, 0xf88c8ac6, 0x94f38853, 0x0b6333fe, 0x8875045e, 0x90c23689, 0x6b08a34b, 0x3fb742ea, 0xa8a9466a, 0xd543807d, 0xbf12e26e, 0x10211c25, 0x068852e1, 0xf1d8f035, 0x012a5782, 0xe84cbf5f, 0xee35a87a, 0x8bfa2f09, }; } }