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

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

package it.unimi.dsi.util;

/*
 * DSI utilities
 *
 * Copyright (C) 2015-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 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