using System.Runtime.CompilerServices; namespace PKHeX.Core { public struct Xoroshiro128Plus { public const ulong XOROSHIRO_CONST = 0x82A2B175229D6A5B; private ulong s0, s1; public Xoroshiro128Plus(ulong seed) { s0 = seed; s1 = XOROSHIRO_CONST; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static ulong RotateLeft(ulong x, int k) { return (x << k) | (x >> (64 - k)); } /// /// Gets the next random . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public ulong Next() { var _s0 = s0; var _s1 = s1; ulong result = _s0 + _s1; _s1 ^= _s0; // Final calculations and store back to fields s0 = RotateLeft(_s0, 24) ^ _s1 ^ (_s1 << 16); s1 = RotateLeft(_s1, 37); return result; } /// /// Gets a random value that is less than /// /// Maximum value (exclusive). Generates a bitmask for the loop. /// Random value public ulong NextInt(ulong MOD = 0xFFFFFFFF) { ulong mask = GetBitmask(MOD); ulong res; do { res = Next() & mask; } while (res >= MOD); return res; } /// /// Next Power of Two /// [MethodImpl(MethodImplOptions.AggressiveInlining)] private static ulong GetBitmask(ulong x) { x--; // comment out to always take the next biggest power of two, even if x is already a power of two x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; return x; } // ReSharper disable once NonReadonlyMemberInGetHashCode // ReSharper disable once NonReadonlyMemberInGetHashCode public override int GetHashCode() => (int)s0; public override bool Equals(object obj) => obj is Xoroshiro128Plus s && Equals(s); public bool Equals(Xoroshiro128Plus obj) => obj.s0 == s0 && obj.s1 == s1; public static bool operator ==(Xoroshiro128Plus left, Xoroshiro128Plus right) => left.Equals(right); public static bool operator !=(Xoroshiro128Plus left, Xoroshiro128Plus right) => !(left == right); } }