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

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

package it.unimi.dsi.util;

/*
 * DSI utilities
 *
 * Copyright (C) 2012-2020 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.io.Serializable;

import it.unimi.dsi.Util;

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

/** A fast, high-quality 64-bit {@linkplain RandomGenerator pseudorandom number generator} described in “Some long-period random number generators using shift
 * and xors”, ANZIAM Journal 48, C188−C202, 2007. */

public class XorGensRandomGenerator extends AbstractRandomGenerator implements Serializable {
	private static final long serialVersionUID = 0L;
	private static final int WLEN = 64;
	private static final int R = 64;
	private static final int S = 53;
	private static final int A = 33;
	private static final int B = 26;
	private static final int C = 27;
	private static final int D = 29;
	private static final long WEYL = 0x61c8864680b583ebL;
	/** State of the Xorshift generator. */
	private long[] x = new long[R];
	private long weyl;
	private int i;

	/** Creates a new generator, initializing its seed with {@link Util#randomSeed()}. */
	public XorGensRandomGenerator() {
		this(Util.randomSeed());
	}

	/** Creates a new generator using a given seed.
	 *
	 * @param seed a nonzero seed for the generator (if zero, the generator will be seeded with -1).
	 */
	public XorGensRandomGenerator(final long seed) {
		setSeed(seed);
	}

	@Override
	public void setSeed(long seed) {
		long v = seed == 0 ? -1 : seed; /* v must be nonzero */
		for (int k = WLEN; k > 0; k--) { /* Avoid correlations for close seeds */
			v ^= v << 10;
			v ^= v >>> 15; /* Recurrence has period 2**wlen-1 */
			v ^= v << 4;
			v ^= v >>> 13; /* for wlen = 32 or 64 */
		}

		for (int k = 0; k < R; k++) { /* Initialise circular array */
			v ^= v << 10;
			v ^= v >>> 15;
			v ^= v << 4;
			v ^= v >>> 13;
			x[k] = v;
		}

		i = R - 1;

		long t;
		for (int k = 4 * R; k > 0; k--) { /* Discard first 4*r results */
			t = x[i = (i + 1) & (R - 1)];
			t ^= t << A;
			t ^= t >>> B;
			v = x[(i + (R - S)) & (R - 1)];
			v ^= v << C;
			v ^= v >>> D;
			x[i] = t ^ v;
		}
	}

	@Override
	public long nextLong() {
		long t, v;
		t = x[i = (i + 1) & (R - 1)]; /* Assumes that r is a power of two */
		v = x[(i + (R - S)) & (R - 1)]; /* Index is (i-s) mod r */
		t ^= t << A;
		v ^= v << C;
		t ^= t >>> B; /* (I + L^a)(I + R^b) */
		v ^= v >>> D; /* (I + L^c)(I + R^d) */
		x[i] = (v ^= t); /* Update circular array */
		weyl += WEYL;
		return (v + (weyl ^ (weyl >>> 27)));
	}

	@Override
	public int nextInt() {
		return (int)nextLong();
	}

	@Override
	public int nextInt(final int n) {
		return (int)nextLong(n);
	}

	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) {
		for (int i = bytes.length; i != 0;)
			for (long bits = nextLong(), n = Math.min(i, 8); n-- != 0; bits >>= 8) bytes[--i] = (byte)bits;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy