// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; namespace osu.Game.Rulesets.Catch.MathUtils { /// /// A PRNG specified in http://heliosphan.org/fastrandom.html. /// public class FastRandom { private const double int_to_real = 1.0 / (int.MaxValue + 1.0); private const uint int_mask = 0x7FFFFFFF; private const uint y_initial = 842502087; private const uint z_initial = 3579807591; private const uint w_initial = 273326509; private uint x, y = y_initial, z = z_initial, w = w_initial; public FastRandom(int seed) { x = (uint)seed; } public FastRandom() : this(Environment.TickCount) { } /// /// Generates a random unsigned integer within the range [, ). /// /// The random value. public uint NextUInt() { uint t = x ^ (x << 11); x = y; y = z; z = w; return w = w ^ (w >> 19) ^ t ^ (t >> 8); } /// /// Generates a random integer value within the range [0, ). /// /// The random value. public int Next() => (int)(int_mask & NextUInt()); /// /// Generates a random integer value within the range [0, ). /// /// The upper bound. /// The random value. public int Next(int upperBound) => (int)(NextDouble() * upperBound); /// /// Generates a random integer value within the range [, ). /// /// The lower bound of the range. /// The upper bound of the range. /// The random value. public int Next(int lowerBound, int upperBound) => (int)(lowerBound + NextDouble() * (upperBound - lowerBound)); /// /// Generates a random integer value within the range [, ). /// /// The lower bound of the range. /// The upper bound of the range. /// The random value. public int Next(double lowerBound, double upperBound) => (int)(lowerBound + NextDouble() * (upperBound - lowerBound)); /// /// Generates a random double value within the range [0, 1). /// /// The random value. public double NextDouble() => int_to_real * Next(); private uint bitBuffer; private int bitIndex = 32; /// /// Generates a reandom boolean value. Cached such that a random value is only generated once in every 32 calls. /// /// The random value. public bool NextBool() { if (bitIndex == 32) { bitBuffer = NextUInt(); bitIndex = 1; return (bitBuffer & 1) == 1; } bitIndex++; return ((bitBuffer >>= 1) & 1) == 1; } } }