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

src.it.unimi.dsi.util.XorShift128PlusRandomGenerator Maven / Gradle / Ivy

package it.unimi.dsi.util;

/*
 * DSI utilities
 *
 * Copyright (C) 2013-2017 Sebastiano Vigna
 *
 *  This library is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU Lesser General Public License as published by the Free
 *  Software Foundation; either version 3 of the License, or (at your option)
 *  any later version.
 *
 *  This library 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 Lesser General Public License
 *  for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this program; if not, see .
 *
 */


import it.unimi.dsi.Util;
import it.unimi.dsi.fastutil.HashCommon;
import it.unimi.dsi.logging.ProgressLogger;

import java.util.Random;

import org.apache.commons.math3.random.AbstractRandomGenerator;
import org.apache.commons.math3.random.RandomGenerator;

/** A fast, high-quality {@linkplain RandomGenerator pseudorandom number generator} that
 * returns the sum of consecutive outputs of a Marsaglia Xorshift generator (described in “Xorshift RNGs”, Journal of
 * Statistical Software, 8:1−6, 2003) with 128 bits of state.
 * It is presently used in the JavaScript engines of
 * Chrome,
 * Firefox,
 * Safari and Edge.
 *
 * 

Warning: this generator has been superseded by {@link XoRoShiRo128PlusRandom}, * which is faster and has stronger statistical properties. * *

More details can be found in my paper “Further scramblings * of Marsaglia's xorshift generators”, Journal of Computational and Applied Mathematics, 315:175−181, 2016, and * on the xoroshiro+/xorshift*/xorshift+ * generators and the PRNG shootout page. * The basic idea is taken from Mutsuo Saito and Makuto Matsumoto's * XSadd generator, which * is however based on 32-bit shifts and fails several statistical tests when reversed. * *

Note that this is * not a cryptographic-strength pseudorandom number generator, but its quality is * preposterously higher than {@link Random}'s, and its cycle length is * 2128 − 1, which is more than enough for any single-thread application. * *

By using the supplied {@link #jump()} method it is possible to generate non-overlapping long sequences * for parallel computations. This class provides also a {@link #split()} method to support recursive parallel computations, in the spirit of * Java 8's SplittableRandom. * * @see it.unimi.dsi.util * @see RandomGenerator * @see XorShift128PlusRandom * @deprecated Please use {@link XoRoShiRo128PlusRandomGenerator} instead. */ @Deprecated public class XorShift128PlusRandomGenerator extends AbstractRandomGenerator { /** The internal state of the algorithm. */ private long s0, s1; /** Creates a new generator seeded using {@link Util#randomSeed()}. */ public XorShift128PlusRandomGenerator() { this(Util.randomSeed()); } /** Creates a new generator using a given seed. * * @param seed a seed for the generator. */ public XorShift128PlusRandomGenerator(final long seed) { setSeed(seed); } @Override public long nextLong() { long s1 = this.s0; final long s0 = this.s1; this.s0 = s0; s1 ^= s1 << 23; return (this.s1 = (s1 ^ s0 ^ (s1 >>> 18) ^ (s0 >>> 5))) + s0; } @Override public int nextInt() { return (int)nextLong(); } @Override public int nextInt(final int n) { return (int)nextLong(n); } /** Returns a pseudorandom uniformly distributed {@code long} value * between 0 (inclusive) and the specified value (exclusive), drawn from * this random number generator's sequence. The algorithm used to generate * the value guarantees that the result is uniform, provided that the * sequence of 64-bit values produced by this generator is. * * @param n the positive bound on the random number to be returned. * @return the next pseudorandom {@code long} value between {@code 0} (inclusive) and {@code n} (exclusive). */ public long nextLong(final long n) { if (n <= 0) throw new IllegalArgumentException(); // No special provision for n power of two: all our bits are good. for(;;) { final long bits = nextLong() >>> 1; final long value = bits % n; if (bits - value + (n - 1) >= 0) return value; } } @Override public double nextDouble() { return (nextLong() >>> 11) * 0x1.0p-53; } @Override public float nextFloat() { return (nextLong() >>> 40) * 0x1.0p-24f; } @Override public boolean nextBoolean() { return nextLong() < 0; } @Override public void nextBytes(final byte[] bytes) { int i = bytes.length, n = 0; while(i != 0) { n = Math.min(i, 8); for (long bits = nextLong(); n-- != 0; bits >>= 8) bytes[--i] = (byte)bits; } } private static final long JUMP[] = { 0x8a5cd789635d2dffL, 0x121fd2155c472f96L }; /** The the jump function for this generator. It is equivalent to 264 * calls to {@link #nextLong()}; it can be used to generate 264 * non-overlapping subsequences for parallel computations. */ public void jump() { long s0 = 0; long s1 = 0; for(int i = 0; i < JUMP.length; i++) for(int b = 0; b < 64; b++) { if ((JUMP[i] & 1L << b) != 0) { s0 ^= this.s0; s1 ^= this.s1; } nextLong(); } this.s0 = s0; this.s1 = s1; } /** * Returns a new instance that shares no mutable state * with this instance. The sequence generated by the new instance * depends deterministically from the state of this instance, * but the probability that the sequence generated by this * instance and by the new instance overlap is negligible. * * @return the new instance. */ public XorShift128PlusRandomGenerator split() { final XorShift128PlusRandomGenerator split = new XorShift128PlusRandomGenerator(); split.s0 = HashCommon.murmurHash3(s0); split.s1 = HashCommon.murmurHash3(s1); return split; } /** Sets the seed of this generator. * *

The argument will be used to seed a {@link SplitMix64RandomGenerator}, whose output * will in turn be used to seed this generator. This approach makes “warmup” unnecessary, * and makes the probability of starting from a state * with a large fraction of bits set to zero astronomically small. * * @param seed a seed for this generator. */ @Override public void setSeed(final long seed) { final SplitMix64RandomGenerator r = new SplitMix64RandomGenerator(seed); s0 = r.nextLong(); s1 = r.nextLong(); } /** Sets the state of this generator. * *

The internal state of the generator will be reset, and the state array filled with the provided array. * * @param state an array of 2 longs; at least one must be nonzero. */ public void setState(final long[] state) { if (state.length != 2) throw new IllegalArgumentException("The argument array contains " + state.length + " longs instead of " + 2); s0 = state[0]; s1 = state[1]; } public static void main(String[] arg) { long n = Long.parseLong(arg[0]); long x = 0; ProgressLogger pl = new ProgressLogger(); XorShift128PlusRandomGenerator r = new XorShift128PlusRandomGenerator(); for(int k = 10; k-- != 0;) { pl.start("Measuring..."); for (long i = n; i-- != 0;) x ^= r.nextLong(); pl.done(n); if (x == 0) System.out.println(x); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy