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

stream.generator.SFMT19937 Maven / Gradle / Ivy

The newest version!
/*
 *  streams library
 *
 *  Copyright (C) 2011-2014 by Christian Bockermann, Hendrik Blom
 * 
 *  streams is a library, API and runtime environment for processing high
 *  volume data streams. It is composed of three submodules "stream-api",
 *  "stream-core" and "stream-runtime".
 *
 *  The streams library (and its submodules) is free software: you can 
 *  redistribute it and/or modify it under the terms of the 
 *  GNU Affero General Public License as published by the Free Software 
 *  Foundation, either version 3 of the License, or (at your option) any 
 *  later version.
 *
 *  The stream.ai library (and its submodules) is distributed in the hope
 *  that it will be useful, but WITHOUT ANY WARRANTY; without even the implied 
 *  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see http://www.gnu.org/licenses/.
 */
package stream.generator;

/**
 * An adapation of  SFMT
 * (SIMD oriented Fast Mersenne Twister) version 1.3 by Mutsuo Saito
 * (Hiroshima University) and Makoto Matsumoto (Hiroshima University). This
 * adapation supports only the period 219937 − 1; the original
 * supports some longer and shorter periods.
 * 
 * 

* The license (a modified BSD License) for the original C code from which this * code is adapted: * *

 * Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima
 * University. All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of the Hiroshima University nor the names of
 *       its contributors may 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.
 * 
* * @author Adrian King (ceroxylon at hotmail.com) */ public class SFMT19937 { // Static variables // //////////////////////////////////////////////////////////// /** * Mersenne Exponent. The period of the sequence is a multiple of 2 * MEXP − 1. If you adapt this code to support a * different exponent, you must change many of the other constants here as * well; consult the original C code. */ public final static int MEXP = 19937; /** * The SFMT generator has an internal state array of 128-bit integers, and * N is its size. */ final static int N = MEXP / 128 + 1; /** * N32 is the size of internal state array when regarded as an * array of 32-bit integers. */ public final static int N32 = N * 4; /** * The pick up position of the array. */ final static int POS1 = 122; /** * The parameter of shift left as four 32-bit registers. */ final static int SL1 = 18; /** * The parameter of shift left as one 128-bit register. The 128-bit integer * is shifted by SL2 * 8 bits. */ final static int SL2 = 1; /** * The parameter of shift right as four 32-bit registers. */ final static int SR1 = 11; /** * The parameter of shift right as one 128-bit register. The 128-bit integer * is shifted by SL2 * 8 bits. */ final static int SR2 = 1; /** * A bitmask parameter, used in the recursion to break symmetry of SIMD. */ final static int MSK1 = 0xdfffffef; /** * A bitmask parameter, used in the recursion to break symmetry of SIMD. */ final static int MSK2 = 0xddfecb7f; /** * A bitmask parameter, used in the recursion to break symmetry of SIMD. */ final static int MSK3 = 0xbffaffff; /** * A bitmask parameter, used in the recursion to break symmetry of SIMD. */ final static int MSK4 = 0xbffffff6; /** * Part of a 128-bit period certification vector. */ final static int PARITY1 = 0x00000001; /** * Part of a 128-bit period certification vector. */ final static int PARITY2 = 0x00000000; /** * Part of a 128-bit period certification vector. */ final static int PARITY3 = 0x00000000; /** * Part of a 128-bit period certification vector. */ final static int PARITY4 = 0x13c9e684; /** * A parity check vector which certifies the period of 2{@link #MEXP} * . */ final static int parity[] = { PARITY1, PARITY2, PARITY3, PARITY4 }; /** * A number mixed with the time of day to provide a unique seed to each * generator of this type allocated. */ static long uniquifier = 314159265358979L; // Instance variables // ////////////////////////////////////////////////////////// /** * The internal state array. Blocks of four consecutive ints * are often treated as a single 128-bit integer that is * little-endian—that is, its low-order bits are at lower indices in * the array, and high-order bits at higher indices. */ final int[] sfmt = new int[N32]; /** * Index counter of the next int to return from {@link #next}. */ int idx = N32; // Constructors // //////////////////////////////////////////////////////////////// /** * Constructor that initially uses a seed based on the time of day. */ public SFMT19937() { this(System.nanoTime() + uniquifier++); } /** * Constructor that initializes the internal state array by calling * {@link #setSeed} with the specified argument. * * @param seed * initial seed for this generator. */ public SFMT19937(long seed) { setSeed(seed); } // Instance methods // //////////////////////////////////////////////////////////// /** * Applies the recursion formula. * * @param r * output array. * @param rI * index in r. * @param a * state array. * @param aI * index in a. * @param b * state array. * @param bI * index in b. * @param c * state array. * @param cI * index in c. * @param d * state array. * @param dI * index in d. */ void doRecursion(int[] r, int rI, int[] a, int aI, int[] b, int bI, int[] c, int cI, int[] d, int dI) { // 128-bit shift: x = a << SL2 * 8: final int lShift = SL2 * 8; int a0 = a[aI], a1 = a[aI + 1], a2 = a[aI + 2], a3 = a[aI + 3]; // for SL2 <= 3, this is more concise, but possibly not as fast (haven't // timed it): // int x0 = a0 << lShift, // x1 = (a1 << lShift) | (a0 >>> (32 - lShift)), // x2 = (a2 << lShift) | (a1 >>> (32 - lShift)), // x3 = (a3 << lShift) | (a2 >>> (32 - lShift)); long hi = ((long) a3 << 32) | (a2 & (-1L >>> 32)), lo = ((long) a1 << 32) | (a0 & (-1L >>> 32)), outLo = lo << lShift, outHi = (hi << lShift) | (lo >>> (64 - lShift)); int x0 = (int) outLo, x1 = (int) (outLo >>> 32), x2 = (int) outHi, x3 = (int) (outHi >>> 32); // 128-bit shift: y = c >>> SR2 * 8: final int rShift = SR2 * 8; hi = ((long) c[cI + 3] << 32) | (c[cI + 2] & (-1L >>> 32)); lo = ((long) c[cI + 1] << 32) | (c[cI] & (-1L >>> 32)); outHi = hi >>> rShift; outLo = (lo >>> rShift) | (hi << (64 - rShift)); int y0 = (int) outLo, y1 = (int) (outLo >>> 32), y2 = (int) outHi, y3 = (int) (outHi >>> 32); // rest of forumula: r[rI] = a0 ^ x0 ^ ((b[bI] >>> SR1) & MSK1) ^ y0 ^ (d[dI] << SL1); r[rI + 1] = a1 ^ x1 ^ ((b[bI + 1] >>> SR1) & MSK2) ^ y1 ^ (d[dI + 1] << SL1); r[rI + 2] = a2 ^ x2 ^ ((b[bI + 2] >>> SR1) & MSK3) ^ y2 ^ (d[dI + 2] << SL1); r[rI + 3] = a3 ^ x3 ^ ((b[bI + 3] >>> SR1) & MSK4) ^ y3 ^ (d[dI + 3] << SL1); } /** * Fills the internal state array with pseudorandom integers. */ void genRandAll() { int i = 0, r1 = 4 * (N - 2), r2 = 4 * (N - 1); for (; i < 4 * (N - POS1); i += 4) { doRecursion(sfmt, i, sfmt, i, sfmt, i + 4 * POS1, sfmt, r1, sfmt, r2); r1 = r2; r2 = i; } for (; i < 4 * N; i += 4) { doRecursion(sfmt, i, sfmt, i, sfmt, i + 4 * (POS1 - N), sfmt, r1, sfmt, r2); r1 = r2; r2 = i; } } /** * Fills a user-specified array with pseudorandom integers. * * @param array * 128-bit array to be filled with pseudorandom numbers. * @param size * number of elements of array to fill. * @throws IllegalArgumentException * if size is greater than the length of * array, or if size is less than * {@link #N32}, or is not a multiple of 4. */ void genRandArray(int[] array, int size) { if (size > array.length) throw new IllegalArgumentException("Given size " + size + " exceeds array length " + array.length); if (size < N32) throw new IllegalArgumentException("Size must be at least " + N32 + ", but is " + size); if (size % 4 != 0) throw new IllegalArgumentException("Size must be a multiple of 4: " + size); int i = 0, j = 0, r1I = 4 * (N - 2), r2I = 4 * (N - 1); int[] r1 = sfmt, r2 = sfmt; for (; i < 4 * (N - POS1); i += 4) { doRecursion(array, i, sfmt, i, sfmt, i + 4 * POS1, r1, r1I, r2, r2I); r1 = r2; r1I = r2I; r2 = array; r2I = i; } for (; i < 4 * N; i += 4) { doRecursion(array, i, sfmt, i, array, i + 4 * (POS1 - N), r1, r1I, r2, r2I); assert r1 == r2; r1I = r2I; assert r2 == array; r2I = i; } for (; i < size - 4 * N; i += 4) { doRecursion(array, i, array, i - 4 * N, array, i + 4 * (POS1 - N), r1, r1I, r2, r2I); assert r1 == r2; r1I = r2I; assert r2 == array; r2I = i; } for (; j < 4 * 2 * N - size; j++) sfmt[j] = array[j + size - 4 * N]; for (; i < size; i += 4, j += 4) { doRecursion(array, i, array, i - 4 * N, array, i + 4 * (POS1 - N), r1, r1I, r2, r2I); assert r1 == r2; r1I = r2I; assert r2 == array; r2I = i; sfmt[j] = array[i]; sfmt[j + 1] = array[i + 1]; sfmt[j + 2] = array[i + 2]; sfmt[j + 3] = array[i + 3]; } } /** * Used by {@link #initByArray}. * * @param x * 32-bit integer. * @return 32-bit integer. */ int func1(int x) { return (x ^ (x >>> 27)) * 1664525; } /** * Used by {@link #initByArray}. * * @param x * 32-bit integer. * @return 32-bit integer. */ int func2(int x) { return (x ^ (x >>> 27)) * 1566083941; } /** * Certifies the period of 2{@link #MEXP}. */ void periodCertification() { int inner = 0; for (int i = 0; i < 4; i++) inner ^= sfmt[i] & parity[i]; for (int i = 16; i > 0; i >>= 1) inner ^= inner >> i; if ((inner & 1) != 0) // check OK return; for (int i = 0; i < 4; i++) { int work = 1; for (int j = 0; j < 32; j++) { if ((work & parity[i]) != 0) { sfmt[i] ^= work; return; } work <<= 1; } } } /** * Returns the smallest array size allowed as an argument to * {@link #fillArray}. */ public int minArraySize() { return N32; } /** * Generates and returns the next 32-bit pseudorandom number. * * @return next number. */ public int next() { if (idx >= N32) { genRandAll(); idx = 0; } return sfmt[idx++]; } /** * Fills the given array with pseudorandom 32-bit integers. Equivalent to * {@link #fillArray(int[],int)} applied to * (array,array.length). * * @param array * array to fill. */ public void fillArray(int[] array) { genRandArray(array, array.length); } /** * Fills the given array with the specified number of pseudorandom 32-bit * integers. The specified number of elements must be a multiple of four. * * @param array * array to fill. * @param elems * the number of elements of array (starting at * index zero) to fill; subsequent elements are not modified. * @throws IllegalArgumentException * if elems is greater than the length of * array, or is less than {@link #N32}, or is not a * multiple of 4. */ public void fillArray(int[] array, int elems) { genRandArray(array, elems); idx = N32; } /** * Initializes the internal state array with a 32-bit seed. * * @param seed * 32-bit seed. */ public void setIntSeed(int seed) { sfmt[0] = seed; for (int i = 1; i < N32; i++) { int prev = sfmt[i - 1]; sfmt[i] = 1812433253 * (prev ^ (prev >>> 30)) + i; } periodCertification(); idx = N32; } /** * Initializes the internal state array with a 64-bit seed. * * @param seed * 64-bit seed. */ public void setSeed(long seed) { initByArray((int) seed, (int) (seed >>> 32)); } /** * Initializes the internal state array with an array of 32-bit integers. * * @param key * array of 32-bit integers, used as a seed. */ public void initByArray(int... key) { @SuppressWarnings("unused") int lag = N32 >= 623 ? 11 : N32 >= 68 ? 7 : N32 >= 39 ? 5 : 3, mid = (N32 - lag) / 2; for (int i = sfmt.length - 1; i >= 0; i--) sfmt[i] = 0x8b8b8b8b; int count = key.length >= N32 ? key.length : N32 - 1, r = func1(0x8b8b8b8b); sfmt[mid] += r; r += key.length; sfmt[mid + lag] += r; sfmt[0] = r; int i = 1, j = 0; for (; j < count && j < key.length; j++) { r = func1(sfmt[i] ^ sfmt[(i + mid) % N32] ^ sfmt[(i + N32 - 1) % N32]); sfmt[(i + mid) % N32] += r; r += key[j] + i; sfmt[(i + mid + lag) % N32] += r; sfmt[i] = r; i = (i + 1) % N32; } for (; j < count; j++) { r = func1(sfmt[i] ^ sfmt[(i + mid) % N32] ^ sfmt[(i + N32 - 1) % N32]); sfmt[(i + mid) % N32] += r; r += i; sfmt[(i + mid + lag) % N32] += r; sfmt[i] = r; i = (i + 1) % N32; } for (j = 0; j < N32; j++) { r = func2(sfmt[i] + sfmt[(i + mid) % N32] + sfmt[(i + N32 - 1) % N32]); sfmt[(i + mid) % N32] ^= r; r -= i; sfmt[(i + mid + lag) % N32] ^= r; sfmt[i] = r; i = (i + 1) % N32; } periodCertification(); idx = N32; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy