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

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

Go to download

The DSI utilities are a mishmash of classes accumulated during the last twenty years in projects developed at the DSI (Dipartimento di Scienze dell'Informazione, i.e., Information Sciences Department), now DI (Dipartimento di Informatica, i.e., Informatics Department), of the Universita` degli Studi di Milano.

There is a newer version: 2.7.3
Show newest version
package it.unimi.dsi.util;

/*
 * DSI utilities
 *
 * Copyright (C) 2013-2019 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 java.util.Random;

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

/** A fast, high-quality {@linkplain Random pseudorandom number generator} that
 * combines a long-period instance of George Marsaglia's Xorshift generators (described in “Xorshift RNGs”, Journal of
 * Statistical Software, 8:1−6, 2003) with a multiplication.
 *
 * @see it.unimi.dsi.util
 * @see Random
 * @deprecated Please use {@link XorShift1024StarPhiRandom} instead.
 */
@Deprecated
public class XorShift1024StarRandom extends Random {
	private static final long serialVersionUID = 1L;

	/** The internal state of the algorithm. */
	private long[] s;
	private int p;

	/** Creates a new generator seeded using {@link Util#randomSeed()}. */
	public XorShift1024StarRandom() {
		this(Util.randomSeed());
	}

	/** Creates a new generator using a given seed.
	 *
	 * @param seed a seed for the generator.
	 */
	public XorShift1024StarRandom(final long seed) {
		super(seed);
	}

	@Override
	protected int next(final int bits) {
		return (int)(nextLong() >>> 64 - bits);
	}

	@Override
	public long nextLong() {
		final long s0 = s[p];
		long s1 = s[p = (p + 1) & 15];
		s1 ^= s1 << 31;
		return (s[p] = s1 ^ s0 ^ (s1 >>> 11) ^ (s0 >>> 30)) * 1181783497276652981L;
	}

	@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("illegal bound " + n + " (must be positive)");
		long t = nextLong();
		final long nMinus1 = n - 1;
		// Shortcut for powers of two
		if ((n & nMinus1) == 0) return t & nMinus1;
		// Rejection-based algorithm to get uniform integers in the general case
		for (long u = t >>> 1; u + nMinus1 - (t = u % n) < 0; u = nextLong() >>> 1);
		return t;
	}

	@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[] = { 0x84242f96eca9c41dL,
			0xa3c65b8776f96855L, 0x5b34a39f070b5837L, 0x4489affce4f31a1eL,
			0x2ffeeb0a48316f40L, 0xdc2d9891fe68c022L, 0x3659132bb12fea70L,
			0xaac17d8efa43cab8L, 0xc4cb815590989b13L, 0x5ee975283d71c93bL,
			0x691548c86c1bd540L, 0x7910c41d10a1e6a5L, 0x0b5fc64563b3e2a8L,
			0x047f7684e9fc949dL, 0xb99181f2d8f685caL, 0x284600e3f30e38c3L
	};

	/** The jump function for this generator. It is equivalent to 2512
	 * calls to {@link #nextLong()}; it can be used to generate 2512
	 * non-overlapping subsequences for parallel computations. */

	public void jump() {
		final long[] t = new long[16];
		for (int i = 0; i < JUMP.length; i++)
			for (int b = 0; b < 64; b++) {
				if ((JUMP[i] & 1L << b) != 0) for (int j = 0; j < 16; j++)
					t[j] ^= s[(j + p) & 15];
				nextLong();
			}

		for (int j = 0; j < 16; j++)
			s[(j + p) & 15] = t[j];
	}

    /**
     * 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 XorShift1024StarRandom split() {
		final XorShift1024StarRandom split = new XorShift1024StarRandom();
		for(int i = s.length; i-- != 0;) split.s[i] = HashCommon.murmurHash3(s[i]);
		split.p = p;
		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) { if (s == null) s = new long[16]; p = 0; final SplitMix64RandomGenerator r = new SplitMix64RandomGenerator(seed); for(int i = s.length; i-- != 0;) s[i] = 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 16 longs; at least one must be nonzero. * @param p the internal index. */ public void setState(final long[] state, final int p) { if (state.length != s.length) throw new IllegalArgumentException("The argument array contains " + state.length + " longs instead of " + s.length); System.arraycopy(state, 0, s, 0, s.length); this.p = p; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy