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

src.it.unimi.dsi.util.SplitMix64RandomGenerator 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) 2015-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.io.Serializable;
import java.util.SplittableRandom;

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

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

/** A fast, high-quality, non-splittable version of the SplitMix
 * pseudorandom number generator used by {@link SplittableRandom}. Due to
 * the fixed increment constant and to different strategies in generating finite ranges, the methods of this generator
 * are usually faster than those of {@link SplittableRandom}.
 *
 * 

Note that this generator has a relatively short period (264) so it should * not be used to generate very long sequences (the rule of thumb to have a period * greater than the square of the length of the sequence you want to generate). * * @see it.unimi.dsi.util * @see RandomGenerator * @see SplitMix64Random */ public class SplitMix64RandomGenerator extends AbstractRandomGenerator implements Serializable { private static final long serialVersionUID = 0L; /** 264 · φ, φ = (√5 − 1)/2. */ private static final long PHI = 0x9E3779B97F4A7C15L; /** The internal state of the algorithm (a Weyl generator using the {@link #PHI} as increment). */ private long x; /** Creates a new generator seeded using {@link Util#randomSeed()}. */ public SplitMix64RandomGenerator() { this(Util.randomSeed()); } /** Creates a new generator using a given seed. * * @param seed a seed for the generator. */ public SplitMix64RandomGenerator(final long seed) { setSeed(seed); } /* David Stafford's (http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html) * "Mix13" variant of the 64-bit finalizer in Austin Appleby's MurmurHash3 algorithm. */ private static long staffordMix13(long z) { z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L; z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL; return z ^ (z >>> 31); } /* David Stafford's (http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html) * "Mix4" variant of the 64-bit finalizer in Austin Appleby's MurmurHash3 algorithm. */ private static int staffordMix4Upper32(long z) { z = (z ^ (z >>> 33)) * 0x62A9D9ED799705F5L; return (int)(((z ^ (z >>> 28)) * 0xCB24D0A5C88C35B3L) >>> 32); } @Override public long nextLong() { return staffordMix13(x += PHI); } @Override public int nextInt() { return staffordMix4Upper32(x += PHI); } @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 = staffordMix13(x += PHI); 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 = staffordMix13(x += PHI) >>> 1); return t; } @Override public double nextDouble() { return (staffordMix13(x += PHI) >>> 11) * 0x1.0p-53; } @Override public float nextFloat() { return (staffordMix4Upper32(x += PHI) >>> 8) * 0x1.0p-24f; } @Override public boolean nextBoolean() { return staffordMix4Upper32(x += PHI) < 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 = staffordMix13(x += PHI); n-- != 0; bits >>= 8) bytes[--i] = (byte)bits; } } /** Sets the seed of this generator. * *

The seed will be passed through {@link HashCommon#murmurHash3(long)}. * * @param seed a seed for this generator. */ @Override public void setSeed(final long seed) { x = HashCommon.murmurHash3(seed); } /** Sets the state of this generator. * * @param state the new state for this generator (must be nonzero). */ public void setState(final long state) { x = state; } public static void main(String[] arg) { long n = Long.parseLong(arg[0]); long x = 0; ProgressLogger pl = new ProgressLogger(); SplitMix64RandomGenerator r = new SplitMix64RandomGenerator(); 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